The Site module is AppEngine's CMS and deployment layer. A site is a deployable web property attached to an org — pages, theme, navigation, domain, container — and the module covers creating and removing sites, mapping them to custom domains, wiring SSL, and deploying or scaling the underlying container in Kubernetes. It also runs dev environments for in-cloud development workflows.
Site CRUD
/site/addJWT/site/removeJWT/site/create-siteJWT/site/clone-siteJWT/site/delete-site/:siteOrgId/:siteIdJWTadd is the modern endpoint with plan validation — checks that the org's plan allows another site before creating. create-site is the older path without validation. remove parallels add and optionally cleans up the K8s resources. clone-site deep-copies an existing site for templating.
await fetch('/api/site/add', {
method: 'POST',
headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
body: JSON.stringify({
siteName: 'spring-2026',
title: 'Spring Collection',
description: 'Our spring 2026 lookbook',
template: 'lookbook-modern',
domainName: 'spring.example.com',
publishedPagesOnly: false,
}),
});
siteName is lowercase kebab-case and immutable after creation. domainName is optional — without it the site lives at the org's default subdomain (my-org.appmint.app).
Reading sites
/site/get-site/:configSiteName/:domainName?JWT/site/get-site-by-hostname/:hostname?JWT/site/get-site-host-mappings/:siteName?JWT/site/org-sites/:siteOrgIdJWT/site/get-org/:domainNameJWTget-site-by-hostname is what the AppEngine edge layer calls on every request — given a hostname, return the site config plus the org. This is the routing primitive the platform's CDN/proxy uses to send traffic to the right K8s deployment. get-org does the same lookup but returns just the org info (used by SSO callbacks where only org context is needed).
Domains
/site/attach-domainJWT/site/update-domain/:domain?JWT/site/remove-domain/:domain?JWT/site/change-site-domain-namesJWT/site/unregister-site-domain/:siteId/:domainNameJWT/site/fix-domainsJWTattach-domain registers a domain → site mapping. The platform creates a Cloudflare DNS record (CNAME → the K8s ingress) and an SSL cert. fix-domains re-syncs domain mappings with Cloudflare — useful after manual DNS changes or when reconnecting a previously-registered domain.
The DNS provider is configurable per-org but defaults to Cloudflare. Plan-based limits control whether custom domains are allowed at all (free plan typically restricts to subdomains).
Pages and content
/site/page/:hostName/:siteName/*JWT/site/page/:hostName/:siteName/*JWT/site/page-data/:datatype/:dataId?JWT/site/site-mapJWT/site/app/dsl/:nameNo authpage/... returns the page's content tree — rendered by the storefront or admin UI. page-data is the data-layer fetch shorthand for any page-bound collection. site-map returns or generates the sitemap for SEO. app/dsl returns the site's app DSL (Domain Specific Language config) — public because the customer-facing app needs it without auth.
Templates
/site/apply-templateJWTApply a named template to an existing site. Copies pages, navigation, theme, and settings; doesn't overwrite content already created by the user (config defaults are merged, not replaced).
Plan validation
/site/usage-statsJWT/site/plan-limitsJWTplan-limits returns the org's quotas (max sites, max dev environments, custom domains allowed). usage-stats returns current usage against those limits. The "create site" UI calls these to disable the create button when the org is at quota.
Dev environments
Dev environments are full-fledged in-browser dev workspaces — VS Code in the cloud, an isolated container, the org's site code mounted. They sit alongside production sites in the same K8s cluster.
/dev-environment/*JWTThe dev-environment controller exposes endpoints for starting, stopping, attaching to, and listing the workspaces for an org. Plan limits control how many dev environments an org can spin up concurrently. The container image, IDE, and pre-installed tooling are provider-configured.
This is what powers Vibe Studio — the AI agent runs against a real deployable workspace rather than a sandbox.
Kubernetes deployment
K8sDeploymentService (and the broader k8-management module it sits next to) handles the actual container lifecycle:
- Provision new namespace per org
- Deploy site/dev-environment as a Deployment + Service + Ingress
- Wire ingress to the configured domain mapping
- Auto-scale based on CPU/memory thresholds
- Tear down on
remove-site
Application code rarely touches K8s directly — the site endpoints abstract it. For advanced operators, the K8s Management module exposes raw cluster operations.
SSL
SSL is automatic. When attach-domain runs:
- Cloudflare validates ownership via DNS challenge.
- A cert is issued (via Cloudflare's edge cert or LetsEncrypt if configured).
- The K8s ingress is updated to terminate TLS at the cert.
For domains where DNS isn't fully delegated to Cloudflare, the platform supports HTTP-01 challenge via the ingress controller. The trade-off is a brief window where the domain is reachable over HTTP only.
Container management
/site/get-site-host-mappings/:siteName?JWTThe container-management.service.ts runs adjacent operations: listing pods, restarting deployments, scaling replicas, fetching pod logs. Most of these surface through the platform's site management UI rather than as REST endpoints.
For a deeper operations need (e.g. kubectl exec into a pod), use a real K8s admin tool with the cluster's credentials — AppEngine doesn't proxy arbitrary K8s API calls.
Lifecycle in practice
- 1
Create a site
POST /site/addwith siteName, template, optional domain. The platform creates the K8s resources, attaches the domain, and provisions SSL. Takes 30-90 seconds end to end. - 2
Develop locally or in cloud
Either pull the site config and run a Next.js app locally pointing at AppEngine, or spin up a dev environment and code in the browser.
- 3
Deploy
For local dev: push container to your registry, the platform pulls. For dev environment: click "promote to production" in the platform UI.
- 4
Map a custom domain
POST /site/attach-domainwith the domain. CNAME the domain at your DNS provider (or delegate to Cloudflare). Within minutes the platform issues SSL and the site is live on the new domain.
Plan limits in practice
| Plan | Sites | Dev envs | Custom domains |
|---|---|---|---|
| Free | 1 | 0 | No |
| Basic | 3 | 1 | Yes |
| Pro | 10 | 3 | Yes |
| Team | 25 | 10 | Yes |
| Enterprise | unlimited | unlimited | Yes |
Verify against GET /site/plan-limits in your env — exact numbers are configurable.
For one-step "build this site for me" flows, see Vibe Studio and SpinForge. They use the Site module under the hood but expose a higher-level interface.