Skip to main content

Manifest

Every Appnest app includes a manifest.json at the project root. It tells the platform where the UI runs, which server functions exist, which events they handle, what to collect at install via installation_parameters, OAuth needs, and which outbound URLs are allowed.

This page is the canonical reference for that file: required shape, rules, field definitions, and a full structural example. Keep the manifest aligned with app-backend/server.js—every backend_api_functions key and every event handler must name a real export from that file.


Structure (summary)

LevelKeys
Top-levelOnly platform_version, parent_product, and product_config.
product_config.<product>frontend_locations, whitelisted_domains, event_listener_functions, backend_api_functions, installation_parameters, oauth_config.
  • <product> must match parent_product (e.g. surveysparrow).
  • Do not duplicate the product-level keys at the top level.
  • product_config may contain more than one product key in multi-product setups; each app still follows the same nested shape per key.

Use installation_parameters for install-time fields (values the admin provides when installing the app).


Rules

1. Event listeners

Declare handlers under product_config.<product>.event_listener_functions. Each object’s handler value must match an export from app-backend/server.js.

2. Scheduled functions

Scheduled jobs are configured in code (for example via $schedule) and validated at runtime. Ensure scheduler usage aligns with Scheduler (and platform) expectations; the manifest does not replace those declarations.

3. Backend API functions

Declare invokable server functions under product_config.<product>.backend_api_functions. Each key must match an export from app-backend/server.js. Use timeout (seconds) when the platform supports it.

4. OAuth

Apps that use OAuth MUST declare product_config.<product>.oauth_config with provider id(s) and the fields the platform expects (client_id, client_secret, authorize_url, token_url, and options such as scope).

5. Consistency

The manifest must reflect only real exports from app-backend/server.js. Mismatches between manifest and code are invalid.


Schema

Top-level keys

KeyTypeDescription
platform_versionstringPlatform version string the tooling expects (see templates and CLI output for the current value).
parent_productstringParent product id (e.g. "surveysparrow").
product_configobjectMap of product id → config object. Keys should match products you target; primary app config usually sits under parent_product.

product_config.<product>

All product-specific manifest content lives under one object per product id. Prefer snake_case for manifest keys.

KeyTypeDescription
frontend_locationsobjectWhere the app is rendered. See Product Location.
whitelisted_domainsstring[]Regex strings for allowed outbound URLs. See whitelisted_domains.
event_listener_functionsobjectPlatform events → { handler }. See event_listener_functions.
backend_api_functionsobjectExported function names → options (e.g. timeout). See backend_api_functions.
installation_parametersobjectInstall-time parameters. See installation_parameters.
oauth_configobjectOAuth providers and credentials shape. See oauth_config.

frontend_locations

Under product_config.<product>.frontend_locations. For screenshots and where each location id appears in the product UI, see Product Location.

"frontend_locations": {
"full_page_app": {
"url": "index.html",
"icon": "styles/images/icon.svg"
}
}
  • Keys: Location ids where the product embeds your app, for example full_page_app, builder_integrations_list, response_details, contact_details, new_survey_shares, contact_import, response_import, home_navigation, home_left_panel, survey_settings, and other ids the platform defines for your product.
  • url: Relative path to the HTML entry (often index.html).
  • icon: Optional; relative path to an icon asset (e.g. SVG), typically used where the UI shows an app tile—use a square image (commonly 64×64) unless your team specifies otherwise.

whitelisted_domains

