# Dynamic configuration from the browser **Prerequisites** Read the [developing a data source extension article](/frontend-development/developing-a-data-source-extension.md). In the [developing a data source extension article](/frontend-development/developing-a-data-source-extension.md), we described how you could create a data source and then configure it in the Studio. But, you might need to add additional dynamic configuration options in the browser when requesting a data source. For example, for pagination or a user-provided search string. In this article, we'll show you how to do that. For our example, we'll continue using our Star Wars API, this time for characters. ## Access query parameters in the extension Our data source schema to return a list of all the Star Wars characters would look like this: ```json title="schema.json" { "customDataSourceType": "example/star-wars-character-search", "name": "Star wars character search", "category": "Content", "icon": "source", "schema": [] } ``` You can store the `schema.json` file wherever you like, because it's only required in the Studio and not by the code. The parameters for the custom data source are added to the query of the page URL (for example `pageSize` in `https://yoursite.com/page?pageSize=20`). You can access these parameters as `context.request.query` inside the extension implementation: ```javascript title="index.js" import { DataSourceConfiguration, DataSourceContext, DataSourceResult } from '@frontastic/extension-types'; import axios from 'axios'; export default { 'data-sources': { 'example/star-wars-character-search': async ( config: DataSourceConfiguration, context: DataSourceContext, ): Promise => { const pageSize = context.request.query.pageSize || 10; const after = context.request.query.cursor || null; return await axios .post('https://swapi-graphql.netlify.app/.netlify/functions/index', { query: `{ allPeople(first: ${pageSize}, after: ${JSON.stringify(after)}) { totalCount pageInfo { hasNextPage endCursor } people { id name species { name } } } }`, }) .then( (response): DataSourceResult => { return { dataSourcePayload: response.data?.data?.allPeople || {}, } as DataSourceResult; }, ) .catch((reason) => { return { dataSourcePayload: { ok: false, error: reason.toString(), }, } as DataSourceResult; }); } } }; ``` ## Set parameters in the component You can then use the router inside a Frontend component to change the query parameters: ```javascript import React from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; const StarWarsCharacterSearchTastic = ({ data }) => { const { totalCount, pageInfo, people } = data.data.dataSource; const router = useRouter(); const { slug, ...queryWithoutSlug } = router.query; return (

Star Wars Characters

{totalCount} total characters found

{people.map((character) => (

{character.name}

{character.species !== null && (

Species: {character.species.name}

)}
))} {pageInfo.hasNextPage && (
Next Page
)}
); }; export default StarWarsCharacterSearchTastic; ``` ## Clash of parameters This query is shared between all the data sources available on the same page. So, you need to ensure you use query parameter names that don't clash between the different data sources. If 2 or more data sources use the same query parameter name, or if multiple instances of the data source are used on the same page with the same query parameter name, they'll clash. The `dataSourceId` can be used to distinguish different data sources since it's guaranteed to have a unique value for each data source. ## Related pages - [Area overview page with navigation](/frontend-development.md) - [Previous page: Developing a dynamic page extension](/frontend-development/developing-a-dynamic-page-extension.md) - [Next page: Dynamic filters for data sources and dynamic pages](/frontend-development/dynamic-filters-for-data-sources-and-dynamic-pages.md)