Specify configuration options
Your connector must define the configuration options that a user will need to complete to use your extension and add an instance of your data source type to their data layer or site with visual editing enabled.
For example, you may want the user to enter the ID and API key for their CMS instance. You can use these options to request other dynamic or sensitive pieces of data that should be kept out of your extension code.
First you need to define the configuration options and then you need to create extension UI for those options. The Netlify UI will render the extension UI for users to fill out and configure a data source using your extension.
Required options
All data sources in Connect and the visual editor require name
, prefix
, and instanceID
configuration options. All three are string values.
The first two, name
and prefix
, should be required options. They allow users to connect one data layer to multiple data sources of the same type, such as two instances of your custom data source. When Netlify generates the GraphQL schema, we will add the prefix to all GraphQL types from that data source.
The third, instanceID
, should be optional. This option enables users to add cross-references in the Netlify UI to link between data sources of different types. For example, between a Drupal data source and a Contentful data source. Note that these cross-references are different from cross-reference fields that your data source can resolve.
Define options
You need to define the configuration options using extension.addConnector({ defineOptions: fn })
.
Netlify uses these options and their types for validation. The configuration options are also made available to the other Connector APIs so that you can use the values in your connector. You can access the values in connector.model()
, connector.sync()
, extension.addConnector({ initState: fn })
, and connector.proxySchema()
using options
:
For example:
connector.model(async ({ define, options }) => { const cmsSchema = await fetchSchema(options.url, options.apiToken); // ...});
connector.sync(async ({ models, isInitialSync, options }) => { const cmsUrl = options.url; // ...});
You have the option to pass these values in manually while working on local development, as outlined below.
To define configuration options for your connector, use extension.addConnector({ defineOptions: fn })
to define and return a zod.object()
that includes a property for each configuration option. Learn more about the Zod schema.
Option properties
Netlify supports the following properties:
- option type: defined using the related zod method, for example
zod.string()
. We currently support objects, strings, numbers, and boolean values. Arrays are not supported. optional()
: (optional) marks the option as optional
For example, to define required name
, prefix
, and apiToken
options, and an optional pageLimit
option, you would do the following:
extension.addConnector({ defineOptions: ({ zod }) => { return zod.object({ name: zod.string(), prefix: zod.string(), instanceID: zod.string().optional(), apiToken: zod.string(), pageLimit: zod.string().optional(), }); }})
Add extension UI
Use this section to understand the components you need for extension UI. The following section will help you auto-generate it using the needed components.
The extension UI should have a surface for Connect settings, visual editor settings, or both.
After you define configuration options using extension.addConnector
, you need to create extension UI surfaces that Netlify will render when a user adds a new data source in the Netlify UI.
Each surface should include a form that the user will complete to configure a data source using your extension. The form should include fields for all of the configuration options that your connector expects, including the required name
and prefix
fields.
To handle the form submissions, your extension will also require an endpoint that will send the form data to createConnectConfiguration
.
For an example of how to define a configuration settings form, review the add a new surface section of our extension UI docs.
You can preview the form while you work by following the instructions on how to develop extension UI locally.
Auto-generated extension UI
Limitations of auto-generated extension UI
Auto-generated forms only work with the object, string, number, and boolean Zod types. If you need something more complex, use the next section on how to manually generated your extension UI.
Follow these steps to take advantage of the auto-generated extension UI. These components will also generated the required fields for any connector (name
and prefix
).
- Set up your trpc router
import { initTRPC } from "@trpc/server";import { type Context } from "@netlify/sdk/ui/functions/trpc";
const trpc = initTRPC.context<Context>().create();
export const router = trpc.router;export const procedure = trpc.procedure;
- For your endpoints use the
createConnectRouter
tRPC router helper.
import { router } from "./trpc.js";import { createConnectRouter } from "@netlify/sdk/ui/functions/trpc";import { ConnectorConfigurationSchema } from "../schema/connector-configuration.js";
export const appRouter = router({ connect: createConnectRouter({ schema: ConnectorConfigurationSchema }),});
export type AppRouter = typeof appRouter;
- To add additional metadata to your extension UI form fields use a
configFieldsMeta
object.
import * as zod from "zod";
import { type SmartFormFieldsMetadata } from "@netlify/sdk/ui/react/components";
export const ConnectorConfigurationSchema = zod.object({ apiUrl: zod.string().trim().min(1).default("https://api.example.com"), apiToken: zod.string().trim().min(1).default("exampleToken"), instanceID: zod.string().optional()});
export const configFieldsMeta: SmartFormFieldsMetadata = { apiUrl: { label: "API URL", helpText: "The URL of the API to connect to", }, apiToken: { label: "API Token", helpText: "The token to authenticate with the API", secret: true }, instanceID: { label: "Instance ID", helpText: "The ID of the instance to connect to", },};
export type ConnectorSettings = Zod.output<typeof ConnectorConfigurationSchema>;
- Finally, to tie it all together, use the
ConnectedConnectForm
(how do I link to reference docs?) component for yourConnectConfigurationSurface
.
import { Card, CardTitle, ConnectConfigurationSurface, ConnectedConnectForm } from "@netlify/sdk/ui/react/components";import { useNetlifySDK } from "@netlify/sdk/ui/react";import { configFieldsMeta, ConnectorConfigurationSchema } from "../../schema/connector-configuration";import { trpc } from "../trpc.js";
export const ConnectConfiguration = () => { const sdk = useNetlifySDK();
return ( <ConnectConfigurationSurface> <Card> <CardTitle>{sdk.extension.name}</CardTitle> <ConnectedConnectForm fieldsMeta={configFieldsMeta} schema={ConnectorConfigurationSchema} connect={trpc.connect} /> </Card> </ConnectConfigurationSurface> );};
Set configuration values for local development
During local development, you can set values for the connector’s configuration options as if a user had entered them in the Netlify UI.
To do this, add the localDevOptions
property to the object that you pass to the addConnector
method, and add a value for each configuration option on the localDevOptions
object.
For example:
import { NetlifyExtension } from "@netlify/sdk";
const extension = new NetlifyExtension();
const connector = extension.addConnector({ typePrefix: "Example", supports: { connect: true, }, // localDevOptions emulates a user setting configuration // options in the Netlify UI. localDevOptions only runs // during local development. localDevOptions: { exampleConfigOption: "Hello!", instanceID: "MarketingData" }, defineOptions: ({ zod }) => { return zod.object({ exampleConfigOption: zod.string(), instanceID: zod.string().optional(), }); }});
export { extension };