Configuration
Learn about backfill.config.ts permissions, settings defaults, page declarations, UI contributions.
The manifest is one file: backfill.config.ts. It’s a TypeScript module whose default export is the result of defineExtension({...}). The platform reads and validates it before running any of your code.
Keep declarations that can grow large out of the manifest. Custom entities live in src/entities/ and custom fields live in src/fields/. The CLI discovers those files and normalizes them into the deployment artifact.
Minimum manifest
import { defineExtension } from "@backfill-io/sdk";
export default defineExtension({
key: "my-extension",
name: "My Extension",
version: "0.1.0",
permissions: {
entities: { Invoice: ["read", "write"] },
},
});
key and name are required. version is recommended. Everything else is optional.
All manifest fields
defineExtension({
key: string, // unique extension key
name: string, // human display name
version?: string,
permissions?: {
entities?: Record<EntityName, ("read" | "write")[]>,
http?: string[], // each must be an https URL with an explicit host
secrets?: Record<SecretName, ("read" | "write")[]>,
},
config?: Record<string, any>, // settings defaults — see Settings article
pages?: ExtensionPageConfig[],
ui?: {
tabs?: UiTabConfig[],
panels?: UiPanelConfig[],
actions?: UiActionConfig[],
},
});
Permissions are enforced
If your code calls Invoice.update(...) and the manifest only granted read, the runtime rejects the write. Same for HTTP and secrets. There’s no allow-by-default — anything not in the manifest is denied.
entities
permissions: {
entities: {
Invoice: ["read", "write"],
Customer: ["read"],
NexusAddress: ["read", "write"], // also for custom entities you declare
},
}
http
permissions: {
http: ["https://api.stripe.com/*"],
}
- Must be
https://. Plain HTTP is rejected. - Must have an explicit host.
*as the host is rejected. - Path wildcards are fine.
secrets
permissions: {
secrets: {
stripe_api_key: ["read"],
webhook_secret: ["read"],
},
}
Names must match ^[a-z][a-z0-9_]{0,62}$. See Secrets.
config
config: {
taxRate: 8.25,
taxLabel: "Sales Tax",
enableTaxOnInvoices: true,
}
Settings.getAll() at runtime returns the merged map of these defaults plus any overrides the workspace admin set in the dashboard.
pages
Each entry registers an extension page. See UI Pages.
pages: [
{
id: "nexus-addresses",
title: "Nexus Addresses",
path: "nexus-addresses",
render: "src/pages/nexus-addresses.tsx",
kind: "list",
nav: { label: "Nexus Addresses", section: "Tax", order: 10 },
},
],
ui: tabs, panels, actions
Contribute UI to existing entity pages. See UI Contributions.
ui: {
actions: [
{
id: "save-nexus-address",
label: "Save Nexus Address",
page: "nexus-address-form",
run: "src/pages/actions/save-nexus-address.ts",
},
],
}