Customize the Sign Up Form
Customize the sign up form by adding new fields or modifying existing ones.
Before you start
The next instructions assume that you have a working application that uses SuperTokens for authentication. If not, please refer to the quickstart guide and then return here.
Add extra fields
To include more fields in the sign up form, you need to first update both the frontend and backend configuration. Then, when the sing up payload arrives on the backend, you should add a way to persist those values.
1. Add the new fields to the UI
You first need to add the new fields to your sign up interface. Given that you are using a custom implementation, the steps vary based on your code. After you have updated the form, ensure that the submit action follows the next example.
import { signUp } from "supertokens-web-js/recipe/emailpassword";
async function signUpClicked(email: string, password: string, name: string, age: number, country: string) {
let response = await signUp({
formFields: [
{
id: "email",
value: email,
},
{
id: "password",
value: password,
},
{
id: "name",
value: name,
},
{
id: "age",
value: age + "",
},
{
id: "country",
value: country,
},
],
});
// ... rest of the code
}async function signUpClicked(email: string, password: string, name: string, age: number, country: string) {
let response = await supertokensEmailPassword.signUp({
formFields: [
{
id: "email",
value: email,
},
{
id: "password",
value: password,
},
{
id: "name",
value: name,
},
{
id: "age",
value: age + "",
},
{
id: "country",
value: country,
},
],
});
// ... rest of the code
}curl --location --request POST '<YOUR_API_DOMAIN>/auth/signup'
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"formFields": [{
"id": "email",
"value": "john@example.com"
}, {
"id": "password",
"value": "somePassword123"
}, {
id: "name",
value: "John Doe"
}, {
id: "age",
value: 27
}, {
id: "country",
value: "USA"
}]
}'import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "name",
label: "Full name",
placeholder: "First name and last name",
},
{
id: "age",
label: "Your age",
placeholder: "How old are you?",
},
{
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true,
},
],
},
},
}),
Session.init(),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "name",
label: "Full name",
placeholder: "First name and last name",
},
{
id: "age",
label: "Your age",
placeholder: "How old are you?",
},
{
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true,
},
],
},
},
}),
supertokensUISession.init(),
],
});Create custom components
By default, the new fields use input elements.
To enable more complex fields you can create your own custom components.
Set the inputComponent property for each field that you want to customize.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "select-dropdown",
label: "Select Dropdown",
inputComponent: ({ value, name, onChange }) => (
<div data-supertokens="inputContainer">
<div data-supertokens="inputWrapper ">
<select
style={{
border: "unset",
borderRadius: "6px",
height: "32px",
backgroundColor: "#fafafa",
color: "#757575",
letterSpacing: "1.2px",
fontSize: "14px",
width: "100%",
marginRight: "25px",
padding: "1px 0 1px 10px",
}}
value={value}
name={name}
onChange={(e) => onChange(e.target.value)}
>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
</div>
</div>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
nonOptionalErrorMsg: "You must accept the terms and conditions",
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
marginBottom: " -12px",
}}
>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>
I agree to the{" "}
<a href="https://supertokens.com/legal/terms-and-conditions" data-supertokens="link">
Terms and Conditions
</a>
</span>
</div>
),
},
],
},
},
}),
Session.init(),
],
});2. Include the extra fields in the backend configuration
Change the Backend SDK initialization call to ensure that the system processes the new fields when a new user registers.
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [
{
id: "name",
},
{
id: "age",
},
{
id: "country",
optional: true,
},
],
},
}),
Session.init({
/* ... */
}),
],
});import (
"github.com/supertokens/supertokens-golang/recipe/emailpassword"
"github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
countryOptional := true
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
emailpassword.Init(&epmodels.TypeInput{
SignUpFeature: &epmodels.TypeInputSignUp{
FormFields: []epmodels.TypeInputFormField{
{
ID: "name",
},
{
ID: "age",
},
{
ID: "country",
Optional: &countryOptional,
},
},
},
}),
},
})
}from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import emailpassword, session
from supertokens_python.recipe.emailpassword import InputFormField
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
emailpassword.init(
sign_up_feature=emailpassword.InputSignUpFeature(
form_fields=[InputFormField(id='name'), InputFormField(id='age'), InputFormField(id='country', optional=True)]
)
),
session.init()
]
)3. Save the values after a successful sign up
Use the signUpPOST API function to process the field values and persist them.
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
signUpPOST: async function (input) {
if (originalImplementation.signUpPOST === undefined) {
throw Error("Should never come here");
}
// First we call the original implementation of signUpPOST.
let response = await originalImplementation.signUpPOST(input);
// Post sign up response, we check if it was successful
if (response.status === "OK") {
// These are the input form fields values that the user used while signing up
let formFields = input.formFields;
}
return response;
},
};
},
},
}),
Session.init({
/* ... */
}),
],
});import (
"github.com/supertokens/supertokens-golang/recipe/emailpassword"
"github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
emailpassword.Init(&epmodels.TypeInput{
Override: &epmodels.OverrideStruct{
APIs: func(originalImplementation epmodels.APIInterface) epmodels.APIInterface {
// First we copy the original implementation func
originalSignUpPOST := *originalImplementation.SignUpPOST
(*originalImplementation.SignUpPOST) = func(formFields []epmodels.TypeFormField, tenantId string, options epmodels.APIOptions, userContext supertokens.UserContext) (epmodels.SignUpPOSTResponse, error) {
resp, err := originalSignUpPOST(formFields, tenantId, options, userContext)
if err != nil {
return epmodels.SignUpPOSTResponse{}, err
}
if resp.OK != nil {
// sign up was successful
// TODO: You can now read the formFields from the input params
}
return resp, err
}
return originalImplementation
},
},
}),
},
})
}from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import emailpassword, session
from supertokens_python.recipe.emailpassword.interfaces import (
APIInterface,
APIOptions,
SignUpPostOkResult,
)
from supertokens_python.recipe.emailpassword.types import FormField
from typing import List, Dict, Any, Union
from supertokens_python.recipe.session.interfaces import SessionContainer
def override_email_password_apis(original_implementation: APIInterface):
original_sign_up_post = original_implementation.sign_up_post
async def sign_up_post(
form_fields: List[FormField],
tenant_id: str,
session: Union[SessionContainer, None],
should_try_linking_with_session_user: Union[bool, None],
api_options: APIOptions,
user_context: Dict[str, Any],
):
# First we call the original implementation of sign_up_post.
response = await original_sign_up_post(
form_fields,
tenant_id,
session,
should_try_linking_with_session_user,
api_options,
user_context,
)
# Post sign up response, we check if it was successful
if isinstance(response, SignUpPostOkResult):
pass
# TODO: use the input form fields values for custom logic
return response
original_implementation.sign_up_post = sign_up_post
return original_implementation
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework="...",
recipe_list=[
emailpassword.init(
override=emailpassword.InputOverrideConfig(
apis=override_email_password_apis
)
),
session.init(),
],
)Customize each form field
Modify labels and placeholders
To change the labels and placeholders of the fields, update the formFields property, in the recipe configuration.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "customFieldName",
placeholder: "Custom value",
},
],
},
},
}),
Session.init(),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "customFieldName",
placeholder: "Custom value",
},
],
},
},
}),
supertokensUISession.init(),
],
});Set default values
Add a getDefaultValue option to the formFields configuration to set default values.
Keep in mind that the function needs to return a string.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "Your Email",
getDefaultValue: () => "john.doe@gmail.com",
},
{
id: "name",
label: "Full name",
getDefaultValue: () => "John Doe",
},
],
},
},
}),
Session.init(),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "Your Email",
getDefaultValue: () => "john.doe@gmail.com",
},
{
id: "name",
label: "Full name",
getDefaultValue: () => "John Doe",
},
],
},
},
}),
supertokensUISession.init(),
],
});Change the optional error message
When you try to submit the login form without filling in the required fields, the UI, by default, shows an error stating that the Field is not optional.
To customize this message set the nonOptionalErrorMsg property to a custom string.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "Your Email",
placeholder: "Email",
nonOptionalErrorMsg: "Please add your email",
},
{
id: "name",
label: "Full name",
placeholder: "Name",
nonOptionalErrorMsg: "Full name is required",
},
],
},
},
}),
Session.init(),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "Your Email",
placeholder: "Email",
nonOptionalErrorMsg: "Please add your email",
},
{
id: "name",
label: "Full name",
placeholder: "Name",
nonOptionalErrorMsg: "Full name is required",
},
],
},
},
}),
supertokensUISession.init(),
],
});Change the field order
To customize the order of fields in your sign up form, override the EmailPasswordSignUpForm component.
Use the next example as a reference.
import React from "react";
import { SuperTokensWrapper } from "supertokens-auth-react";
import { EmailPasswordComponentsOverrideProvider } from "supertokens-auth-react/recipe/emailpassword";
function App() {
return (
<SuperTokensWrapper>
<EmailPasswordComponentsOverrideProvider
components={{
EmailPasswordSignUpForm_Override: ({ DefaultComponent, ...props }) => {
return (
<DefaultComponent
{...props}
formFields={[
props.formFields.find(({ id }) => id === "name")!,
props.formFields.find(({ id }) => id === "email")!,
props.formFields.find(({ id }) => id === "password")!,
]}
/>
);
},
}}
>
{/* Rest of the JSX */}
</EmailPasswordComponentsOverrideProvider>
</SuperTokensWrapper>
);
}
export default App;import React from "react";
import { SuperTokensWrapper } from "supertokens-auth-react";
import { EmailPasswordPreBuiltUI } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";
import { EmailPasswordComponentsOverrideProvider } from "supertokens-auth-react/recipe/emailpassword";
import { getRoutingComponent, canHandleRoute } from "supertokens-auth-react/ui";
function App() {
if (canHandleRoute([EmailPasswordPreBuiltUI])) {
return (
<EmailPasswordComponentsOverrideProvider
components={{
EmailPasswordSignUpForm_Override: ({ DefaultComponent, ...props }) => {
return (
<DefaultComponent
{...props}
formFields={[
props.formFields.find(({ id }) => id === "name")!,
props.formFields.find(({ id }) => id === "email")!,
props.formFields.find(({ id }) => id === "password")!,
]}
/>
);
},
}}
>
{getRoutingComponent([EmailPasswordPreBuiltUI])}
</EmailPasswordComponentsOverrideProvider>
);
}
return <SuperTokensWrapper>{/* Rest of the JSX */}</SuperTokensWrapper>;
}
export default App;Change field validators
1. Update the frontend configuration
Add a validate method to any of your formFields.
The following example shows how to add age verification to the form:
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "name",
label: "Full name",
placeholder: "First name and last name",
},
{
id: "age",
label: "Your age",
placeholder: "How old are you?",
optional: true,
/* Validation method to make sure that age is above 18 */
validate: async (value) => {
if (parseInt(value) > 18) {
return undefined; // means that there is no error
}
return "You must be over 18 to register";
},
},
{
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true,
},
],
},
},
}),
Session.init(),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "name",
label: "Full name",
placeholder: "First name and last name",
},
{
id: "age",
label: "Your age",
placeholder: "How old are you?",
optional: true,
/* Validation method to make sure that age is above 18 */
validate: async (value) => {
if (parseInt(value) > 18) {
return undefined; // means that there is no error
}
return "You must be over 18 to register";
},
},
{
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true,
},
],
},
},
}),
supertokensUISession.init(),
],
});2. Update the backend configuration
Add validate functions to each of the form fields, in the backend SDK initialization call.
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [
{
id: "name",
},
{
id: "age",
/* Validation method to make sure that age >= 18 */
validate: async (value, tenantId) => {
if (parseInt(value) >= 18) {
return undefined; // means that there is no error
}
return "You must be over 18 to register";
},
},
{
id: "country",
optional: true,
},
],
},
}),
Session.init({}),
],
});import (
"strconv"
"github.com/supertokens/supertokens-golang/recipe/emailpassword"
"github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
countryOptional := true
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
emailpassword.Init(&epmodels.TypeInput{
SignUpFeature: &epmodels.TypeInputSignUp{
FormFields: []epmodels.TypeInputFormField{
{
ID: "name",
},
{
ID: "age",
Validate: func(value interface{}, tenantId string) *string {
age, _ := strconv.Atoi(value.(string))
if age >= 18 {
// return nil to indicate success
return nil
}
err := "You must be over 18 to register"
return &err
},
},
{
ID: "country",
Optional: &countryOptional,
},
},
},
}),
},
})
}from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import emailpassword
from supertokens_python.recipe.emailpassword import InputFormField
from typing import Any
async def validate_age(value: Any, tenant_id: str):
# Validation method to make sure that age >= 18
if int(value) >= 18:
return None # means that there is no error
return 'You must be over 18 to register'
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
emailpassword.init(
sign_up_feature=emailpassword.InputSignUpFeature(
form_fields=[
InputFormField(id='name'),
InputFormField(id='age', validate=validate_age),
InputFormField(id='country', optional=True)
]
)
)
]
)Change the default email and password validators
By default, SuperTokens adds an email and a password validator to the sign up form.
- The default email validator makes sure that the provided email is in the correct email format.
- The default password validator makes sure that the provided password:
- has a minimum of 8 characters.
- contains at least one lowercase character
- contains at least one number
To add your own validators follow the steps described initially in this section.
Here is an example of what you need to change.
1. Update the frontend configuration
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
{
id: "password",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
],
},
},
}),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUIEmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [
{
id: "email",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
{
id: "password",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
],
},
},
}),
],
});1. Update the backend configuration
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [
{
id: "email",
validate: async (value, tenantId) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
{
id: "password",
validate: async (value, tenantId) => {
// Your own validation returning a string or undefined if no errors.
return "...";
},
},
],
},
}),
],
});import (
"github.com/supertokens/supertokens-golang/recipe/emailpassword"
"github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
emailpassword.Init(&epmodels.TypeInput{
SignUpFeature: &epmodels.TypeInputSignUp{
FormFields: []epmodels.TypeInputFormField{
{
ID: "email",
Validate: func(value interface{}, tenantId string) *string {
// Your own validation returning a string or nil if no errors.
return nil
},
},
{
ID: "password",
Validate: func(value interface{}, tenantId string) *string {
// Your own validation returning a string or nil if no errors.
return nil
},
},
},
},
}),
},
})
}from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import emailpassword
from supertokens_python.recipe.emailpassword import InputFormField
from typing import Any
async def validate_password(value: Any, tenant_id: str):
pass # TODO
async def validate_email(value: Any, tenant_id: str):
pass # TODO
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
emailpassword.init(
sign_up_feature=emailpassword.InputSignUpFeature(
form_fields=[
InputFormField(id='password', validate=validate_password),
InputFormField(id='email', validate=validate_email)
]
)
)
]
)Add terms of service and privacy policy links
To add “Terms of service” and “Privacy policy” links to your sign up page add the links in the frontend SDK initialization call. Based on the provided configuration the data renders in the following way:
- Provided both links: “By signing up, you agree to the Terms of Service and Privacy Policy”
- Provided only Terms of service link: “By signing up, you agree to the Terms of Service”
- Provided only Privacy policy link: “By signing up, you agree to the Privacy Policy”
import SuperTokens from "supertokens-auth-react";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
termsOfServiceLink: "https://example.com/terms-of-service",
privacyPolicyLink: "https://example.com/privacy-policy",
recipeList: [
/* ... */
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
termsOfServiceLink: "https://example.com/terms-of-service",
privacyPolicyLink: "https://example.com/privacy-policy",
recipeList: [
/* ... */
],
});