# Glyphfield complete documentation corpus This file is generated at request time from the same processed MDX collection as the human documentation. Use /llms.txt as the concise router and this file when the task needs complete product and operating context. --- # Contributing Extend Glyphfield while keeping the visual Studio, portable source, browser automation, deterministic APIs, docs, exports, and tests in parity. Canonical page: /docs/contributing Markdown endpoint: /api/docs/contributing Glyphfield is an open-source local-first brand studio. A complete contribution updates the user-facing behavior and every public contract that represents it. The goal is not merely to make a new control appear; it is to keep preview, source, persistence, automation, documentation, and export resolving from the same state. ## Development setup [#development-setup] ```bash git clone https://github.com/Kevin-Liu-01/Glyphfield.git cd Glyphfield corepack enable pnpm install --frozen-lockfile pnpm dev ``` Development runs at `http://localhost:3012`. Before opening a change, run the checks appropriate to its scope: ```bash pnpm typecheck pnpm test pnpm lint pnpm build ``` Documentation-only changes should still run docs generation/typecheck and the focused documentation tests. Visual changes should also be inspected in the real browser at representative desktop and mobile widths. ## Architecture map [#architecture-map] | Area | Primary owner | | ------------------------------------ | ---------------------------------------------------------------------------------------- | | Projects, tabs, active identity/tool | `src/components/StudioApp.tsx` | | Public Studio tool catalog | `src/lib/studioCatalog.ts` | | Tool-to-editor rendering | `src/components/StudioToolWorkspace.tsx` | | Design Lab composition and export | `src/components/ShaderLabStudio.tsx` | | Portable canvas scene graph | `src/lib/canvasDocument.ts` | | Design Lab source adapter | `src/lib/designLabDocument.ts` | | Shared persistent editor state | `src/hooks/` and `src/lib/savedDesigns.ts` | | Browser automation | `src/lib/studioAutomation.ts` plus each tool adapter | | Agent discovery and generation | `src/lib/agentApi.ts`, `agentCatalog.ts`, `agentGeneration.ts` | | Human and machine docs | `content/docs/**`, `/llms.txt`, generated `/llms-full.txt` | | Shared Studio controls | `src/components/StudioControls.tsx`, `CanvasViewport.tsx`, and related editor components | Read the repository `AGENTS.md`, root `SKILL.md`, and the nearest directory `SKILL.md` before changing these owners. ## Core invariants [#core-invariants] * Preview, source, saved state, and export must use the same resolved configuration. * Public tool IDs come from `STUDIO_TOOLS`; Design Lab's public ID is `material`. * Canvas layer order comes from `page.elementIds` and must retain stable element/asset IDs. * Source changes go through the owning validator. Never mutate browser storage or component internals as a substitute. * Every editable color uses the shared color component and normalization path. * Every scrollable Studio region uses the shared minimal scrollbar treatment. * Browser exports run serially and return a non-empty Blob with matching filename/MIME data. * GIF repeat and visual loop closure are different checks. * MP4 codec failures remain explicit; do not substitute another format silently. * Shader/material counts and tool counts come from live catalogs, not prose constants. * Preserve unrelated work in an already-dirty checkout. ## Add or change a Studio tool [#add-or-change-a-studio-tool] Follow the parity chain in order: 1. **Catalog** — add or update the public entry in `studioCatalog.ts`. 2. **Workspace** — map the tool to its editor in `StudioToolWorkspace.tsx`. 3. **State** — define one authoritative state model, persistence keys, and initialization behavior. 4. **Preview** — render from that state with shared canvas/color/select/layer systems. 5. **Source** — serialize and validate every meaningful editable field. 6. **Browser API** — expose accessible controls, source support, and tool-specific actions. 7. **HTTP** — update deterministic generation only when the feature can be represented without the browser. 8. **Export** — render from the same source and validate returned bytes. 9. **Documentation** — update the tool guide, capability matrix, agent guidance, examples, and processed Markdown. 10. **Tests** — cover catalog visibility, source round trip, persistence, automation, and output. Do not create an agent-only renderer that approximates an authentic browser visual. Use the Browser API for Canvas, WebGL, local fonts/files, and browser codecs. ## Reuse editor systems [#reuse-editor-systems] Prefer shared components over one-off controls: * `ColorControl` for HEX, OKLCH, native picker, and opacity. * `CanvasViewport` for fit, reset, zoom, pan, and intrinsic output geometry. * `EditableCanvasLayer` plus `CanvasLayerPanel` for selection, transforms, order, and keyboard nudge. * `SourceCodeDrawer` for validated visual/source parity. * `StudioSelect` for consistent accessible selection. * `LogoAppearanceControls` for inversion, outline, dither, and shadow. * `usePortableCanvasWorkspace` for portable source plus autosave. * `window.glyphfield.studio` adapters for agent-visible labels and actions. See [Editor systems and plugins](/docs/studio/editor-systems) before adding a new primitive. ## Change a source schema [#change-a-source-schema] Schema changes require an explicit compatibility decision: 1. Update types and serializer. 2. Validate the new field and reject malformed values without partial mutation. 3. Add a migration when older durable documents must remain supported. 4. Preserve stable IDs, ordering, asset records, and unknown metadata. 5. Update Browser API descriptions and source examples. 6. Update HTTP response/request schemas when relevant. 7. Add current round-trip, old-version migration, and future/invalid-version tests. 8. Update [Version compatibility](/docs/reference/version-compatibility). Never make removing a version field the recommended way to open an unsupported document. ## Change an export [#change-an-export] Test the complete terminal result: | Output | Minimum proof | | ----------- | ---------------------------------------------------------------------------------------- | | SVG | Non-empty UTF-8 SVG, declared dimensions, valid MIME/filename | | PNG/JPG | Non-empty decoded image, exact dimensions, expected alpha/background | | GIF | Multiple changing frames, expected duration/FPS, protected colors, actual seam | | MP4 | Playable video, expected dimensions/duration, browser codec result, required audio track | | PDF | Complete page set, print geometry, legible text and links | | JSON/Lottie | Parser accepts it, source re-applies, visible result matches | Use small fixtures for focused tests, then visually verify a realistic composition. Do not infer success from a resolved Promise alone. ## Document a feature [#document-a-feature] Update documentation in the same change as behavior: * Add the page to the nearest `meta.json` navigation list. * State the owner, input, output, limits, persistence, and completion rule. * Use actual product names and link to exact reference pages. * Include a current screenshot when the visual structure matters. * Avoid hardcoded catalog counts; point to live discovery endpoints. * Confirm the processed `.md` route and `/llms-full.txt` contain the guidance. * Update `/llms.txt` only for compact, high-value agent routing. Use the existing MDX components for path cards, feature grids, system grids, and media rather than introducing page-local visual wrappers. ## Tests and review [#tests-and-review] Start with the narrowest affected test, then widen: ```bash pnpm vitest run src/lib/__tests__/documentationCoverage.test.ts pnpm typecheck pnpm test pnpm lint pnpm build ``` For UI work, review: * Desktop and narrow/mobile layout. * Light and dark themes. * Keyboard-only operation and visible focus. * Reduced motion where animation is automatic. * Empty, loading, error, restored, and long-content states. * Source apply/reset and browser reload. * One authentic exported artifact. ## Security and privacy [#security-and-privacy] * Keep remote URL fetching disabled unless a separately reviewed feature requires it. * Bound request bodies, image geometry, and generated work. * Never commit secrets, local browser data, or proprietary user assets. * Keep generation stateless unless a persistence feature explicitly defines ownership and deletion. * Treat production firewall state as deployment infrastructure and verify it separately. * Preserve third-party license and attribution notices. See [API security](/docs/reference/api-security) and [Storage and privacy](/docs/artifacts/storage-and-privacy). ## Pull request handoff [#pull-request-handoff] A useful handoff explains: 1. The user-facing behavior changed. 2. The state/source owner and compatibility decision. 3. API or Browser API parity. 4. Persistence and export implications. 5. Tests run and visual states inspected. 6. Any unsupported browser or migration boundary. 7. Documentation and attribution updates. See [Capability matrix](/docs/reference/capability-matrix), [Accessibility](/docs/reference/accessibility), and [Self-hosting](/docs/reference/self-hosting). --- # Getting started Create a project, define its shared identity, compose an artifact, save it, and export a production file. Canonical page: /docs/getting-started Markdown endpoint: /api/docs/getting-started ## Open the Studio [#open-the-studio] Run the app locally and open [the Studio](/studio): ```bash pnpm install pnpm dev ``` The local Studio runs at `http://localhost:3012/studio`. ## 1. Choose a project [#1-choose-a-project] The project library contains three project kinds and presents them as draggable, browser-style tabs: * **Starter** is the complete creation system you can duplicate into a new identity. * **Examples** are audited reference identities for General Translation, Ramp, Mintlify, Tailwind CSS, Vite+, Cloudflare, and Stripe. * **My brands** are local identities you create or duplicate. Closing a tab only closes its view. The project remains available under **All projects**. Deleting a custom project removes its saved browser data. ## 2. Set the foundations [#2-set-the-foundations] Open **Brand identity** and edit the shared source: * Brand and short names * Website, tagline, positioning, and description * Challenge, central concept, promise, outcome, pillars, and personality * Recognizable graphic device, composition, image direction, pattern, and rules * Dark and light logo marks * Semantic colors * Display, body, accent, and code typography * Multilingual greetings * Voice principles, phrases, avoided language, and audiences * Named brand applications with categories, formats, and production intent Every generator reads the active identity. A change here flows into books, boards, templates, components, brand elements, motion, Design Lab defaults, agent presets, and exports. ## 3. Find a tool [#3-find-a-tool] Use the left navigation or press `⌘K` / `Ctrl+K` and search for a capability such as `email`, `logo`, `dither`, `slide`, or `terminal`. Tools are grouped into Brand, Motion, Foundations, Expressions, and Components. ## 4. Compose and inspect [#4-compose-and-inspect] Most tools use the same layout: * The left inspector or library controls content, layout, material, surface, and uploaded assets. * The center canvas renders the current artifact. * The right inspector edits the selected frame or layer. * Layered tools use a bottom dock for selection, ordering, visibility, duplication, grouping, and deletion. * The canvas toolbar supports zoom out, zoom in, reset, and fit. * Wheel or trackpad input zooms the canvas, and dragging empty workspace pans a zoomed view. * **Code** opens the exact artifact configuration in a right-side drawer. * The top-right actions save, preview, or export the artifact. In the source drawer, **Apply** validates and writes the edited source into the same state used by the visual controls. Invalid source remains in the drawer with an inline error and does not alter the canvas. **Reset** reloads the current visual snapshot; it does not restore a stale copy from when the drawer first opened. Use **Visual settings** to switch light, dark, or automatic system appearance and choose Switzer, Be Vietnam Pro, Schibsted Grotesk, or Rethink Sans for the interface. Studio appearance never changes the selected brand surface or exported colors. For a flexible first composition, open **Design Lab**: 1. Choose wide, square, or OpenGraph output. 2. Add text, a brand mark, an image, a shader, or a converter. 3. Select each layer to edit geometry, appearance, opacity, and material. 4. Scrub the material timeline to choose an exact shader frame. 5. Save the design before producing variants. ## 5. Export [#5-export] Download actions are specific to each tool. Common outputs include: * PNG for lossless rasterized templates, boards, backgrounds, Lottie frames, and compositions * JPG for smaller opaque Design Lab stills * GIF for frame animation, live materials, and seamless loops * MP4 for browser-encoded video and Animation audio * PDF for the generated Brand Book * JSON for identities, Lottie, canvas documents, and production briefs * SVG for deterministic API templates and backgrounds The export review is the last checkpoint. Confirm dimensions, clipping, background, text contrast, motion, and file type before downloading. A successful click is not the artifact; verify that the downloaded file is non-empty and opens in its target application. Continue with [Download and use artifacts](/docs/artifacts/download-and-use). For exact editing, continue with [Source code editing](/docs/studio/source-editing) and [Source format reference](/docs/reference/source-formats). --- # Documentation Define one brand system, compose production artifacts, animate it, and let agents operate the same tools. Canonical page: /docs Markdown endpoint: /api/docs/ Glyphfield is a local-first, open-source brand studio. It keeps identity foundations, design applications, live materials, motion, source documents, exports, and agent operations connected instead of treating each output as a separate file. ## Choose a path [#choose-a-path] Create or duplicate a project, edit the shared identity, choose a tool, and export. Layer type, marks, images, stickers, converters, and live shaders; save and export still or motion files. Build frame sequences with per-state timing, materials, image transforms, audio, GIF, and MP4. Browse the quality-ranked shared Shader Library, tune its controls, scrub time, and reuse it across tools. Choose HTTP generation, the Studio Browser API, markdown docs, or a combined workflow. Understand PNG, JPG, SVG, GIF, MP4, PDF, Lottie, and JSON portability. Map every Studio capability to source, browser automation, HTTP, and output formats. Inspect endpoints, browser methods, source models, shortcuts, limits, and social previews. ## What is connected [#what-is-connected] Strategy, art direction, logos, authorized assets, colors, typography, language, voice, applications, and defaults. Brand elements, moodboards, a complete brand book, Design Lab, Animation, Lottie, templates, tokens, type, and components. Exact source drawers, a versioned canvas scene graph, saved designs, autosave recovery, layer history, and export preflight. Versioned discovery, deterministic HTTP generation, processed markdown, full-text docs, and browser-native automation. ## See the system [#see-the-system] ## Human and agent parity [#human-and-agent-parity] The visual UI and agent surfaces share the same owners: * `/api/agent`, `/api/catalog`, `/api/labs`, `/api/materials`, `/api/identities`, and `/api/elements` publish current capabilities. * `POST /api/generate` validates deterministic template, background, element-brief, and Design Lab sequence requests. * `window.glyphfield.studio` operates the active browser tool, including local files, exact source, Canvas, WebGL, GIF, and MP4. * Every documentation page is available as processed markdown by adding `.md` to its URL. * `/llms.txt` is the compact agent router; `/llms-full.txt` is the complete generated documentation corpus. Agents should discover first, choose an interface deliberately, apply the smallest source change, visually verify browser-rendered work, and treat a non-empty returned or downloaded artifact as completion. ## Local-first by default [#local-first-by-default] Browser projects, saved designs, uploaded files, fonts, and drafts remain in the current browser profile. Stateless generation requests are processed in memory and do not silently read or mutate a browser-local project. Remote asset URLs are intentionally unsupported. ## Operate and extend [#operate-and-extend] Keep identity and tool source, original authorized assets, and rendered proofs outside the browser. Separate source, storage, Canvas, WebGL, codec, and download failures without clearing the active project. Serve the dynamic docs, discovery, generation, OpenGraph, and Studio routes with browser capabilities intact. Update catalog, state, source, Browser API, HTTP, docs, exports, and tests as one parity chain. * [Back up and restore a project](/docs/artifacts/backup-and-restore) * [Troubleshoot Studio and exports](/docs/reference/troubleshooting) * [Check browser capabilities](/docs/reference/browser-support) * [Self-host Glyphfield](/docs/reference/self-hosting) * [Review version compatibility](/docs/reference/version-compatibility) * [Contribute to Glyphfield](/docs/contributing) ## Important links [#important-links] * [Open the Studio](/studio) * [Read the compact agent runbook](/llms.txt) * [Read the complete agent corpus](/llms-full.txt) * [Inspect the agent manifest](/api/agent) * [Inspect OpenAPI 3.1](/openapi.json) * [Read the contribution guide](/docs/contributing) * [View the source](https://github.com/Kevin-Liu-01/Glyphfield) Glyphfield software is released under the [MIT License](https://github.com/Kevin-Liu-01/Glyphfield/blob/main/LICENSE). Bundled third-party marks, fonts, textures, shaders, and reference-brand assets retain their own licenses and ownership. --- # Browser-agent workflow Operate the Studio when generation depends on WebGL, Canvas, local files, visual placement, Lottie, GIF, or MP4 capture. Canonical page: /docs/agents/browser-workflow Markdown endpoint: /api/docs/agents/browser-workflow Some capabilities intentionally render in the browser because their output depends on browser graphics APIs or interactive composition. They remain programmatically available through the Studio Browser API. ## Use the browser for [#use-the-browser-for] * Moodboard PNG up to 4800 × 6000 * Animation GIF and MP4 packages, including MP4 audio * Live Design Lab shaders, stills, GIFs, MP4, and shader sequences * PNG output from OpenGraph, terminal, logos, and templates * Local font, image, logo, and shader inputs * Visual placement, opacity, scale, and zoom inspection * Shared Brand identity settings that update all browser-local designs * Exact source editing for the active artifact through the right-side Code drawer ## Discovery before operation [#discovery-before-operation] 1. Fetch `/api/catalog`. 2. Select the exact tool `id` or visible `name`. 3. Open `/studio`. 4. Choose a built-in identity or create a local project. 5. Open the matching tool with navigation or Studio search. 6. Read `window.glyphfield.studio.describe()` and `controls()`. 7. Configure by accessible label with `activate`/`set`, or use `readSource`/`applySource` for exact source editing. 8. Resolve any inline validation error before continuing; an error means the visual document was not changed. 9. Verify the canvas at a useful inspection zoom and use Reset/Fit when needed. 10. Invoke the tool's export action and verify the returned artifact. ## Stable programmatic interface [#stable-programmatic-interface] ```js window.glyphfield.studio.describe(); window.glyphfield.studio.controls(); const nextToolReady = new Promise((resolve) => { window.addEventListener('glyphfield:studio-api-ready', resolve, { once: true }); }); window.glyphfield.studio.activate('Design Lab'); await nextToolReady; // Re-read the adapter after switching tools. const studio = window.glyphfield.studio; if (studio.activeTool() !== 'material') { throw new Error(`Expected Design Lab, received ${studio.activeTool()}`); } const current = JSON.parse(studio.readSource()); current.composition.backgroundColor = '#111216'; await studio.applySource(current); const artifact = await studio.invoke('design.export', { format: 'png', download: true, }); ``` The page dispatches `glyphfield:studio-api-ready` whenever the active tool adapter is ready. Listen for that event when automation starts before Studio has finished loading. Generic actions are `source.read`, `source.apply`, `controls.list`, `control.activate`, `control.set`, and `artifact.download`. `describe()` lists any additional actions exposed by the active tool. An export can return a Blob without saving it, save immediately with `download: true`, or be saved later with `studio.download(artifact)`. ## Reliable interaction [#reliable-interaction] * Prefer visible labels and accessible names over coordinates. * Wait for imported images, fonts, and shader previews to finish rendering. * Use the canvas at 100% for final inspection. * Confirm surface and logo reversal in both light and dark compositions. * Treat browser download completion as the terminal success condition. * For Blob-only export, require a non-empty Blob with the expected MIME type and filename. * Inspect multiple motion frames and verify the seam when a perfect loop is required. * Do not delete projects unless the user explicitly requests deletion. * Do not assume the drawer document is a `/api/generate` payload. Use the tool's [source format](/docs/reference/source-formats). ## Persistence boundary [#persistence-boundary] Project identity, navigation, tabs, and most tool drafts persist in `localStorage`. Design Lab named designs, complete autosaves, and converted assets use IndexedDB with a small synchronous recovery journal where needed. The Browser API reads and mutates the same active project state. Stateless HTTP requests do not silently mutate projects; generated apply-ready documents must be passed explicitly to `applySource`. ## Choosing API versus browser [#choosing-api-versus-browser] If `/api/generate` can represent the artifact, prefer it. Use the Studio Browser API when visual judgment or browser-native rendering is part of the requested result. --- # Choose the right interface Route an agent request to deterministic HTTP generation, the Studio Browser API, or direct markdown documentation. Canonical page: /docs/agents/choose-interface Markdown endpoint: /api/docs/agents/choose-interface Glyphfield has three agent-facing interfaces. Choosing the correct one is the first correctness decision. ## Routing rule [#routing-rule] | Need | Use | Why | | ----------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------ | | Discover tools, identities, shaders, surfaces, elements, schemas, or policies | HTTP discovery endpoints | Structured, cacheable, versioned data | | Generate a slide, blog cover, partnership lockup, static background, element brief, or Design Lab source document | `POST /api/generate` | Deterministic validation and portable response | | Render WebGL, Canvas, local fonts/files, Lottie, interactive placement, GIF, JPG, PNG, or MP4 | `window.glyphfield.studio` | Uses the authentic browser renderer and active project | | Read one topic | `/docs/.md` | Clean processed markdown for the exact page | | Load the complete knowledge surface | `/llms-full.txt` | Concatenated current docs without scraping HTML | | Find an unknown topic | `/api/search` or `/api/catalog` | Search prose or structured capabilities | Best for source-controlled SVG, JSON briefs, repeatable requests, and initial Design Lab documents. Best for everything that depends on the current canvas, WebGL, browser codecs, file objects, or visual verification. Best for instructions, workflows, examples, edge cases, and exact source semantics. The visual workspace remains the final evidence for placement, contrast, clipping, timing, and motion quality. ## Default decision tree [#default-decision-tree] 1. Read `/llms.txt` and `/api/agent`. 2. Discover the exact tool or generator instead of inventing an ID. 3. If `POST /api/generate` fully expresses the result, use it. 4. If the result depends on Canvas, WebGL, browser codecs, local files, or visual placement, open `/studio` and use the Browser API. 5. If HTTP returns an apply-ready `design-sequence`, explicitly pass `response.document` to `applySource`; HTTP generation never mutates the open Studio by itself. 6. Inspect the canvas and export through the active tool. 7. Treat the downloaded file or returned Blob—not a button click—as completion. ## Examples [#examples] ### Static agenda slide [#static-agenda-slide] Use HTTP. The slide renderer is deterministic SVG and does not require an open project. ### Live Gem Smoke poster [#live-gem-smoke-poster] Use HTTP to create a `design-sequence` document, then use the browser to apply and export it. The server returns composition intent; the browser produces the authentic shader pixels. ### Existing local project update [#existing-local-project-update] Use the Browser API. Read the open tool's source, apply the smallest change, and save/export in that project. A stateless request cannot infer which browser-local project the user meant. ### Brand-element production brief [#brand-element-production-brief] Use `/api/elements` to find the ID and `POST /api/generate` with `kind: "element-brief"`. Use Studio only if the user also needs a visual proof or manual composition. ## Never guess across boundaries [#never-guess-across-boundaries] * A Code-drawer document is not automatically a `/api/generate` request. * A discovery record is not a rendered artifact. * An HTTP success does not mean a browser-local design was updated. * A browser control activation does not mean an export finished. * A material preview is not permission to redistribute a third-party asset. See [Connect an agent](/docs/agents/connect), [Browser API](/docs/reference/browser-api), and [Capability matrix](/docs/reference/capability-matrix). --- # Connect an agent Discover Glyphfield, choose an identity and capability, submit a generation request, and save the returned artifact. Canonical page: /docs/agents/connect Markdown endpoint: /api/docs/agents/connect ## Connection sequence [#connection-sequence] An agent should follow this sequence for every new deployment origin: 1. Fetch `/llms.txt` for the concise operating router. Fetch `/llms-full.txt` when the task needs the complete product model. 2. Fetch `/api/agent` for the current version, policies, resources, and contract. 3. Fetch `/api/labs` to discover the current Studio plugin surface. 4. Fetch `/api/catalog` when selecting a deterministic background or tactile surface recipe; its `surfaceLibrary` contains every preset, attribution record, and physical control. 5. Fetch `/api/materials` when selecting a shader or editing shared material controls. 6. Fetch `/api/identities` when using any built-in preset. 7. Fetch `/api/elements` when choosing a brand application. 8. Fetch `GET /api/generate` immediately before constructing a request. 9. `POST application/json` to `/api/generate`. 10. Save the returned artifact, or apply a returned Design Lab document through `window.glyphfield.studio` for browser-native Canvas/WebGL export. Do not infer undocumented enum values. Do not scrape the client bundle when a structured endpoint provides the same information. ## Shell connection check [#shell-connection-check] ```bash BASE_URL=http://localhost:3012 curl -fsS "$BASE_URL/llms.txt" curl -fsS "$BASE_URL/api/agent" | jq '{ version, schemaVersion, resources, interfaces, execution }' curl -fsS "$BASE_URL/api/labs" | jq '{ count, plugins: [.plugins[].id] }' curl -fsS "$BASE_URL/api/catalog" | jq '{ surfaces: .surfaceLibrary.count, surfaceControls: (.surfaceLibrary.controls | keys) }' curl -fsS "$BASE_URL/api/materials" | jq '{ count, engines, sharedBy }' curl -fsS "$BASE_URL/api/generate" | jq '.kinds | keys' ``` For a deployed instance, replace `BASE_URL` with its origin. ## TypeScript discovery client [#typescript-discovery-client] ```ts const baseUrl = 'http://localhost:3012'; const [manifest, labs, materials, generation, identities, elements] = await Promise.all([ fetch(`${baseUrl}/api/agent`).then((response) => response.json()), fetch(`${baseUrl}/api/labs`).then((response) => response.json()), fetch(`${baseUrl}/api/materials`).then((response) => response.json()), fetch(`${baseUrl}/api/generate`).then((response) => response.json()), fetch(`${baseUrl}/api/identities`).then((response) => response.json()), fetch(`${baseUrl}/api/elements`).then((response) => response.json()), ]); console.log(manifest.version, labs.count, materials.count, generation.schemaVersion); console.log(identities.identities.length, elements.elements.length); console.log(manifest.studioBrowserApi.global); ``` Independent discovery requests can run concurrently. Fetch the generation contract again if substantial time passes before generation. ## Minimal generation call [#minimal-generation-call] ```ts const response = await fetch(`${baseUrl}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind: 'template', template: 'slides', slideLayout: 'title', texture: 'white', title: 'Code is the source of truth.', identity: { preset: 'gt' }, output: 'raw', }), }); if (!response.ok) throw new Error(await response.text()); const svg = await response.text(); ``` The raw response is a complete SVG string. ## Programmatic Design Lab sequence [#programmatic-design-lab-sequence] The HTTP API creates the exact source document; the browser API renders it through the same live shader canvases and compositor as the UI. ```ts const response = await fetch(`${baseUrl}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind: 'design-sequence', identity: { preset: 'gt' }, shader: { materialId: 'paper-gem-smoke' }, sequence: { cutCount: 10, finalHoldMs: 5000, pace: 'accelerating' }, effect: { kind: 'bayer', opacity: 0.76 }, texts: [{ value: 'Open Source', weight: 500 }], export: { width: 1920, fps: 30, quality: 'best' }, }), }); const generated = await response.json(); // Run inside the open /studio page after selecting Design Lab. const studio = window.glyphfield.studio; if (studio.activeTool() !== 'material') throw new Error('Open Design Lab first.'); await studio.applySource(generated.document); const artifact = await studio.invoke('design.export', { format: 'mp4', mode: 'shader-sequence', download: true, }); ``` Use `studio.describe()` before invoking tool-specific actions. `studio.controls()` and the accessible-label `activate`/`set` methods make every visible UI operation programmatically available, including tools without a headless renderer. Export with PNG, JPG, GIF, or MP4; omit `download` when the caller wants only the returned Blob, or call `studio.download(artifact)` later. ## Prompting an agent [#prompting-an-agent] Point an LLM at the runbook rather than reproducing the full schema in a prompt: ```text Read https://YOUR_ORIGIN/llms.txt and the linked agent manifest. Generate a white GT agenda slide titled “One system, every market.” Save the raw SVG response as gt-agenda.svg. Do not use undocumented enum values. ``` This keeps the deployment’s current contract authoritative. For broad implementation work, replace `/llms.txt` with `/llms-full.txt`. For a focused task, load one page such as `/api/docs/studio/design-lab` or `/api/docs/reference/browser-api`. ## Browser source workflow [#browser-source-workflow] When a task requires an artifact that the public generation API cannot fully express, open the matching Studio tool and use `window.glyphfield.studio`. Prefer `readSource`/`applySource` for exact documents and `controls`/`activate`/`set` for visible operations. The Code drawer remains the human-facing version of the same source workflow. Do not paste an arbitrary Studio source document into `POST /api/generate`. The drawer is the browser-local document for an open tool; the generation route is a separate versioned HTTP contract. `design-sequence` explicitly returns an apply-ready `document`. See [Browser workflow](/docs/agents/browser-workflow), [Source code editing](/docs/studio/source-editing), and [Source formats](/docs/reference/source-formats). --- # Errors and limits Handle validation responses, request limits, content types, and retries safely. Canonical page: /docs/agents/errors Markdown endpoint: /api/docs/agents/errors Validation failures use a structured response: ```json { "error": { "code": "invalid_request", "field": "settings.width", "message": "settings.width must be an integer between 64 and 4096." }, "schemaVersion": 1 } ``` ## Status codes [#status-codes] | Status | Meaning | Response | | ------ | -------------------------------------- | ---------------------------------------------- | | 400 | Malformed JSON or invalid field | Correct the named field | | 413 | Request body exceeds 5 MB | Reduce or recompress embedded assets | | 415 | Content-Type is not JSON | Send `Content-Type: application/json` | | 429 | Production request rate limit exceeded | Wait for the limit window before retrying | | 500 | Artifact generation failed | Log the response and retry only if appropriate | ## Retry policy [#retry-policy] Do not retry an unchanged validation request. Read `error.field`, correct the input, and submit a new request. Unknown top-level request fields fail with `unknown_field` rather than silently falling back to defaults. For `429`, stop concurrent work and wait for the rate-limit window. Do not fan out retries. For transient 5xx responses, use bounded exponential backoff and retain the original request for diagnosis. Generation is deterministic for the same contract and inputs. ## Important limits [#important-limits] * Request body: 5 MB maximum * Data URL asset: 5 MB maximum * Background width and height: 64–4096 * Background total pixels: 12,000,000 maximum * Template title: 240 characters * Template body: 1000 characters * Remote asset URLs: unsupported ## Contract drift [#contract-drift] Always read `GET /api/generate` and check `schemaVersion`. If the schema version is unknown, stop and update the client rather than silently guessing. ## Browser API failures [#browser-api-failures] Browser automation uses JavaScript errors rather than HTTP status codes: | Error | Typical cause | Response | | ----------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | `TypeError` | Malformed action input, unsupported source, wrong control value, empty artifact | Correct the input; do not retry unchanged | | `RangeError` | Accessible control label or action is not exposed by the active adapter | Re-read `describe()` and `controls()`; confirm the active tool | | `Error` from a renderer | WebGL context, image decode, Canvas, GIF, MP4, font, or codec failure | Preserve source, capture the exact capability failure, retry only when conditions changed | After a tool switch, the global adapter is replaced. A stale reference can report the old action set or mutate the wrong tool. Wait for `glyphfield:studio-api-ready` and re-read `window.glyphfield.studio`. Do not swallow export errors and report success because the source was valid. A valid document and a rendered file are separate completion checkpoints. ## Recovery-safe behavior [#recovery-safe-behavior] When rendering fails after source application: 1. Re-read the source and retain it. 2. Record `activeTool()`, `describe()`, browser capability, requested format, dimensions, and action. 3. Stop sequence preview or release any active export job. 4. Retry only after changing the actual failure condition. 5. If the browser lacks the requested codec, report that limitation without substituting a different format. For human-facing Studio, storage, WebGL, and export diagnosis, continue with [Troubleshooting and recovery](/docs/reference/troubleshooting). For deployment abuse controls, see [API security](/docs/reference/api-security). --- # Generation API Generate templates, backgrounds, resolved brand-element briefs, and apply-ready Design Lab sequences with the versioned JSON contract. Canonical page: /docs/agents/generate Markdown endpoint: /api/docs/agents/generate `POST /api/generate` accepts `application/json`. The request `kind` selects one of four generators. ## Output selection [#output-selection] * `output: "json"` is the default for SVG generators. The response contains metadata and `artifact.content`. * `output: "raw"` returns `image/svg+xml` directly. * `element-brief` always returns JSON. * `design-sequence` returns an apply-ready Design Lab document, its resolved shader timeline, and browser API commands. ## Design sequence [#design-sequence] Design sequence creates the same versioned composition used by Design Lab. It supports an identity-aware brand mark, multiple text layers, a Bayer/ASCII/halftone/posterize converter, any material returned by `/api/materials`, 8–12 cuts, and a 3–6 second final hold. ```json { "kind": "design-sequence", "identity": { "preset": "gt" }, "ratio": "wide", "backgroundColor": "#111216", "shader": { "materialId": "paper-gem-smoke", "shaderSize": 1 }, "sequence": { "cutCount": 10, "finalHoldMs": 5000, "pace": "accelerating" }, "effect": { "kind": "bayer", "opacity": 0.76, "foreground": "#F5F5F2", "background": "#111216" }, "texts": [{ "value": "Open Source", "weight": 500 }], "export": { "width": 1920, "fps": 30, "quality": "best" } } ``` The response is JSON with: * `schemaVersion: 1`: the HTTP response-envelope version. * `document`: an apply-ready Design Lab compatibility source with `version: 3`. * `sequence.timeline`: resolved material IDs and cut boundaries. * `automation`: the stable browser global and exact apply/export commands. `document.version` is not the active canvas schema. `applySource(response.document)` validates and migrates the compact compatibility source, then the Design Lab adapter exposes the normalized result as CanvasDocument schema 2 with Design Lab source metadata version 4. Re-read source after application before making targeted CanvasDocument edits. Apply and render inside `/studio`: ```js await window.glyphfield.studio.applySource(response.document); const artifact = await window.glyphfield.studio.invoke( 'design.export', { format: 'mp4', mode: 'shader-sequence', download: true } ); ``` Choose `png`, `jpg`, `gif`, or `mp4`. Shader-sequence mode is available for GIF and MP4. The export action resolves to the real UI artifact object and uses the authentic shader canvases, composition effects, text, marks, layer order, and output settings; `download: true` also saves it. ## Template [#template] Template generates slides, blog covers, and partnership lockups. ```json { "kind": "template", "template": "slides", "slideLayout": "agenda", "texture": "white", "title": "One system, every market.", "body": "Foundation\nExpression\nApplication\nDelivery", "identity": { "preset": "gt" }, "output": "raw" } ``` ### Template enums [#template-enums] * `template`: `slides | blog | partnership` * `texture`: `white | dark | grid | noise` * `slideLayout`: `title | section | agenda | split | metrics | quote | timeline | statement | comparison | process | chart | team | image | closing` Fixed output sizes are 1600 × 900 for slides, 1200 × 630 for blog, and 1200 × 600 for partnership. ## Background [#background] Background generates gradient, grain-gradient, dither, and pattern SVGs. ```json { "kind": "background", "identity": { "preset": "gt" }, "settings": { "width": 1200, "height": 630, "style": "grain-gradient", "gradient": "mesh", "angle": 32, "colorA": "#FFFFFF", "colorB": "#181818", "colorC": "#737373", "focalX": 42, "focalY": 38, "relief": 24, "grain": 18, "pattern": "dots", "patternOpacity": 14, "spacing": 24, "logoTone": "black", "logoScale": 24, "logoOpacity": 100, "logoX": 0, "logoY": 0 }, "output": "raw" } ``` Width and height must each be 64–4096, and the total may not exceed 12,000,000 pixels. ## Element brief [#element-brief] Element brief resolves a stable record from `/api/elements` against an identity. ```json { "kind": "element-brief", "elementId": "email-signature", "identity": { "preset": "custom", "name": "Acme", "website": "acme.test", "tagline": "Tools for careful teams." } } ``` The response describes the element, dimensions, format, keywords, resolved identity, settings, and preview family. It does not rasterize an image. ## JSON artifact envelope [#json-artifact-envelope] ```json { "schemaVersion": 1, "artifact": { "content": "...", "filename": "gt-slides-agenda.svg", "mimeType": "image/svg+xml", "width": 1600, "height": 900 } } ``` Check `schemaVersion`, `mimeType`, and dimensions before storing the content. ## Studio source is a separate contract [#studio-source-is-a-separate-contract] The **Code** drawer inside `/studio` serializes the active browser tool. It supports exact edits for identities, boards, Animation, Lottie, Design Lab, templates, foundations, and components. Design Lab uses CanvasDocument schema 2 with Design Lab metadata source version 4. Browser documents are intentionally shaped around each interactive tool and are not interchangeable with the `POST /api/generate` request body. Use the HTTP contract on this page for deterministic remote generation. `design-sequence` is deliberately a bridge: it emits a compact, apply-ready compatibility document for programmatic browser rendering, and the browser normalizes it to current Studio source. For every other tool, use the active `window.glyphfield.studio` API to read/apply source or operate visible controls. --- # Identities and custom assets Use built-in identity systems, override foundation fields, and safely send local logo and image data. Canonical page: /docs/agents/identity-assets Markdown endpoint: /api/docs/agents/identity-assets Every generator accepts an `identity` object. ## Presets [#presets] * `starter` is the complete neutral default. * `template` is a rigorous identity-construction blueprint. * `gt` resolves the bundled General Translation identity and logo family. * `ramp`, `mintlify`, `tailwind`, `viteplus`, `cloudflare`, and `stripe` resolve audited reference systems and their local logo assets. * `custom` avoids inheriting a preset logo and creates a monogram when no logo is supplied. Fetch `/api/identities` at runtime instead of hard-coding the list. Each record includes foundations, strategy, graphic-system rules, application definitions, proof references, and local asset IDs. ## Identity fields [#identity-fields] | Field | Limit | | -------------- | --------------------------------------------- | | `name` | 80 characters | | `shortName` | 8 characters | | `website` | 200 characters | | `tagline` | 180 characters | | `positioning` | 320 characters | | `description` | 320 characters | | `ink`, `paper` | Six-digit HEX | | `logoDataUrl` | Supported base64 image data URL, maximum 5 MB | Fields override the selected preset. Omitted values inherit from the preset. ## Convert a logo to a data URL [#convert-a-logo-to-a-data-url] On macOS or Linux: ```bash MIME=image/png LOGO_DATA="data:$MIME;base64,$(base64 < logo.png | tr -d '\n')" ``` Then construct the request with `jq` so shell escaping is handled safely: ```bash jq -n --arg logo "$LOGO_DATA" '{ kind: "background", identity: { preset: "custom", name: "Acme", shortName: "AC", website: "acme.test", ink: "#111111", paper: "#FFFFFF", logoDataUrl: $logo }, settings: { width: 1200, height: 630, style: "gradient", colorA: "#FFFFFF", colorB: "#D9FF63" }, output: "raw" }' > request.json ``` Supported custom image data includes PNG, JPEG, WebP, GIF, and SVG. Remote URLs are rejected; download and authorize the asset before converting it. ## Background and partner images [#background-and-partner-images] Templates additionally support `backgroundImageDataUrl` and `partnerLogoDataUrl`. Use `partnerId` only for asset IDs returned by `/api/identities` for the selected preset. The API embeds accepted assets into the returned SVG so it remains portable. ## Reference sources and trademark boundary [#reference-sources-and-trademark-boundary] The reference identities were studied from primary brand sources current in July 2026: * [Ramp press kit](https://ramp.com/press/) * [Mintlify documentation appearance guide](https://www.mintlify.com/docs/organize/settings-appearance) and [design practice](https://www.mintlify.com/blog/how-we-design-at-mintlify) * [Tailwind CSS brand assets](https://tailwindcss.com/brand) * [Vite+ product site](https://viteplus.dev/) * [Cloudflare press kit](https://www.cloudflare.com/en-gb/press/press-kit/) and [logo guidance](https://www.cloudflare.com/en-gb/logo/) * [Stripe newsroom and logo kit](https://stripe.com/newsroom/information) These systems are included for design study and interoperability. Brand names, marks, and source assets remain the property of their respective owners. Glyphfield’s MIT license applies to the software and original templates; it does not grant trademark rights or imply endorsement. Reference identities also bundle the font files needed to render their Display, Body, Accent, and Code roles without falling back to Glyphfield's interface typeface. Those files retain their original licenses and are not relicensed by Glyphfield's MIT license. The bundled role map and redistribution notice live in [`public/fonts/brands/README.md`](https://github.com/Kevin-Liu-01/Glyphfield/blob/main/public/fonts/brands/README.md). --- # Agent integration Give LLMs and coding agents structured discovery, deterministic generation, and a browser fallback for visual capabilities. Canonical page: /docs/agents Markdown endpoint: /api/docs/agents Glyphfield exposes a public, versioned agent interface. An agent can discover the product without scraping application JavaScript, generate portable assets or apply-ready compositions over HTTP, and operate every visual Studio control through the programmatic Browser API. ## Discovery surface [#discovery-surface] | Resource | Purpose | | ------------------ | ------------------------------------------------------------------------------------------------ | | `/llms.txt` | Canonical operational runbook for language models | | `/llms-full.txt` | Complete concatenated documentation corpus generated from current MDX | | `/api/docs/{slug}` | One processed documentation page as Markdown | | `/api/agent` | Versioned manifest, policies, resources, and generation contract | | `/openapi.json` | OpenAPI 3.1 route document | | `/api/catalog` | Studio tools and capability keywords | | `/api/labs` | Every Studio lab plugin and its shared-library capabilities | | `/api/materials` | Every shader, attribution, palette, look preset, and editable control | | `/api/identities` | Built-in template and reference identity records | | `/api/elements` | Searchable brand application records | | `/api/generate` | GET contract and POST generation endpoint | | `/studio` | Browser-local visual workspace | | `skills/` | Installable task skills for creation, HTTP generation, Studio operation, and export verification | ## Three connected surfaces [#three-connected-surfaces] ### HTTP generation [#http-generation] Use HTTP when the desired artifact is a template SVG, background SVG, element brief, or an apply-ready Design Lab sequence document. This path is deterministic, portable, and does not require a browser until a requested result depends on live rendering. ### Browser operation [#browser-operation] Use the Studio when a task requires Canvas, WebGL, local fonts, local images, visual placement, high-resolution PNG/JPG rasterization, GIF or MP4 capture, Lottie, or exact source edits to an active browser artifact. Browser-capable agents use `window.glyphfield.studio` to apply validated source, inspect the resulting canvas, operate accessible controls, and export the real composition. ### Documentation corpus [#documentation-corpus] Use `/llms.txt` to route the task, `/llms-full.txt` to load the full current product model, and `/api/docs/{slug}` when only one topic is needed. These routes are built from the same documentation source as the human UI. An agent should use the smallest interface that fully expresses the requested artifact. HTTP and browser operation are deliberately composable rather than mutually exclusive. ## Operating invariant [#operating-invariant] Agents must discover, mutate, and verify: 1. Discover the live contract and catalog IDs. 2. Read current source before changing an open artifact. 3. Preserve unknown fields and apply the smallest change through a validator. 4. Re-read state after applying it. 5. Inspect visual output when appearance matters. 6. Confirm the actual file or Blob, not only the request status. ## No API key [#no-api-key] The current public agent routes do not require authentication. Do not invent an `Authorization` header. Always re-read `/api/agent` and `GET /api/generate` because availability and schemas may change. Install or inspect the focused [Glyphfield Skills](/docs/skills), then start with [Choose an interface](/docs/agents/choose-interface), [Connect an agent](/docs/agents/connect), and the complete [Agent recipes](/docs/agents/recipes). --- # Agent recipes Complete programmatic workflows for discovery, design composition, material selection, saving, verification, and export. Canonical page: /docs/agents/recipes Markdown endpoint: /api/docs/agents/recipes These recipes show the full operation, including discovery and completion checks. Replace `BASE_URL` with the Glyphfield deployment origin. ## Discover before generating [#discover-before-generating] ```bash BASE_URL=http://localhost:3012 curl -fsS "$BASE_URL/api/agent" | jq '{version, schemaVersion, resources, interfaces}' curl -fsS "$BASE_URL/api/labs" | jq '.plugins[] | {id, name, capabilities}' curl -fsS "$BASE_URL/api/materials" | jq '{count, defaults, engines, sharedBy}' curl -fsS "$BASE_URL/api/identities" | jq '.identities[] | {id, name}' curl -fsS "$BASE_URL/api/generate" | jq '{schemaVersion, kinds}' ``` Cache discovery only within the endpoint's advertised cache window. Fetch the generation contract again before emitting a request if the client may be stale. ## Generate and save a raw SVG [#generate-and-save-a-raw-svg] ```bash curl -fsS -X POST "$BASE_URL/api/generate" \ -H 'Content-Type: application/json' \ -d '{ "kind": "template", "template": "slides", "slideLayout": "statement", "texture": "dark", "title": "One system. Every surface.", "identity": { "preset": "gt" }, "output": "raw" }' \ -o one-system.svg test -s one-system.svg ``` The terminal success condition is a non-empty SVG file, not a `200` response alone. ## Generate a tactile background [#generate-a-tactile-background] ```bash curl -fsS -X POST "$BASE_URL/api/generate" \ -H 'Content-Type: application/json' \ -d '{ "kind": "background", "identity": { "preset": "gt" }, "settings": { "width": 1600, "height": 900, "style": "grain-gradient", "gradient": "mesh", "colorA": "#F5F5F2", "colorB": "#181818", "colorC": "#7058FF", "surfaceMaterial": "embossed-paper", "surfaceDepth": 36, "surfaceRoughness": 72, "surfaceScale": 44, "grain": 12 }, "output": "raw" }' \ -o tactile-background.svg ``` ## Create and render a Design Lab sequence [#create-and-render-a-design-lab-sequence] First generate the exact composition document: ```js const baseUrl = 'http://localhost:3012'; const response = await fetch(`${baseUrl}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind: 'design-sequence', identity: { preset: 'gt' }, ratio: 'wide', backgroundColor: '#111216', includeBrandMark: true, texts: [ { value: 'Open source', weight: 500 }, { value: 'Every language. One source.', weight: 400 }, ], shader: { materialId: 'paper-gem-smoke', shaderSize: 0.8, opacity: 1, }, effect: { kind: 'bayer', opacity: 0.72, foreground: '#F5F5F2', background: '#111216', }, sequence: { cutCount: 10, finalHoldMs: 5000, pace: 'accelerating' }, export: { width: 1920, fps: 30, quality: 'best', gifLoop: 'seamless' }, }), }); if (!response.ok) throw new Error(await response.text()); const generated = await response.json(); ``` Then run inside the open Design Lab page: ```js await new Promise((resolve) => { if (window.glyphfield?.studio) resolve(); else window.addEventListener('glyphfield:studio-api-ready', resolve, { once: true }); }); let studio = window.glyphfield.studio; if (studio.activeTool() !== 'material') { const ready = new Promise((resolve) => { window.addEventListener('glyphfield:studio-api-ready', resolve, { once: true }); }); studio.activate('Design Lab'); await ready; studio = window.glyphfield.studio; } await studio.applySource(generated.document); const artifact = await studio.invoke('design.export', { format: 'mp4', mode: 'shader-sequence', download: true, }); if (!(artifact.blob instanceof Blob) || artifact.blob.size === 0) { throw new Error('Design Lab returned an empty export.'); } ``` Re-read `window.glyphfield.studio` after switching tools because the active adapter is replaced. ## Edit an existing composition safely [#edit-an-existing-composition-safely] ```js const studio = window.glyphfield.studio; const source = JSON.parse(studio.readSource()); const firstText = Object.values(source.elements) .find((element) => element.kind === 'text'); if (!firstText) throw new Error('No text layer exists.'); firstText.content = 'Updated by an agent'; firstText.style.opacity = 0.88; await studio.applySource(source); const applied = JSON.parse(studio.readSource()); if (applied.elements[firstText.id].content !== 'Updated by an agent') { throw new Error('The source did not round-trip.'); } ``` Preserve unknown fields from the read document. Do not reconstruct the canvas envelope when a targeted edit is sufficient. ## Use a local file [#use-a-local-file] ```js const bytes = await fileHandle.getFile(); const file = new File([bytes], 'mark.svg', { type: 'image/svg+xml' }); window.glyphfield.studio.set('Upload mark', file); ``` Only create a `File` from a source the user authorized. Wait for the preview or source to confirm the asset loaded before exporting. ## Export every supported format [#export-every-supported-format] ```js for (const format of ['png', 'jpg', 'gif', 'mp4']) { const artifact = await window.glyphfield.studio.invoke('design.export', { format, download: true, }); console.log(format, artifact.fileName, artifact.blob.size); } ``` Do not run these exports concurrently. They share live canvases and browser encoder resources. Generate one, verify it, then continue. ## Failure handling [#failure-handling] 1. For HTTP failures, parse `error.code`, `error.field`, and `error.message`. 2. Do not retry unchanged validation input. 3. For Browser API failures, call `describe()` and `controls()` again; the active tool may have changed. 4. If a browser lacks MP4 encoding, report the capability failure and retain the source document; do not silently substitute GIF. 5. If WebGL is unavailable, use a deterministic surface/background fallback only when it still satisfies the requested artifact. --- # Skills moved The installable Glyphfield skill guide now has its own first-class documentation section. Canonical page: /docs/agents/skills Markdown endpoint: /api/docs/agents/skills Skills now have a dedicated top-level documentation tree. Continue to [Skills overview](/docs/skills) for installation, routing, composition patterns, and one guide for every bundled package. --- # Backup and restore Preserve identities, exact editable source, browser-local saves, assets, and rendered artifacts across browsers and Glyphfield versions. Canonical page: /docs/artifacts/backup-and-restore Markdown endpoint: /api/docs/artifacts/backup-and-restore Glyphfield is local-first, not account-synced. Browser storage makes everyday work fast and private, but the browser profile and site origin are not a durable backup. Keep portable source and original assets outside the browser whenever a design must survive device changes, site-data clearing, or a deployment moving to another hostname. ## What needs to be preserved [#what-needs-to-be-preserved] | Data | Normal owner | Portable by itself? | Backup action | | ----------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------- | | Project identity | Browser `localStorage` | Only after copying its validated JSON | Open **Code**, copy the current `BrandIdentity`, and save it as JSON | | Tool drafts and navigation | Browser `localStorage` | No | Copy source from each important source-enabled tool | | Design Lab autosave and named designs | IndexedDB plus a small recovery journal | Not across profiles or origins | Save a named design, then copy the current CanvasDocument from **Code** | | Converted Design Lab assets | IndexedDB and CanvasDocument asset records | Yes only when bytes are embedded | Run export preflight and retain any original file that remains external | | Uploaded images, fonts, Lottie, and audio | Browser memory, object URLs, or embedded records depending on the tool | Not always | Keep the original authorized files beside the source | | PNG, JPG, SVG, GIF, MP4, PDF | Downloaded file | Yes, but not editable | Keep beside source as the approved rendered proof | Closing a Studio tab does not delete a project. Deleting a browser profile, clearing site data, using private browsing, or changing from one origin to another can remove or isolate local state. ## Recommended backup bundle [#recommended-backup-bundle] For every design that matters, keep one folder containing: 1. The active identity JSON. 2. The current tool source JSON or Lottie source. 3. The approved rendered artifact. 4. Original assets and font files that are not embedded in the source. 5. A short note with identity ID, tool name, output dimensions, frame rate, duration, loop mode, and expected audio. 6. License and attribution records for third-party marks, materials, fonts, and source media. Name the files as one set, for example: ```text launch-system/ identity.json design-lab.canvas.json launch-loop.mp4 launch-loop.gif assets/ wordmark.svg campaign-photo.webp display-font.woff2 README.md ``` ## Back up a Design Lab composition [#back-up-a-design-lab-composition] ### In the Studio [#in-the-studio] 1. Open the intended project and **Design Lab**. 2. Wait until the save status reports that the workspace is autosaved. 3. Create a named save so the current state has an explicit checkpoint. 4. Open **Code** and select **Copy**. 5. Save the copied JSON as `design-name.canvas.json` outside the browser. 6. Export one PNG proof at the intended dimensions. 7. If the design moves, export GIF or MP4 and record the selected duration, FPS, quality, and loop mode. The Code drawer is the durable source boundary. A named save is still browser-local and should not be treated as an off-device backup. ### Through the Browser API [#through-the-browser-api] ```js const studio = window.glyphfield.studio; if (studio.activeTool() !== 'material') { throw new Error('Open Design Lab before reading its source.'); } const description = studio.describe(); if (!description.source.read) throw new Error('Source reading is unavailable.'); const source = studio.readSource(); const document = JSON.parse(source); if (document.schemaVersion !== 2) { throw new Error(`Unexpected CanvasDocument schema ${document.schemaVersion}.`); } // Return `source` to the calling agent or save it with the caller's authorized // file interface. Do not write directly into Glyphfield browser storage. ``` Read the source again immediately before backup if a user has continued editing. Do not reconstruct a document from an example or from stale application state. ## Restore a composition [#restore-a-composition] ### In the Studio [#in-the-studio-1] 1. Open the correct project and tool. 2. Open **Code**. 3. Paste the complete saved object. 4. Select **Apply** and resolve any validation error. 5. Confirm the layer count and front-to-back order. 6. Inspect logos, images, fonts, shader frames, converter colors, and output dimensions. 7. Create a new named save only after the restored composition is visually correct. ### Through the Browser API [#through-the-browser-api-1] ```js const studio = window.glyphfield.studio; const before = studio.readSource(); try { await studio.applySource(savedDocument); const restored = JSON.parse(studio.readSource()); if (restored.schemaVersion !== 2) throw new Error('Restore did not normalize.'); } catch (error) { // `before` remains the recovery copy for this operation. throw error; } ``` `applySource()` validates before committing. A failed application should leave the current artifact unchanged, but retain the pre-restore source until the visual result has been verified. ## Move between browsers, devices, or origins [#move-between-browsers-devices-or-origins] Browser storage is scoped by origin and profile. `http://localhost:3012`, a preview deployment, and the production hostname have separate data stores even when they serve the same Git commit. To move safely: 1. Export source and original assets from the old origin. 2. Open the same or a newer compatible Glyphfield version at the new origin. 3. Create or select the intended identity. 4. Apply the identity source first. 5. Open each tool and apply its source. 6. Reattach any non-embedded local font, image, audio, or Lottie file. 7. Re-export a proof and compare it with the approved artifact. Glyphfield does not currently provide a one-click archive of every project, draft, IndexedDB record, and original local file. Treat the source-plus-assets bundle above as the supported transfer path. ## Autosave recovery [#autosave-recovery] Design Lab writes a complete autosave to IndexedDB and maintains a small synchronous recovery journal while a newer write is settling. On the same origin and browser profile, reloading the page can restore the newest consistent draft. If recovery appears stuck: 1. Do not clear site data. 2. Reload the same origin once and wait for the autosave status to settle. 3. Open the expected identity and Design Lab workspace. 4. If source opens, copy it before making more edits. 5. If IndexedDB is blocked, preserve any readable Code source and original files, then continue in a normal browser profile. Cleared site data cannot be reconstructed from Glyphfield unless an external source or artifact backup exists. ## Migration rules [#migration-rules] * CanvasDocument schema 1 is migrated to schema 2 when it parses successfully. * CanvasDocument schema 2 is the current portable scene graph. * Design Lab metadata source version 4 is the current complete composition model. * A `design-sequence` HTTP response contains a version-3 compatibility document. Apply it first, then re-read the normalized CanvasDocument before storing it as the durable source. * Unknown future canvas schema versions are rejected rather than guessed. * Stable IDs, page order, asset records, and unknown metadata should remain intact through any manual edit. See [Version compatibility](/docs/reference/version-compatibility) for the full matrix and [Troubleshooting](/docs/reference/troubleshooting) for recovery failures. ## Restore verification [#restore-verification] A restore is complete only when: * The intended identity and tool are active. * Source applies without validation errors. * Layer count, order, transforms, opacity, and visibility match. * Embedded and local assets resolve. * At least one still export is non-empty and has the expected dimensions. * Motion contains changing frames; seamless GIFs close cleanly; MP4 audio is present when required. * The restored source is copied again after normalization. See [Storage and privacy](/docs/artifacts/storage-and-privacy), [Source code editing](/docs/studio/source-editing), and [Formats and portability](/docs/artifacts/formats-and-portability). --- # Download and use artifacts Export from Studio or the API, verify the result, and integrate SVG, still, motion, PDF, JSON, and Lottie outputs. Canonical page: /docs/artifacts/download-and-use Markdown endpoint: /api/docs/artifacts/download-and-use ## Export from Studio [#export-from-studio] Configure the artifact, inspect the preview, then use the tool's export action. Design Lab offers PNG, JPG, GIF, and MP4; Animation offers GIF and MP4; Brand Book exposes PDF through print/export; other tools expose the formats listed in the [capability matrix](/docs/reference/capability-matrix). For a programmatic Design Lab export: ```js const studio = window.glyphfield.studio; if (studio.activeTool() !== 'material') throw new Error('Open Design Lab first.'); const artifact = await studio.invoke('design.export', { format: 'gif', mode: 'standard', download: false, }); if (!(artifact.blob instanceof Blob) || artifact.blob.size === 0) { throw new Error('Empty GIF export.'); } studio.download(artifact); ``` Do not run browser exports concurrently. Wait for one renderer/encoder job and verify it before starting the next. ## Download raw SVG from the API [#download-raw-svg-from-the-api] ```bash BASE_URL=http://localhost:3012 curl -fsS -X POST "$BASE_URL/api/generate" \ -H 'Content-Type: application/json' \ -d '{ "kind": "template", "template": "slides", "slideLayout": "statement", "texture": "white", "title": "One identity. Every surface.", "identity": { "preset": "gt" }, "output": "raw" }' \ -o gt-statement-slide.svg test -s gt-statement-slide.svg ``` Raw output returns `image/svg+xml` and a deterministic `Content-Disposition` filename. ## Extract SVG from a JSON envelope [#extract-svg-from-a-json-envelope] ```bash curl -fsS -X POST "$BASE_URL/api/generate" \ -H 'Content-Type: application/json' \ -d @request.json \ -o response.json jq -r '.artifact.content' response.json > artifact.svg jq '.artifact | { filename, mimeType, width, height }' response.json test -s artifact.svg ``` ## Integrate SVG [#integrate-svg] The command above writes the file into the current working directory. Copy it into your application's public asset directory before referencing it from HTML or CSS; the example asset is generated output and is not bundled with Glyphfield. ```bash mkdir -p public/brand cp gt-statement-slide.svg public/brand/gt-statement-slide.svg ``` ```html General Translation statement slide ``` ```css .launch-hero { background: center / cover no-repeat url('/brand/launch-background.svg'); } ``` Inline only trusted SVG when internal styling or scripting is required. ## Integrate stills and motion [#integrate-stills-and-motion] * Use PNG for transparency and crisp flat graphics. * Use JPG for smaller opaque images. * Use GIF when the destination requires it; check dimensions, palette artifacts, file size, and seam. * Use MP4 for longer or higher-fidelity motion; include captions/transcripts where relevant and verify audio. * Keep autoplay respectful of `prefers-reduced-motion` and platform policy. ## Use JSON and briefs [#use-json-and-briefs] Element briefs are production specifications, not images. Store them next to the implementation when traceability matters. CanvasDocument or tool source should be treated as editable state and opened/applied through a compatible Studio version rather than rendered by guessing at fields. ## Handoff bundle [#handoff-bundle] A robust handoff contains: 1. Rendered artifact(s). 2. Exact editable source or named Design Lab save. 3. Identity ID/revision. 4. Non-embedded authorized assets/fonts. 5. Output settings and loop/audio expectations. 6. License/attribution notes where required. This is enough for a person or agent to regenerate the work without shifting layers or losing material timing. --- # Formats and portability Understand SVG, PNG, JPG, GIF, MP4, PDF, JSON, Lottie, fonts, assets, loops, and codec boundaries. Canonical page: /docs/artifacts/formats-and-portability Markdown endpoint: /api/docs/artifacts/formats-and-portability ## SVG [#svg] HTTP-generated templates and backgrounds are standalone UTF-8 SVG documents. * Dimensions are fixed on the root SVG. * Authorized data-URL images and bundled marks can be embedded. * Deterministic filters/patterns travel with the file. * Text normally remains text and therefore depends on the documented font stack. * The downloaded file does not depend on the Glyphfield deployment. Keep SVG as the canonical API artifact and rasterize per destination. ## PNG [#png] PNG is a lossless browser still. It preserves transparency where the tool supports it and is appropriate for social images, slide backgrounds, documentation, product surfaces, and archival proofs. Design Lab PNG resolves the complete layer stack: background, shaders at the selected frame, converter effects, text effects, assets, marks, stickers, opacity, blend, and transforms. ## JPG [#jpg] JPG is an opaque Design Lab still. Transparent pixels are composited against the selected canvas background before encoding. Use it when file size matters more than transparency or pixel-perfect flat-color edges. ## GIF [#gif] GIF is palette-based motion and has no audio channel. Glyphfield protects important brand/text colors and can build a global or per-frame palette depending on the export configuration. Two loop modes exist: * **Raw motion** records the requested shader or animation interval without seam correction. Use it for already periodic motion or intentional hard cuts. * **Seamless** captures overlap, blends the tail toward recorded head frames, and verifies closure against the seam anchor. The GIF loop flag only repeats playback; it does not make the last visual state match the first. Inspect the actual seam. ## MP4 [#mp4] MP4 is browser-encoded video for higher color fidelity and motion efficiency. Design Lab encodes the standard live composition or shader-cut sequence. Animation can mix overlapping audio clips into the exported video. Codec availability depends on the browser. If MP4 encoding is unavailable, keep the source and report the limitation; do not silently substitute GIF. ## PDF [#pdf] Brand Book uses the browser print/export path to produce a paginated standards document. PDF is a snapshot of the current identity-derived pages, not the editable source. Re-export after changing the identity. ## JSON and CanvasDocument [#json-and-canvasdocument] JSON may represent: 1. A `BrandIdentity`. 2. An identity-resolved element brief. 3. An API artifact envelope with embedded SVG. 4. A Studio tool's source configuration. 5. A CanvasDocument scene graph. 6. Raw Lottie JSON. Retain `schemaVersion`, tool metadata, stable IDs, asset references, ordering, and unknown fields. Design Lab's current source is CanvasDocument schema 2 with Design Lab metadata source version 4. ## Lottie [#lottie] Raw Lottie JSON can be edited, recolored, and downloaded. A binary `.lottie` archive remains binary and can be replayed/downloaded without being misrepresented as expanded JSON. ## Fonts and assets [#fonts-and-assets] Browser-local fonts and object URLs are not automatically portable. A rendered PNG/JPG/GIF/MP4 captures their visible result, but an editable JSON document may still require the original authorized bytes. Embedded data URLs increase document size but improve portability. For durable handoff, preserve: * The editable source or saved design. * Authorized original images and fonts not embedded in source. * The rendered artifact. * The requested dimensions, frame rate, duration, loop mode, and codec expectations. * Attribution/license records for upstream shader and material sources. See [Storage and privacy](/docs/artifacts/storage-and-privacy) and [Source formats](/docs/reference/source-formats). --- # Artifacts Choose, produce, verify, preserve, and reuse every Glyphfield output format. Canonical page: /docs/artifacts Markdown endpoint: /api/docs/artifacts An artifact is a portable result produced from an identity and an exact configuration. Keep the editable source beside the rendered output whenever the work may need another size, language, material frame, or motion encoding later. ## Output map [#output-map] | Output | Produced by | Best use | | --------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | SVG | HTTP backgrounds and templates | Canonical deterministic vector artifact, source control, downstream rasterization | | PNG | Design Lab, Moodboard, Lottie frame, OpenGraph, Terminal, Partnership, Blog, Slides | Lossless stills, transparency, exact browser composition | | JPG | Design Lab | Smaller opaque photographic/material stills | | GIF | Design Lab and Animation | Portable short motion, email/docs, transparent or palette-constrained loops | | MP4 | Design Lab and Animation | Higher-fidelity motion; Animation can include mixed audio | | PDF | Brand book print/export | Shareable identity standards snapshot | | JSON | Identities, briefs, source documents, Lottie | Editing, automation, handoff, regeneration | | `.lottie` | Lottie | Original compact vector animation archive | ## Production paths [#production-paths] ### Deterministic HTTP [#deterministic-http] Use `POST /api/generate` for repeatable SVG, structured briefs, and apply-ready Design Lab sequence source. The request is validated against the current GET contract and does not silently alter a browser project. ### Authentic browser rendering [#authentic-browser-rendering] Use Studio or `window.glyphfield.studio` when the output depends on Canvas, WebGL, local files, local fonts, visual transforms, Lottie, frame capture, or browser codecs. Programmatic export uses the same live renderer as the visible UI. ### Combined [#combined] Generate a Design Lab document through HTTP, apply it in the browser, inspect it, then export PNG/JPG/GIF/MP4. This separates deterministic authoring from authentic rendering without creating two visual implementations. ## Definition of done [#definition-of-done] For every artifact: 1. Confirm the intended identity and source revision. 2. Inspect the rendered composition when visual output is requested. 3. Confirm dimensions, format, transparency/opacity, and filename. 4. Require a non-empty response body or Blob. 5. For motion, inspect multiple frames and the loop seam; for MP4 audio, confirm the track. 6. Retain the portable source or named saved design when regeneration matters. Continue with [Formats and portability](/docs/artifacts/formats-and-portability), [Download and use artifacts](/docs/artifacts/download-and-use), and [Backup and restore](/docs/artifacts/backup-and-restore). --- # Storage and privacy Understand browser persistence, API request processing, local assets, and source licensing. Canonical page: /docs/artifacts/storage-and-privacy Markdown endpoint: /api/docs/artifacts/storage-and-privacy ## Browser projects [#browser-projects] The Studio stores projects, active tabs, most tool drafts, appearance, and canvas view state in browser `localStorage`. Design Lab named designs, complete autosaves, and converted assets use IndexedDB. A small localStorage recovery journal protects the newest portable Design Lab source during unload and is cleared after IndexedDB catches up. Data is scoped to the current origin and browser profile. Closing a project tab does not delete the project. Deleting a custom project removes it from the Studio’s stored project list. ## Local files [#local-files] Uploaded images, logos, fonts, Lottie files, and shader inputs are loaded by the browser. Some are represented by temporary object URLs for the current page session; converted assets and portable canvas records may store embedded data locally. A downloaded artifact captures or embeds the selected visual input where its format allows it. Clearing site data can remove projects, drafts, saved designs, and converted assets. Export identity/source documents and original authorized files before clearing the origin when the work must survive. Named saves and autosaves are recovery conveniences inside the current browser, not off-device backups. Follow [Backup and restore](/docs/artifacts/backup-and-restore) for a durable source-plus-assets bundle. ## Agent requests [#agent-requests] `POST /api/generate` processes request data in memory and does not persist the submitted identity or asset. The route responds with `Cache-Control: no-store`. GET discovery endpoints are public and cacheable for a short period. The generation route supports CORS with `Access-Control-Allow-Origin: *`. ## Asset boundaries [#asset-boundaries] * Submit only assets you are authorized to process. * Remote URLs are not fetched. * Custom assets must be supplied as supported base64 data URLs. * A request body may not exceed 5 MB. * Bundled GT and reference-brand assets remain the property of their respective owners. ## License [#license] Glyphfield source is open-source software released under the MIT License. You may use, copy, modify, merge, publish, distribute, sublicense, and sell the software subject to the notice and warranty terms in `LICENSE`. The software license does not transfer rights in bundled third-party marks, reference-brand assets, or assets submitted by users. --- # Accessibility Use and extend Glyphfield with keyboard access, visible focus, semantic controls, reduced motion, contrast, and accessible exported artifacts. Canonical page: /docs/reference/accessibility Markdown endpoint: /api/docs/reference/accessibility Glyphfield combines ordinary document UI with direct-manipulation canvases and animated GPU output. Accessibility therefore has two boundaries: operating the Studio itself and making the exported artifact usable in its destination. ## Interaction model [#interaction-model] * Navigation, buttons, selects, fields, dialogs, drawers, tabs, and layer actions should expose visible labels or accessible names. * The visual canvas is paired with a layer list and inspector so geometry and appearance are not controlled only by pointer gestures. * Selected canvas items support arrow-key movement; Shift + arrow performs a larger nudge. * Global Studio and documentation search expose keyboard shortcuts described in [Keyboard shortcuts](/docs/reference/shortcuts). * Source-enabled tools provide a Code drawer for exact structured editing when direct manipulation is insufficient. The current product is not represented as having completed a formal accessibility certification. Treat the guidance and checks below as the maintained contract and report gaps rather than assuming conformance. ## Keyboard workflow [#keyboard-workflow] 1. Use Studio navigation or search to open a tool. 2. Tab through the library, canvas-adjacent controls, inspector, and layer dock. 3. Select a layer from the list when selecting it visually is difficult. 4. Use arrow keys for precise movement and inspector fields for numeric changes. 5. Open **Code** for exact source edits. 6. Return focus to the invoking control when closing menus, dialogs, or drawers. Do not make hover the only way to reveal a required action. Reordering, visibility, duplication, deletion, and export must remain reachable without dragging. ## Focus and labels [#focus-and-labels] Shared Studio components use semantic control roles and accessible labels as part of both human accessibility and Browser API automation. A missing label is therefore two bugs: assistive technology cannot name the control, and an agent cannot address it reliably through `controls()`. When adding or changing a control: * Give icon-only controls an `aria-label`. * Associate form labels with their input. * Preserve visible focus indicators against light and dark surfaces. * Keep disabled state semantic, not only visual. * Announce validation and export failures near the operation that caused them. * Avoid focus traps outside intentional modal/dialog behavior. ## Motion [#motion] Automatic previews should respect reduced-motion intent by pausing, simplifying, or holding on a representative frame where practical. Offscreen and hidden live-material previews pause independently for performance. Exporting motion is an explicit action, so the file can still contain animation. When using it elsewhere: * Provide a still alternative. * Avoid forced autoplay when the destination can honor `prefers-reduced-motion`. * Add pause/stop controls for long or repeating motion. * Avoid rapid flashes and inspect the complete loop, not only the first frame. * Provide captions or a transcript when audio carries meaning. ## Color and contrast [#color-and-contrast] Glyphfield exposes brand colors faithfully, including combinations that may not meet the needs of every destination. Verify the artifact in context. * Check text and essential marks against every shader/material frame they cross. * Use the sticker inner separation edge when white artwork meets a white border. * Prefer explicit converter foreground/background colors over accidental transparency. * Check focus and selected-state contrast in both Studio themes. * Do not encode status using color alone. Generated graphics can be brand-correct and still be inaccessible for a specific use. The publishing product owns final contrast requirements. ## Images, video, and documents [#images-video-and-documents] Exports do not create surrounding semantic HTML automatically. | Artifact | Accessibility responsibility | | ----------- | ----------------------------------------------------------------------------------------------------------------- | | PNG/JPG/SVG | Supply concise alternative text in the destination; use empty alt text for decorative images | | GIF | Provide an equivalent still or description and avoid essential information that appears only briefly | | MP4 | Provide captions/transcript where relevant, controls, and a reduced-motion alternative | | PDF | Check reading order, headings, links, color, and selectable text in the final browser-produced PDF | | Lottie | Provide a fallback, accessible name in the host UI, and reduced-motion behavior | | JSON/source | Document the schema and validation errors; source is not an accessible replacement for the rendered communication | ## Canvas limitations [#canvas-limitations] A rendered canvas does not expose its pixels as a semantic document tree. The layer list, inspectors, source drawer, labels, and keyboard commands are the accessible control surface. Visual content still requires human review or an equivalent described artifact. When a task depends on visual judgment—alignment, contrast over animation, legibility, or loop flashing—source validation alone is insufficient. ## Contributor acceptance checklist [#contributor-acceptance-checklist] Before shipping a Studio interaction: 1. Navigate to it and operate it using only the keyboard. 2. Confirm every control has a meaningful accessible name. 3. Confirm focus remains visible and returns predictably after overlays close. 4. Test at browser zoom and narrow viewport widths. 5. Test light/dark themes and reduced-motion preference. 6. Confirm status/error changes are exposed as text. 7. Confirm the equivalent Browser API control/action remains discoverable. 8. Inspect the exported artifact for contrast, motion, and media alternatives. See [Editor systems](/docs/studio/editor-systems), [Browser API](/docs/reference/browser-api), and [Contributing](/docs/contributing). --- # API security Operate Glyphfield's public generation API with bounded inputs, no remote fetching, explicit CORS, rate limiting, and deployment verification. Canonical page: /docs/reference/api-security Markdown endpoint: /api/docs/reference/api-security `POST /api/generate` is intentionally public and unauthenticated. Security is split between application validation in the repository and request-volume controls at the production edge. Both are required; neither replaces the other. ## Threat and control map [#threat-and-control-map] | Risk | Repository control | Deployment control | | --------------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | Oversized work | Request and data-URL bodies are limited to 5 MB; background geometry and total pixels are bounded | Proxy/body limits should fail clearly before excessive serverless work | | Unexpected request fields | Unknown top-level fields fail with `400 unknown_field` | Log repeated invalid traffic without storing submitted assets unnecessarily | | Remote file access | Remote asset URLs are rejected; supported custom assets use authorized data URLs | Egress policy can provide another boundary where available | | Repeated generation abuse | Deterministic route validation reduces wasted work | IP-keyed rate limit on `POST /api/generate` before serverless execution | | Browser-local data exposure | The HTTP generator does not read Studio localStorage or IndexedDB | Keep the app on trusted HTTPS origins and control third-party script access | | Stale or shared responses | Generation returns `Cache-Control: no-store` | Do not override it with CDN caching | ## Application-owned validation [#application-owned-validation] The route owns request shape, content size, and generator-specific bounds: * JSON requests require `Content-Type: application/json`. * The request body and supported data-URL assets are limited to 5 MB. * Background width and height are limited to the documented range and 12,000,000 total pixels. * Remote URLs are unsupported. * Unknown top-level fields are rejected instead of ignored. * Malformed or invalid requests return structured errors without mutating browser projects. * Submitted identity and asset data are processed in memory and are not persisted by the generation route. Read `GET /api/generate` and `/openapi.json` before sending a request. Do not weaken validators to make an outdated client appear compatible. ## CORS [#cors] Discovery and generation endpoints expose explicit cross-origin response headers. `Access-Control-Allow-Origin: *` makes the public contract callable from another origin; it is not authentication and should not be combined with an assumption that callers are trusted. If a private deployment requires authentication, add it as a deliberate deployment/application contract and update: 1. OPTIONS behavior and allowed headers. 2. OpenAPI security schemes. 3. `/api/agent` policies and examples. 4. Browser and server clients. 5. Error handling and documentation. Do not silently add a cookie requirement to public examples. ## Production rate limiting [#production-rate-limiting] The General Translation production deployment expects an edge firewall rule that matches only `POST /api/generate`, uses an IP-keyed fixed window of 10 requests per 60 seconds, returns `429` after the limit, and keeps the client limited for one minute. The firewall is provider project state, not repository state. A deployment administrator must inspect it separately: ```bash vercel firewall overview --project glyphfield --scope general-translation --json vercel firewall rules list --project glyphfield --scope general-translation --json vercel firewall diff --project glyphfield --scope general-translation --json ``` If the rule is absent, create the intended change and inspect the diff before publication: ```bash vercel firewall rules add "Rate limit Glyphfield generation" \ --description "Bound unauthenticated generation before serverless execution." \ --condition '{"type":"path","op":"eq","value":"/api/generate"}' \ --condition '{"type":"method","op":"eq","value":"POST"}' \ --action rate_limit \ --rate-limit-algo fixed_window \ --rate-limit-keys ip \ --rate-limit-requests 10 \ --rate-limit-window 60 \ --rate-limit-action rate_limit \ --duration 1m \ --yes \ --project glyphfield \ --scope general-translation ``` Publication changes live infrastructure and belongs to an authorized administrator. After publication, confirm that the eleventh request from one client inside the window receives `429` and that normal requests resume after the window. Other hosts should implement an equivalent bound appropriate to their traffic model rather than copying provider-specific commands blindly. ## Browser API security boundary [#browser-api-security-boundary] `window.glyphfield.studio` operates the active browser project. It can read/apply source, interact with controls, handle local files supplied as authorized `File` objects, and return downloadable artifacts. * Do not inject untrusted scripts into the Studio origin. * Do not pass arbitrary filesystem path strings to file controls. * Do not write directly to localStorage, IndexedDB, or React internals. * Do not expose a returned Blob or copied source beyond the user's authorized destination. * Treat imported SVG, font, image, audio, and Lottie content as user-supplied data. The HTTP generation API cannot silently access this browser-local state. ## Logging and privacy [#logging-and-privacy] Operational logs should retain enough information to diagnose route, status, duration, and request class without storing complete user identities, embedded data URLs, or generated artifact bodies. Redact authorization headers if a private deployment adds them. For a reportable failure, prefer: * Request kind and response error code. * Dimensions and approximate body size. * Deployed commit/version and route. * Whether the failure occurred before validation or during generation. Do not paste proprietary source or binary data into a public issue. ## Security verification [#security-verification] Before release: 1. Confirm valid discovery and generation requests succeed. 2. Confirm malformed JSON returns 400. 3. Confirm wrong content type returns 415. 4. Confirm oversized input returns 413. 5. Confirm unknown fields and remote URLs are rejected. 6. Confirm generation responses remain `no-store`. 7. Confirm edge rate limiting is active in production. 8. Confirm browser-local projects are not returned by any HTTP route. See [Errors and limits](/docs/agents/errors), [Endpoint reference](/docs/reference/endpoints), and [Self-hosting](/docs/reference/self-hosting). --- # Studio Browser API Operate every visible Studio control, round-trip source documents, and export authentic browser-rendered artifacts. Canonical page: /docs/reference/browser-api Markdown endpoint: /api/docs/reference/browser-api The active Studio tool registers `window.glyphfield.studio`. This API is the programmatic equivalent of the visible workspace and intentionally uses the same controls, source validators, project state, renderers, and export actions. ## Lifecycle [#lifecycle] The global is replaced whenever the active tool changes. Glyphfield dispatches `glyphfield:studio-api-ready` with `studio.describe()` as event detail after each adapter is registered. ```js await new Promise((resolve) => { if (window.glyphfield?.studio) resolve(); else window.addEventListener('glyphfield:studio-api-ready', resolve, { once: true }); }); ``` When automation activates another tool, subscribe before the click, wait for the event, then read `window.glyphfield.studio` again. ## Core methods [#core-methods] | Method | Result | Use | | ------------------------ | --------------------------------------------- | --------------------------------------------------------------------------- | | `activeTool()` | Studio tool ID | Confirm the adapter matches the intended tool | | `describe()` | Version, tool ID, source support, action list | Discover before invoking | | `controls()` | Visible control labels, kinds, and values | Inspect the actual UI contract | | `activate(label)` | `void` | Click a visible button, tab, or role button by exact accessible label | | `set(label, value)` | `void` | Change an input, textarea, select, checkbox, contenteditable, or file input | | `readSource()` | JSON string | Read the active tool's exact source document | | `applySource(source)` | `Promise` | Validate and apply a JSON object or string, then wait for the React commit | | `invoke(action, input?)` | `Promise` | Run standard or tool-specific actions | | `download(artifact)` | `void` | Save a returned `{ blob, fileName }` artifact | ## Standard actions [#standard-actions] Every adapter supports these through `invoke` when the corresponding capability exists: ```text source.read source.apply controls.list control.activate control.set artifact.download ``` `source.read` and `source.apply` fail clearly when the active tool does not expose source. Use `describe().source` to check first. ## Accessible control contract [#accessible-control-contract] `controls()` discovers enabled `button`, `input`, `textarea`, `select`, `[role="button"]`, and `[role="textbox"]` elements. Labels resolve in this order: 1. `aria-label` 2. `title` 3. `name` 4. `aria-labelledby` 5. Wrapping `