Under product_config.<product>.whitelisted_domains.

  • Array of strings, usually regex patterns for allowed outbound URLs.
  • Escape dots in hostnames when needed (e.g. https://api\\.surveysparrow\\.com(/.*)?).
  • Include product domains, APIs, webhooks (e.g. Slack), and test hosts your app calls.

event_listener_functions

Under product_config.<product>.event_listener_functions.

"event_listener_functions": {
"onSubmissionComplete": {
"handler": "onSubmissionComplete"
},
"onContactCreate": {
"handler": "onSubmissionComplete"
}
}
  • Keys: Platform event names.
  • Values: { "handler": "<exportedFunctionName>" }.
  • The handler receives { payload } (shape depends on the event).
  • Multiple events, one function: reuse the same handler string (second example above).

backend_api_functions

Under product_config.<product>.backend_api_functions.

"backend_api_functions": {
"getMappings": { "timeout": 10 },
"saveMapping": { "timeout": 15 }
}
  • Keys: Names exported from app-backend/server.js.
  • Values: Object with optional timeout (number, seconds). Other options may exist per platform.

installation_parameters

Under product_config.<product>.installation_parameters.

"installation_parameters": {
"surveysparrow_api_key": {
"data-bind": "product.api_key",
"display_name": "SurveySparrow API Key",
"description": "Enter your SurveySparrow API key. You can find it under Settings → Apps & Integrations.",
"required": true,
"secure": true,
"type": "api_key"
},
"survey_api_base_url": {
"display_name": "SurveySparrow API base URL",
"description": "Optional. For example https://api.surveysparrow.com or your regional endpoint.",
"type": "text",
"required": false,
"default_value": "https://api.surveysparrow.com"
}
}

Each entry under installation_parameters is keyed by your parameter id (e.g. surveysparrow_api_key). Object fields:

FieldRequiredValues / notes
(parameter key)YesString key identifying this install field. Your app reads values by this key after install (per platform APIs).
display_nameYesString. Short label shown in the installation UI.
descriptionYesString. Help text explaining what the installer should enter.
typeYesString. Common values: api_key (product API key field), text (plain text). The platform may define other types—use what your tooling documents.
requiredYesBoolean. true if the installer must supply a value; false if optional.
secureNoBoolean. When true, the value is treated as sensitive (e.g. masked). Typical for secrets and api_key fields.
default_valueNoString, number, or boolean (JSON). Prefilled value when the field is optional or you want a suggested default (e.g. a default API base URL).
data-bindNoString. Binding hint for the platform, e.g. product.api_key so the field is tied to the product’s stored API key. Use when documented for your product.

oauth_config

Under product_config.<product>.oauth_config.

"oauth_config": {
"googleCalendar": {
"client_id": "...",
"client_secret": "...",
"authorize_url": "https://accounts.google.com/o/oauth2/auth",
"token_url": "https://oauth2.googleapis.com/token",
"options": {
"response_type": "code",
"access_type": "offline",
"prompt": "consent",
"scope": ["https://www.googleapis.com/auth/calendar"]
}
}
}

Each value under oauth_config is one provider configuration. Fields:

FieldRequiredDescription
(provider key)YesObject key is your provider id (e.g. googleCalendar). It must match how your app reads OAuth config at runtime.
client_idYesOAuth client identifier from the provider.
client_secretYesOAuth client secret from the provider.
authorize_urlYesURL where the user is sent to authorize the app (authorization endpoint).
token_urlYesURL used to exchange an authorization code for tokens (token endpoint).
optionsNoNested object for extra OAuth query/body parameters.
options.response_typeNoTypical value code for the authorization code flow.
options.access_typeNoProvider-specific; e.g. offline so refresh tokens may be issued (Google).
options.promptNoProvider-specific; e.g. consent to force the consent screen.
options.scopeNoArray of scope strings the app requests (e.g. calendar API access).

Provider keys are your ids (e.g. googleCalendar); each value is an object shaped like the table. Some providers or platform versions may support additional fields—use their docs when in doubt.


Quick reference

WhereKeyTypePurpose
Top-levelplatform_versionstring"2.0"
Top-levelparent_productstringe.g. "surveysparrow"
Top-levelproduct_configobjectProduct id → config
Under productfrontend_locationsobjectLocation id → { url, icon? }
Under productwhitelisted_domainsstring[]URL regex patterns
Under productevent_listener_functionsobject{ "<event>": { "handler": "<export>" } }
Under productbackend_api_functionsobject{ "<export>": { "timeout"?: number } }
Under productinstallation_parametersobjectInstall-time parameter definitions
Under productoauth_configobjectPer-provider OAuth fields

Full example

Illustrative only—replace domain patterns, function names, param keys, and OAuth values for your app.

{
"platform_version": "2.0",
"parent_product": "surveysparrow",
"product_config": {
"surveysparrow": {
"frontend_locations": {
"full_page_app": {
"url": "index.html"
}
},
"whitelisted_domains": [
"https://(.*).signsparrow.com(.*)",
"https://(.*).surveysparrow.com(.*)",
"http://(.*).surveysparrow.test(.*)",
"https://hooks\\.slack\\.com(/.*)?",
"https://api\\.surveysparrow\\.com(/.*)?",
"https://api\\.signsparrow\\.com(/.*)?"
],
"event_listener_functions": {
"onSubmissionComplete": {
"handler": "onSubmissionComplete"
},
"onContactCreate": {
"handler": "onContactCreateHandler"
}
},
"backend_api_functions": {
"getMappings": { "timeout": 30 },
"saveMapping": { "timeout": 30 }
},
"installation_parameters": {
"surveysparrow_api_key": {
"data-bind": "product.api_key",
"display_name": "SurveySparrow API Key",
"description": "Enter your SurveySparrow API key.",
"required": true,
"secure": true,
"type": "api_key"
},
"survey_api_base_url": {
"display_name": "SurveySparrow API base URL",
"description": "Optional. For example https://api.surveysparrow.com",
"type": "text",
"required": false,
"default_value": "https://api.surveysparrow.com"
}
},
"oauth_config": {
"googleCalendar": {
"client_id": "...",
"client_secret": "...",
"authorize_url": "https://accounts.google.com/o/oauth2/auth",
"token_url": "https://oauth2.googleapis.com/token",
"options": {
"response_type": "code",
"access_type": "offline",
"prompt": "consent",
"scope": ["https://www.googleapis.com/auth/calendar"]
}
}
}
}
}
}

The onContactCreate example uses onContactCreateHandler to show a distinct export; you can point several events at the same handler name if one function handles them.