Configuration
Client site configuration lives in two files: portal.config.mjs wires up the runtime providers, and src/content/site-config.json controls the brand presentation.
portal.config.mjs
Section titled “portal.config.mjs”portal.config.mjs is the entry point for the portal framework. It must import defineConfig from @drawnagency/core/config — not the root @drawnagency/core export, which includes Node-only integration code and will break in the browser during editor hydration.
import { defineConfig, supabaseDeployStatus } from "@drawnagency/core/config";import { supabaseAuth } from "@drawnagency/auth-supabase";import { githubStorage } from "@drawnagency/github";
export default defineConfig({ auth: supabaseAuth(), storage: githubStorage(), deployStatus: supabaseDeployStatus(), site: { name: "Acme Brand Portal" },});To add your own section types, create a src/sections.ts file at the repo root — see Building custom sections. You can optionally also pass that array to defineConfig’s sections field for a type-check, but registration happens through src/sections.ts regardless of the config field.
Top-level keys
Section titled “Top-level keys”| Key | Description |
|---|---|
auth | Authentication provider. supabaseAuth() for OAuth + email/password; see Auth & audiences setup. |
storage | Content storage backend. githubStorage() saves edits back to the GitHub repository. |
deployStatus | Deploy status provider. supabaseDeployStatus() exposes Netlify build state in the editor UI. |
sections | Optional, type-only. Custom section types register from a root src/sections.ts file, not this field — see Building custom sections. Passing the array here only adds a type-check. |
site.name | The site’s display name, shown in the editor header and page <title>. |
src/content/site-config.json
Section titled “src/content/site-config.json”site-config.json controls brand presentation — colors, typography, and media pipeline settings. The provisioner writes this file when creating a new site; update it manually or via the /populate-site skill.
{ "siteName": "Brand Portal", "primaryColor": "#a84300", "primaryContrast": "#f0f0f0", "darkMode": "dark", "headingFont": "system-ui", "bodyFont": "system-ui", "googleFontsUrl": null, "media": { "adapter": "github", "sizes": [640, 1080, 1920], "maxFileSize": 5242880, "quality": 85 }}Fields
Section titled “Fields”| Field | Type | Description |
|---|---|---|
siteName | string | Site display name (used in metadata and editor UI). |
primaryColor | string | Brand primary color as a 6-digit hex (#RRGGBB). |
primaryContrast | string | Text color that contrasts with primaryColor, as a 6-digit hex. |
darkMode | "light" | "dark" | "optional" | Color scheme. "optional" respects the viewer’s OS preference. |
headingFont | string | CSS font-family value for headings. Use "system-ui" or a Google Font name. |
bodyFont | string | CSS font-family value for body text. |
googleFontsUrl | string | null | Full https://fonts.googleapis.com/css2?... URL, or null for system fonts. |
media.adapter | string | Storage backend for media. Always "github" for current sites. |
media.sizes | number[] | Output widths (px) for processed images. Default: [640, 1080, 1920]. |
media.maxFileSize | number | Maximum upload size in bytes. Default: 5242880 (5 MB). |
media.quality | number | WebP compression quality (1–100). Default: 85. |
For the full reference of every accepted field and its validation rules, see the Config reference.