# StackShip Docs > Build, operate, and automate Terraform infrastructure with StackShip. Index: https://docs.stackship.run/llms.txt # Architecture > The initial production topology and service boundaries. Source: https://docs.stackship.run/architecture/ · Markdown: https://docs.stackship.run/architecture/index.md StackShip starts as four independently deployed Workers in one pnpm/Turborepo monorepo. | Workspace | Runtime | Domain | | --- | --- | --- | | `apps/web` | Next.js 16 through OpenNext | `stackship.run` | | `apps/api` | Hono | `api.stackship.run` | | `apps/mcp` | Hono and the MCP TypeScript SDK | `mcp.stackship.run` | | `apps/docs` | Nimbus on Astro | `docs.stackship.run` | ## Request flow The dashboard calls the API with credentialed cross-origin requests. Both origins are subdomains of the same site, so Better Auth can keep its default same-site cookie posture. The API owns the Better Auth handler at `/api/auth`. OAuth login and consent routes redirect to dashboard screens while preserving Better Auth's signed OAuth query. The MCP Worker publishes RFC 9728 protected-resource metadata, points clients to the API authorization server, and verifies JWT access tokens against the API's JWKS. ## Data plane PlanetScale PostgreSQL is reached from the API through the Cloudflare Hyperdrive binding `397048f06dbc43c1a921c92258384a40`. Drizzle owns application and Better Auth schema. Application traffic uses a least-privileged PlanetScale role; schema migrations use a separate direct administrative connection. The identity Hyperdrive configuration has query caching disabled. Hyperdrive does not expose a supported per-query cache hint, and Better Auth owns its SQL, so sessions, permissions, organizations, and identity reads need the cache-disabled connection. When product reads can tolerate staleness, add a second cache-enabled Hyperdrive configuration and route only those reads through it. R2 is the object plane for state-related artifacts, plans, run logs, and exports. Workers Analytics Engine is for high-cardinality operational events, while PostHog is reserved for product behavior and funnels. ## Failure posture Public health and version endpoints do not require the database. Authentication and protected product operations fail closed when Hyperdrive or required secrets are absent. The MCP endpoint never falls back to anonymous access. # Authentication and enterprise identity > Better Auth, organizations, OAuth 2.1, SSO, SCIM, and MCP authorization. Source: https://docs.stackship.run/authentication/ · Markdown: https://docs.stackship.run/authentication/index.md The authorization server is Better Auth at `https://api.stackship.run/api/auth`. ## Enabled capabilities - Email/password sign-up and sign-in - Google OAuth login - Organization creation, membership, roles, and active organization sessions - Enterprise OIDC and SAML through `@better-auth/sso` - SCIM 2.0 through `@better-auth/scim` - OAuth 2.1 and OIDC through `@better-auth/oauth-provider` - JWT signing and a public JWKS endpoint The admin plugin is enabled because SCIM's `active` property uses its banned state to deactivate users and revoke sessions. ## OAuth and MCP The MCP resource identifier is `https://mcp.stackship.run/mcp`. Clients discover it through `https://mcp.stackship.run/.well-known/oauth-protected-resource`. The authorization server requires PKCE for public clients, supports dynamic client registration for MCP clients, and issues audience-bound JWT access tokens. MCP tools require the `mcp:tools` scope. The initial compatibility mode permits unauthenticated registration of public clients because common MCP clients rely on RFC 7591 dynamic registration. This must be reviewed as Client ID Metadata Documents and MCP registration guidance stabilize. ## Required production secrets | Secret | Purpose | | --- | --- | | `BETTER_AUTH_SECRET` | Session and token cryptography | | `GOOGLE_CLIENT_ID` | Google OAuth client | | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | The API also requires a `HYPERDRIVE` binding. Never store these values in Wrangler configuration or source control. # Deployment > Production prerequisites, secrets, resources, and Worker domains. Source: https://docs.stackship.run/deployment/ · Markdown: https://docs.stackship.run/deployment/index.md StackShip deploys four Workers to the Cloudflare account that owns the `stackship.run` zone. ## Domains | Worker | Custom domain | | --- | --- | | `stackship-web` | `stackship.run` | | `stackship-api` | `api.stackship.run` | | `stackship-mcp` | `mcp.stackship.run` | | `stackship-docs` | `docs.stackship.run` | Wrangler custom domains create the required DNS records and certificates. A hostname cannot already have a conflicting CNAME. ## Database The PlanetScale PostgreSQL database is linked through Hyperdrive configuration `397048f06dbc43c1a921c92258384a40`, bound to the API Worker as `HYPERDRIVE`. Query caching is disabled on this configuration because it serves Better Auth sessions, permissions, organizations, and other consistency-sensitive reads. Do not use SQL comments as cache hints. Cloudflare does not document them as a cache-control API. If product reads later benefit from caching, create a second cache-enabled Hyperdrive configuration and keep identity traffic on this cache-disabled binding. The repository root contains an ignored `.env.migrations` file with the direct administrative connection: ```dotenv DATABASE_URL=postgresql://… ``` Migration commands load this file explicitly: ```sh pnpm db:generate pnpm db:migrate ``` Never point `.env.migrations` at Hyperdrive or commit it to source control. PlanetScale's `sslrootcert=system` URL parameter is normalized in memory for `node-postgres`; `sslmode=verify-full` remains enabled. PlanetScale's stable `postgres` role must own the application tables and the `drizzle.__drizzle_migrations` schema. The credential in `.env.migrations` must inherit PlanetScale's `postgres` permission so Drizzle can perform DDL, but the credential itself must not become the long-lived object owner. If a Hyperdrive or other integration role bootstraps the schema, use PlanetScale's **Reassign objects** action to transfer its objects to `postgres` before running later migrations. Verify the transfer and run `pnpm db:migrate` before rotating or deleting the original role. ## Secrets Set Worker secrets without printing them: ```sh wrangler secret put BETTER_AUTH_SECRET --config apps/api/wrangler.jsonc wrangler secret put GOOGLE_CLIENT_ID --config apps/api/wrangler.jsonc wrangler secret put GOOGLE_CLIENT_SECRET --config apps/api/wrangler.jsonc ``` ## Deploy ```sh pnpm install pnpm check pnpm build pnpm deploy ``` The first basic deployment can ship public health surfaces before database and identity credentials exist. In that state, auth returns `503` and MCP returns `401`; neither service silently weakens its security posture. ## Production checks - `GET https://api.stackship.run/health` checks Worker liveness and configured bindings. - `GET https://api.stackship.run/ready` connects through Hyperdrive and checks for the core Better Auth tables. It returns `503` with `schema: migration_required` until the generated migration is applied. - `GET https://mcp.stackship.run/health` checks MCP Worker liveness. - `GET https://mcp.stackship.run/.well-known/oauth-protected-resource` returns the OAuth protected-resource metadata. # Design system > The shadcn-based white and red StackShip visual language. Source: https://docs.stackship.run/design-system/ · Markdown: https://docs.stackship.run/design-system/index.md StackShip uses shadcn/ui primitives with semantic CSS variables. The look is inspired by the clarity of mature infrastructure control planes such as HCP Terraform and Scalr, combined with EZGH Cloud's crisp white-and-red visual language. StackShip does not reproduce another product's navigation or visual identity. ## Core palette | Token | Value | Use | | --- | --- | --- | | `primary` | `#c32940` | Primary actions, active states, brand emphasis | | `primary-hover` | `#a91f34` | Hover and pressed actions | | `primary-soft` | `#f2b8c1` | Dark-surface labels and quiet accents | | `background` | `#f6f8fb` | Application canvas | | `card` | `#ffffff` | Panels, dialogs, forms, tables | | `muted` | `#eef2f7` | Secondary surfaces | | `border` | `#d8dee8` | Dividers and control borders | | `foreground` | `#172033` | Headlines and primary body text | | `secondary-foreground` | `#253044` | Navigation and supporting text | | `muted-foreground` | `#64748b` | Metadata and descriptions | | `terminal` | `#111722` | Plan output and terminal headers | | `success` | `#177245` | Passing checks and healthy state | | `success-on-dark` | `#8ce0b5` | Passing checks on terminal surfaces | | `warning` | `#9a5b13` | Drift, pending review, and attention states | | `info` | `#315a92` | Active runs and informational state | Do not use red as the only signal for destructive state. Destructive controls need explicit labels, confirmation, and an icon or structural cue. ## Typography - Space Grotesk for display headings - Inter for interface and prose - JetBrains Mono for Terraform addresses, run IDs, hashes, timestamps, and code ## Shape and motion Cards use 12px radii, compact controls use 6–8px radii, and primary marketing actions may use pill shapes. Shadows remain soft and low contrast. The canvas may use a 22px radial dot grid with restrained red ambient glows. Motion uses a fast ease-out curve, approximately `cubic-bezier(.16, 1, .3, 1)`, and respects `prefers-reduced-motion`. ## Product shell The dashboard is an operational control plane, not a marketing page: - A persistent left sidebar establishes organization and platform hierarchy. - The page header keeps global search, documentation, notifications, and the current identity available. - Overview pages lead with health and run state, followed by workspace inventory and audit activity. - Run interfaces expose source, plan, policy, approval, and apply as a visible lifecycle. - Dense data lives in tables; cards are reserved for summaries and bounded workflows. - Sample data must identify itself as preview data until connected to a real organization. At narrow widths the sidebar becomes a sheet, tables hide secondary columns, and run stages become a vertical list. Primary actions remain visible without horizontal scrolling. ## Identity surfaces Sign-in and OAuth consent share the control-plane visual language. They pair a focused form with product and security context, preserve clear error states, and keep enterprise SSO distinct from consumer login methods. OAuth consent must explain scopes in plain language and tell users where access can be revoked. ## shadcn rules - Generate primitives through the shadcn CLI. - Keep primitives in `components/ui`. - Build product-specific components by composing primitives. - Use semantic variables such as `bg-background`, `bg-card`, `text-foreground`, `border-border`, and `bg-primary`. - Do not paste arbitrary component collections or introduce a second token system. # Engineering rules > Repository conventions and the definition of done. Source: https://docs.stackship.run/engineering/ · Markdown: https://docs.stackship.run/engineering/index.md ## Repository StackShip is a pnpm workspace orchestrated with Turborepo. Applications live in `apps/`; shared libraries belong in `packages/`. Each production surface has its own Worker and Wrangler configuration. Custom domains are explicit in source control. ## Definition of done A product change is done only when: 1. The implementation is type-safe and passes its local checks. 2. Relevant tests or protocol probes pass. 3. User-facing behavior and operational changes are documented in Nimbus. 4. New configuration is represented in `.env.example` or deployment docs. 5. No privileged credential is committed. 6. Production health is checked after deployment. ## Documentation workflow Write documentation alongside implementation. Use `apps/docs/src/content/docs/` for pages and `apps/docs/src/content/partials/` for shared sections. Run: ```sh pnpm --filter @stackship/docs check ``` Nimbus publishes clean Markdown alternates and agent indexes. Treat broken internal links or invalid frontmatter as build failures. # Project manifesto > The durable product, platform, and engineering contract for StackShip. Source: https://docs.stackship.run/project-manifesto/ · Markdown: https://docs.stackship.run/project-manifesto/index.md StackShip is a Terraform Cloud platform alternative for running Terraform infrastructure. It gives teams and their agents one place to plan, review, apply, and audit infrastructure changes. ## Product surfaces | Surface | Production origin | Responsibility | | --- | --- | --- | | Dashboard | `https://stackship.run` | Human product experience | | API | `https://api.stackship.run` | Product API and Better Auth | | MCP | `https://mcp.stackship.run` | OAuth-protected agent tools | | Docs | `https://docs.stackship.run` | Human- and agent-readable documentation | | Analytics relay | `https://r.stackship.run` | First-party PostHog ingest | ## Platform commitments - Cloudflare is the infrastructure platform. - Cloudflare Workers run the Hono API, MCP server, Nimbus documentation, and the Next.js dashboard through OpenNext. - PlanetScale PostgreSQL is the system-of-record database. - Cloudflare Hyperdrive is the production database connection layer. - Drizzle is the ORM and migration system. - R2 stores Terraform plans, state artifacts, logs, and other objects. - Workers Analytics Engine stores high-volume operational measurements. - PostHog stores product analytics. - All repositories are pnpm and Turborepo monorepos. ## Identity commitments Better Auth is the identity and authorization foundation. StackShip supports: - Google login - Email and password - Organizations and memberships through the organization plugin - Enterprise OIDC and SAML SSO - SCIM 2.0 user and membership provisioning - An OAuth 2.1 authorization server for external clients - OAuth 2.1-protected MCP access with PKCE and audience-bound JWTs Authentication is served from `https://api.stackship.run/api/auth`. Google must register `https://api.stackship.run/api/auth/callback/google` as a production redirect URI. ## Documentation commitment Documentation is part of the definition of done. A change is incomplete when it changes product behavior, configuration, architecture, API shape, operations, or a user workflow without updating the relevant Nimbus page. Nimbus is deployed independently at `docs.stackship.run`. Its Markdown alternates, `llms.txt`, `llms-full.txt`, sitemap, and canonical links are public interfaces and must remain healthy. ## Interface commitment Dashboard primitives come from shadcn/ui. Components use semantic StackShip tokens rather than one-off colors. The visual language is white and red: high-contrast white cards, cool neutral canvas and borders, deep ink type, and a restrained red brand accent. The dashboard behaves as an infrastructure control plane: organization and environment hierarchy stay visible, run lifecycles are explicit from plan through apply, and workspace health, drift, policy, cost, and audit signals are first-class information. Documentation uses the same language in a denser developer-portal layout. See the [design system](/design-system) for the complete token contract. ## Analytics commitment Product analytics uses PostHog through `https://r.stackship.run`. The current client-safe project key is `phc_C5vaHXvK3UcAmCcqPfboEMZpivVR4SGjZpBxmj8MoZQc`. This `phc_` value is a public ingestion identifier, not a privileged PostHog personal API key. Privileged PostHog keys must never be shipped to clients or committed.