Website building
Build the company website on Cargo and serve it on your own domain: a statically exported Next.js app, one defineApp with its www hostname, and a defineDomain that publishes the records and forwards the apex, changed only through reviewed pull requests.
Set up the website-building cookbook in this project.
1. If the Cargo CLI is not installed yet, follow every step in https://api.getcargo.io/INSTALL.md
2. From the Cargo project, run: cargo-ai cdk add cookbook/website-building
3. Then follow .claude/skills/website-building/SKILL.md. Stop for my approval before any paid call, and stop at "cargo-ai project plan" before deploying anything.$cargo-ai cdk add cookbook/website-buildingSay this to your agent
Build our company website on Cargo from our brand guide and serve it on www.fabrikam.example. Our DNS is hosted elsewhere.
Illustrative output #
Fictional records, to show the shape of what comes back.
PR #12 Website: home, about and pricing from the brand guide merged after review
app:website deployed Routing: static
https://website-1a2b3c4d.app.getcargo.run/pricing/ Pricing | Fabrikam
www.fabrikam.example pending: _cargo-verify not resolved
DNS is hosted elsewhere, so infra/domains/website.ts was deleted. Add at the provider:
TXT _cargo-verify.www cargo-verify=9c1e4a…
CNAME _3f2a91.www _7b0c44.acm-validations.aws
CNAME www d1x2y3z4.cloudfront.net
apex fabrikam.example → https://www.fabrikam.example (provider redirect)
Once the TXT resolves, www.fabrikam.example serves the reviewed pages with their own canonical
URLs, and the next change to the site is another pull request.
Done when #
node --import tsx evals/contract.mjspasses: one app in thewebsite-building-appsfolder with awwwhostname and a static-export build, and either no domain or an adopted domain whosednsRecordsholds the app’sdomainRecordsand whose apex forwards towwwnpm ci && npm run check && npm run buildin the app writesdist/index.html,dist/about/index.html,dist/robots.txtanddist/sitemap.xml, each page with its own title, description and canonical in the initial HTML- the operator reviewed the local preview: every changed page at 1440 and 390 pixels wide with no horizontal scroll, reachable by keyboard with visible focus, readable in both themes, with no console errors or failed requests
- the mailbox check is recorded, or the domain file was deleted
cargo-ai cdk planshows the folder, the app and the domain (or no domain) as an adopt, not a create, and the operator approved it- the deploy log says
Routing: static, and the Cargo URL serves/aboutand/about/directly https://www.<domain>/serves the site in an anonymous session with a valid certificate, the apex redirects to it, and pages carry it as their canonical URL; a pending TXT is reported as pendingsite.jsonisreadyonly for approved content, and a content change reaches the site through one reviewed pull request whose plan shows the same app with a new content hash
What it costs #
Each merge is one deployment of a static app; read the workspace’s current hosting usage before
the first deploy, and say what you found. Adopting a domain the workspace owns adds no charge.
Registering one (register-domain) charges workspace credits once and is not refundable: read
the current price and the credit balance before proposing it, and quote both with the plan. A
working form adds whatever its backend costs. Nothing in the workspace runs on a schedule; your
coding agent’s usage is the rest.
The company website, hosted by Cargo and served on the company’s own domain. A statically
exported Next.js app, the www hostname on it, and a domain that publishes its records and
forwards the apex. Every change is a pull request your coding agent writes and someone reviews;
nothing else is deployed.
What it does #
- Hosts the site.
defineAppuploads the Next.js package; Cargo runs its build and serves every page as prerendered HTML at its own URL. - Serves it on the company’s name.
domains: ["www.…"]attaches the hostname. Cargo’s own URL staysnoindex; the company domain is the one search engines index. - Publishes the records, or tells you what to add. With Cargo holding the DNS,
defineDomainpublishes the app’sdomainRecordsand forwards the apex towww. With the DNS at another provider, the domain file is deleted and the records are added there. - Stays reviewable. Content lives in
site.jsonand the pages inapp/. A change is a diff, a preview and a plan before it is a deploy.
How it works #
flowchart TD
pr["pull request<br/>site.json, app/"] --> plan["cargo-ai cdk plan"]
plan --> app["defineApp website<br/>next build → dist/"]
app --> host["www hostname<br/>_cargo-verify TXT"]
app -->|"domainRecords"| domain["defineDomain<br/>whole zone, apex → www"]
app -.->|"DNS elsewhere"| provider["records added<br/>at the provider"]
- A pull request changes the content or the pages; the app builds locally to
dist/. - The plan shows the app’s new content hash; the deploy uploads the package and Cargo
builds it, routing statically because pages are exported as
<route>/index.html. - The hostname is attached on deploy and verified once its
_cargo-verifyTXT resolves. - The domain publishes the TXT, the certificate-validation CNAME and the
wwwCNAME, and forwards the apex towww.
Adds 2 resource kinds plus the folder they file into.
| File | Resource | Role |
|---|---|---|
infra/apps/website.ts | defineApp | the website and its www hostname |
infra/apps/website/ | (not a resource) | the Next.js package Cargo builds: pages, site.json, tokens |
infra/domains/website.ts | defineDomain | the zone and the apex redirect; deleted when DNS lives elsewhere |
infra/folders/index.ts | defineFolder | the app folder named after the skill |
references/ | (not a resource) | how to brief, build, capture the design and serve the domain |
Why a static export #
Cargo Hosting serves files. A static export gives every page real HTML, its own metadata and a
URL that works when entered directly, with no server to run. trailingSlash: true writes each
page as <route>/index.html, which is what Cargo’s build detects to route statically; without it,
/about serves the home page. What needs a server (route handlers, middleware, image
optimization, a form that delivers) lives somewhere else and is called from the page.
Why a domain file you might delete #
dnsRecords is the whole zone. That is what lets one deploy publish everything the hostname
needs, and it is also why the file is dangerous on the wrong domain: a zone Cargo mailboxes send
from loses its mail records. Most existing company domains keep their DNS at a provider, so for
them the file goes and the three records are added by hand. A dedicated domain held by Cargo
keeps the file.
Placeholders (edit before deploy) #
- Hostname —
infra/apps/website.ts:domains, always thewwwhost. - Domain —
infra/domains/website.ts: the name and the redirect, or delete the file. - Content —
infra/apps/website/site.json: approved company facts,canonicalUrlset tohttps://www.<domain>/,status: "ready"only after review.
What it does not do #
It does not deploy without a reviewed plan, buy a domain without an approved plan line, touch a zone that carries mail, connect a form to a backend nobody chose, or publish a draft.