Build a CMS website
Give an agent the DynoStatic installation URL and this guide. It can build or convert a website using the installed documentation and authenticated APIs; it does not need the DynoStatic source repository or an external skill. Preserve an existing site's design and hosting unless the owner requests a change.
Discover the installation
Read integration.php at the installation root. Its version identifies the
installed product; agent is the versioned dynostatic.integration-guide contract.
Follow its absolute guide and API links, which include any installation subfolder.
The public manifest contains product capabilities, not configured website data
or the permissions of a particular user. The optional SKILL.md
and llms.txt lead to these same contracts.
For an older installation without agent, use its available CMS and Automation
guides and authenticated discovery. Do not assume a newer feature exists. A
missing capability is a concrete compatibility gap; do not work around it with
raw database writes or an unrestricted remote execution endpoint.
Use physical gateways on hosts without rewrites: append api/?action=… or
admin/?page=… to the complete installation URL. Preserve the subfolder. Read
these contracts as needed:
| Task | Contract |
|---|---|
| Read published content during builds | Content API, cms.manifest |
| Import or manage website resources | Automation API, automation.capabilities |
| Group and refresh translated variants | Source-managed translations |
| Render widget-managed fields in an existing website | Website forms |
| Connect repository builds and Worker hosting | Cloudflare website builds |
| Add runtime interactive widgets | Embedding and styling |
Choose what DynoStatic manages
| Mode | Where the visitor's page comes from | How an edit becomes visible |
|---|---|---|
| Widget embed | The host page plus DynoStatic's runtime widget | Publish the widget; no host rebuild is normally needed for widget content |
| Headless website | The site's own Astro or other static build | Publish CMS content, deliver a build hook, fetch current publications, build and deploy |
| Native Site publishing | DynoStatic's trusted static templates | Create an immutable release/export, then deliver that artifact |
An existing custom Astro design usually uses the headless mode. Runtime widgets can coexist with it. An editing workspace and an immutable publication capture are useful inputs, but neither automatically fetches later publications. A hook that rebuilds old local files does not create a live CMS connection.
Preserve and map the existing site
Inspect repository instructions, current edits and actual deployment configuration. Inventory the repository/branch, provider account, build command, output directory, routes, redirects, canonical URLs, structured data, locale variants, photographs, shared content, forms and dynamic handlers. Keep user-authored edits. Discover the real host account and deployment mode instead of inferring them from a project name.
Model each human-editable page as a Pages entry with meaningful content, image and
SEO fields. Use the pages collection or the page collection selected in Site
publishing. Repeated business data, navigation, services and testimonials can remain
shared collections/singletons. A site registration or one large copy JSON field
does not give editors a useful list of pages. Keep the frontend layout in code
when the owner wants content and SEO editing without a section builder.
Declare every supported locale and preserve each localized route. Use native
translation groups to link the same page across languages. Derive alternate links
from those mappings, not from English path guesses. Preserve explicit display
order, image alternatives and translation placeholders such as {city} or {year}.
Resolve missing locale content deliberately before import.
Field keys use lowercase ASCII identifiers: map existing camelCase keys in both
the import and frontend adapter. Disable native routes for data-only schemas when
the frontend owns routing; cms.routes is then not a complete inventory of the
external site's pages. Upload originals through supported media operations and
retain real media identities and transfer hashes.
Use the existing visual/code editor for formatted text. Text fields declare
editor: inline_html for short inline copy or editor: rich_html for block content.
Leave plain strings plain. Match the frontend's allowed tags and attributes to
the declared contract; do not globally decode entities or render every CMS string
as HTML. Reuse DynoStatic's editor rather than adding an unrelated editor dependency.
Import safely through supported operations
Select the exact website and verify its identity. An Automation token manages resources; a Content API token reads build data. They are not interchangeable. Discover installed capabilities and granted actions first. Start with read access; use proposal or write scopes only for the operations needed and authorized.
Preview the inventory and mappings before importing. Use bounded changesets, revision preconditions, supported media uploads and normal publication operations. Discover exact commands and limits instead of guessing payloads. Never insert CMS table rows directly: revisions, publication snapshots, dependencies, audit history and queued events are part of the operation.
Make retries inert and refuse to overwrite later editor changes. When revisiting an imported site, start from its current publications, not the original seed. Verify substantial imports with isolated fixtures before writing live data. Defer enabling the build hook until bulk import completes. Follow the owner's existing deployment and backup instructions; maintenance access is not a routine integration prerequisite.
Organize translations beneath the source
Choose independent editing when humans maintain each language separately. Choose source-managed policies when target variants follow one authored source. The source language is configurable; do not assume English for every installation.
Before activation, link native translation groups and resolve unpublished target drafts. Classify fields as Translate, Copy from source or Keep locale-specific. Keep localized slugs/URLs; copy facts and media where appropriate. Preserve existing AI-written translations. Activation organizes existing variants without rewriting them or pretending their source revision is known.
In source-managed mode, editors work on source entries and see variants and update status beneath them. Publish the source, export queued requests, rewrite only the translation values, then import and publish the completed batch. Preserve all identities, hashes, supported HTML and placeholders. Re-export after a stale-state conflict. Do not bypass read-only generated variants with ordinary entry writes.
Manual and external AI rewriting use the same translation contract. This release does not execute translation-service APIs. Future provider adapters can fulfill that contract; documenting it does not configure a provider. Existing page translations remain published while refreshes are prepared. Website forms apply the stricter completeness rule described below.
Fetch current publications on every build
Use a private website-bound content:read token in the local protected environment
and the host's build secrets. Never prefix it with PUBLIC_ or place it in
browser JavaScript, generated HTML, URLs, logs or deployment receipts. Do not send
browser Origin headers to the Content API.
The build adapter must:
- Fetch
cms.manifest, verify itssite_idagainst the configured website, and check the needed schemas/actions/locales. - Read required singletons and every collection page for every required locale. Follow opaque cursors until exhausted; validate expected inventory, routes, ordering, field shapes, formatting, placeholders and media identities.
- Include published translation groups and any required
cms.formresponses. Fetch referenced media from the trusted same-origin Content API. Do not forward a bearer token to arbitrary media URLs or across redirects. - Validate a complete candidate before replacing generated build input. Fail on missing credentials, HTTP errors, unpublished required content, duplicates, incomplete translations or inconsistent reads. Production must not silently fall back to migration seeds or yesterday's content.
- Run the fresh-content step in the actual host build command. If it is an npm
prebuildstep, usenpm run build; invoking Astro directly bypasses it.
Content collections have best-effort pagination. A maximum content_version or a
single ETag does not prove a multi-request atomic capture. Compare complete
publication inventories/captures and refuse observed changes. This detects races
but does not create transaction-wide snapshot semantics. Use a supported immutable
release when an atomic snapshot is required.
Escape normal text and serialize JSON-LD with < escaped. Validate allowed
formatting before using Astro set:html. Leave the last successful deployment
serving when a new build fails.
Choose where images are served
An image URL in CMS content, or an embedded gallery, does not automatically become a Cloudflare asset. Choose and verify the delivery path:
- Remote URLs: the page uses the published media URL and that URL's host serves the bytes. Keep the origin dependency explicit.
- Build assets: download verified originals, optimize them during the site's build and deploy the outputs with the website. The website's asset host serves those bytes; CMS originals remain available for future edits/builds.
Use MIME/size limits, hashes and deterministic filenames for downloads. Remove
unused generated images only after validating the new capture. For Astro, verify
that generated imports include the downloaded directory. With Vite versions that
skip hidden directories, a narrow glob with exhaustive: true is needed. Set both
the primary image width and responsive widths; a srcset alone does not bound the
fallback image. Check the actual emitted URLs, dimensions and file sizes.
Photo galleries support adding and ordering items. Connecting a gallery widget's
ordered items to an external static build still requires a site adapter; widget
catalog readiness is not a generic export API. Do not invent cms.gallery or
claim every widget has a Content API equivalent. A CMS collection of image refs
is another supported model for an Astro gallery. Native static exports have their
own media options described in the CMS guide.
Let the widget manage fields and the website handle submissions
Select the contact widget's Website Worker mode when the site should retain
its renderer, /api/contact, Turnstile, Resend/MXRoute or other existing transport.
The widget supplies the published form definition; it does not move mail secrets
or submissions into DynoStatic's inbox.
Follow the website's Pages languages. The builder displays inherited language names and a link to shared language settings; a separate comma-separated list is unnecessary. Without Pages, use the named source selector and target checkboxes. Edit the source form, publish, and complete its queued translation batches.
Fetch cms.form using content:read. Bundle the same complete definition and
revision into the frontend and server validator. Share field keys, option values
and validation rules; translate labels, help, captions and feedback, never visitor
answers. Reject unsupported form features rather than silently dropping them.
HTTP 409 form_translations_pending must fail the build and retain the previous
deployment. An old browser revision must receive stale_form before provider calls.
Use the form contract and its dependency-free runtime example. Validate server-side before spam checks and sending mail. Keep provider credentials in Worker runtime secrets. Verify failure paths with mocked delivery; sending real contact messages is a separate authorized action.
Prove automatic publishing
The complete path is publish → queued webhook → delivery → host build → fresh CMS capture → deployment → public result. Configure the selected website's hook for required content publication, removal, translation, schema and media events. Read the installed event catalog and subscribe to changes consumed by the adapter. For Cloudflare-specific steps, use Cloudflare website builds.
Verify a functioning job runner. The optional probabilistic web runner is
best-effort; a hosting cron running bin/dynostatic cron is recommended for timely
delivery. A successful hook response proves delivery, not a completed build.
Check the provider's final result and the public artifact. A credential-free
receipt with fetch time, publication digest and form revision can make this proof
inspectable without exposing tokens or content bodies.
Before completion, verify editable Pages, source/target organization, locale routes and SEO, representative desktop/mobile rendering, built images and existing form behavior. Exercise safe import retries and refusal of later-edit overwrites when an import is involved. Use focused checks appropriate to the change.
Report separately what is imported, built locally, deployed, and proven to update automatically. Record concrete remaining provider access, cron or DNS work. Keep a site-specific conversion log with mappings, configuration names, validation and open items. Product defect history belongs in the product log, not in reusable instructions that tell every future site to patch the CMS.