# Implementation Plan: Website Information Architecture / Core Pages **Branch**: `215-website-core-pages` | **Date**: 2026-04-19 | **Spec**: `specs/215-website-core-pages/spec.md` **Input**: Feature specification from `specs/215-website-core-pages/spec.md` **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts. ## Summary - Keep `apps/website` fully local to the website track and preserve `@tenantatlas/website`, `WEBSITE_PORT`, and the root `dev:website` / `build:website` workflows. - Re-anchor the public-site IA in the existing Astro route and metadata layer (`src/lib/site.ts`, `src/types/site.ts`, `src/content/pages`, and published Astro pages) instead of introducing a CMS, router framework, or any `apps/platform` coupling. - Canonicalize the initial public core around Home, Product, Trust, Changelog, Contact, Privacy, and Imprint; keep one primary conversion path; standardize optional content discoverability on `Resources`; leave the editorial `articles` collection unpublished; and keep Pricing/Docs/Solutions-hub style expansion deferred. - Reconcile the current v0 topology with compatibility-safe changes by introducing `/trust`, `/changelog`, and `/imprint`, shrinking primary navigation to the Spec 215 core, and extending smoke coverage for the new IA contract. ## Technical Context **Language/Version**: Astro 6.0.0 templates + TypeScript 5.9 strict **Primary Dependencies**: Astro 6, Tailwind CSS v4 via `@tailwindcss/vite`, Astro content collections, local Astro layout/primitive/content helpers, Playwright smoke tests **Storage**: Static filesystem pages, content modules, and Astro content collections under `apps/website/src` and `apps/website/public`; no database **Testing**: Root build proof via `corepack pnpm build:website` plus Playwright smoke coverage in `apps/website/tests/smoke` **Validation Lanes**: fast-feedback **Target Platform**: Static public website for modern desktop and mobile browsers **Project Type**: Web (standalone Astro app inside the monorepo) **Performance Goals**: Preserve static HTML output for canonical public routes, keep browsing flows zero-hydration by default, and avoid introducing JS-heavy navigation or runtime platform coupling **Constraints**: Preserve `@tenantatlas/website`, `WEBSITE_PORT`, and Astro static output mode; keep all IA changes local to `apps/website`; do not publish placeholder routes; keep one clear primary conversion path; keep Trust top-level visible; avoid premature promotion of `Resources`, later editorial surfaces, Docs, or Pricing **Scale/Scope**: Current public site ships 9 routes, 3 future content collections (`articles` as unpublished editorial inventory, `changelog`, `resources`), one route-definition source in `src/lib/site.ts`, and a small Playwright smoke suite that must expand to cover the Spec 215 IA contract ## UI / Surface Guardrail Plan - **Guardrail scope**: no operator-facing surface change - **Native vs custom classification summary**: N/A - public Astro website only - **Shared-family relevance**: none - **State layers in scope**: none - **Handling modes by drift class or surface**: N/A - **Repository-signal treatment**: report-only - **Special surface test profiles**: N/A - **Required tests or manual smoke**: manual-smoke plus browser smoke for public routes - **Exception path and spread control**: none - **Active feature PR close-out entry**: Smoke Coverage ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first / Graph contract / deterministic capabilities / RBAC-UX / Filament surface rules: N/A for this feature because all work stays inside `apps/website` and introduces no `/admin`, `/admin/t/{tenant}/...`, or `/system` runtime behavior. - Read/write separation: Pass. The feature changes public route structure, navigation, and content discoverability only; Contact remains a public conversion surface, not a website-side backend workflow. - Workspace isolation: Pass. The website remains runtime-independent from `apps/platform`, and the plan preserves the explicit website working contract. - Data minimization: Pass. The feature only reorganizes public pages, content sources, and navigation metadata; it introduces no tenant data, secrets, auth state, or operational records. - Test governance (TEST-GOV-001): Pass. Validation stays in `fast-feedback` with build proof plus the local Playwright smoke suite, with no database, auth, provider, or heavy-suite defaults. - Proportionality / no premature abstraction: Pass. The plan reuses the existing `site.ts`, `types/site.ts`, Astro page routes, and content collections instead of introducing a CMS, server route layer, or generic routing framework. - Persisted truth / new state: Pass. No database schema, queued work, new domain state family, or persisted artifact is introduced. - UI semantics / few layers: Pass. The added semantics stay limited to website-local route roles, navigation groups, publication rules, and journey flow rather than becoming a cross-app framework. - Website working contract: Pass. The plan keeps all implementation local to `apps/website` and preserves `@tenantatlas/website`, `WEBSITE_PORT`, and root workflow compatibility. Status: ✅ No constitution violations for this feature. The plan remains website-only, static-first, and scoped to the existing Astro website track. ## Test Governance Check > **Fill for any runtime-changing or test-affecting feature. Docs-only or template-only work may state concise `N/A` or `none`.** - **Test purpose / classification by changed surface**: Browser smoke coverage for required public routes, navigation/footer topology, compatibility routing, and optional-surface suppression plus static build proof - **Affected validation lanes**: fast-feedback - **Why this lane mix is the narrowest sufficient proof**: The feature changes the runtime route topology and public-shell behavior of a static Astro site. Build proof catches route and artifact generation regressions; focused Playwright smoke coverage is the smallest realistic browser-level proof for link reachability, canonical paths, and the absence of placeholder navigation without adding backend or heavy end-to-end cost. - **Narrowest proving command(s)**: `corepack pnpm build:website` and `cd apps/website && corepack pnpm exec playwright test` - **Fixture / helper / factory / seed / context cost risks**: none; public website pages require no database, auth, tenant, or provider setup - **Expensive defaults or shared helper growth introduced?**: no; any smoke-helper changes remain local to `apps/website/tests/smoke` - **Heavy-family additions, promotions, or visibility changes**: none - **Surface-class relief / special coverage rule**: N/A - **Closing validation and reviewer handoff**: Re-run the website build and smoke suite after route, shell, or navigation changes. Reviewers should verify that `/`, `/product`, `/trust`, `/changelog`, `/contact`, `/privacy`, and `/imprint` load; `/trust` and `/changelog` can still route visitors to `/contact` within the intended action flow; Trust is top-level visible; the brand links home; one primary CTA remains obvious; unpublished optional content hubs stay hidden; and any legacy route compatibility is explicit rather than silently duplicated. - **Budget / baseline / trend follow-up**: none beyond small website smoke-suite growth - **Review-stop questions**: Did any route rename break sitemap/canonical output? Did optional surfaces leak into primary nav without content? Did a compatibility path become permanent instead of transitional? Did any change introduce platform coupling or hidden runtime cost? - **Escalation path**: document-in-feature - **Active feature PR close-out entry**: Smoke Coverage - **Why no dedicated follow-up spec is needed**: The change is bounded to a small public-route contract and website shell behavior. The later page-structure specs handle content/detail work, so route and navigation proof can remain inside this feature. ## Project Structure ### Documentation (this feature) ```text specs/215-website-core-pages/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── public-site-ia.openapi.yaml └── tasks.md ``` ### Source Code (repository root) ```text apps/website/ ├── astro.config.mjs ├── package.json ├── playwright.config.ts ├── public/ ├── src/ │ ├── components/ │ │ ├── layout/ # Navbar, Footer, PageShell │ │ ├── primitives/ # Container, Section, Button, Card, Input, Textarea, Grid, Stack │ │ ├── sections/ # PageHero, FeatureGrid, TrustGrid, CTASection, LogoStrip │ │ └── content/ # CTA wrappers, callouts, text blocks │ ├── content/ │ │ ├── changelog/ # Existing future collection for dated updates │ │ ├── pages/ # Route-level content definitions │ │ └── resources/ # Existing optional future collection │ ├── content.config.ts │ ├── layouts/ │ │ └── BaseLayout.astro │ ├── lib/ │ │ ├── seo.ts │ │ └── site.ts # Current route, shell, and navigation truth │ ├── pages/ │ │ ├── index.astro │ │ ├── product.astro │ │ ├── contact.astro │ │ ├── privacy.astro │ │ ├── solutions.astro │ │ ├── integrations.astro │ │ ├── security-trust.astro │ │ ├── legal.astro │ │ ├── terms.astro │ │ └── sitemap.xml.ts │ ├── styles/ │ └── types/ └── tests/ └── smoke/ ``` **Structure Decision**: Keep the existing website structure and implement the IA in the current Astro route stack. The core truth should live in `src/lib/site.ts`, `src/types/site.ts`, `src/content/pages`, and published page files. Add canonical route files for `/trust`, `/changelog`, and `/imprint`, and use compatibility-only routes only when a rename is necessary to avoid avoidable breakage. ## Complexity Tracking None. ## Proportionality Review - **Current operator problem**: The current website still reflects the broader v0 route inventory, with `Solutions` and `Integrations` acting as primary-nav peers, `Security & Trust` using a non-canonical path, and no `/changelog` or `/imprint` routes even though Spec 215 treats those as part of the small credible core. - **Existing structure is insufficient because**: `src/lib/site.ts` and `src/types/site.ts` currently encode one flat route inventory but do not distinguish between required core surfaces, optional content surfaces, deferred surfaces, and compatibility paths. That makes it too easy for template-era routes to keep occupying top-level attention. - **Narrowest correct implementation**: Reuse the existing route-definition layer and content collections to encode the new IA contract, publish only the required core routes, and tighten smoke coverage around route topology and navigation behavior. Do not introduce a CMS, API contract, or platform/shared routing abstraction. - **Ownership cost created**: Ongoing maintenance of the explicit public IA contract, a small set of compatibility decisions for renamed routes, and lightweight smoke assertions that protect navigation and route truth. - **Alternative intentionally rejected**: Keeping the current v0 topology and trying to solve the IA only through page copy was rejected because it leaves the route and navigation contract incoherent; adding a richer content/router system was rejected because the website does not need that extra ownership cost. - **Release truth**: Current-release truth for `apps/website` ## Phase 0 — Outline & Research (complete) - Output: `specs/215-website-core-pages/research.md` - Key decisions captured: - Keep the IA fully local to `apps/website` and preserve the website working contract. - Use the existing `src/lib/site.ts` + `src/types/site.ts` route-definition layer as the canonical public IA source of truth. - Canonicalize the required public core around `/`, `/product`, `/trust`, `/changelog`, `/contact`, `/privacy`, and `/imprint`, with compatibility handling only where renames are necessary. - Gate optional `Resources` discoverability through the existing Astro content collections, and keep the editorial `articles` collection unpublished until a later spec activates it. - Reclassify current `Solutions`, `Integrations`, `Legal`, and `Terms` surfaces as secondary supporting routes so primary navigation stays buyer-first and intentionally small. - Validate with build proof plus route- and navigation-focused Playwright smoke coverage. ## Phase 1 — Design & Contracts (complete) ### Data model - Output: `specs/215-website-core-pages/data-model.md` - No database schema changes are required; the model is a website-local route, navigation, publication, and compatibility contract. ### Public IA contract - Output: `specs/215-website-core-pages/contracts/public-site-ia.openapi.yaml` - The contract captures required public HTML routes, navigation invariants, optional-surface gating, and compatibility-path expectations for the initial website IA. ### Quickstart - Output: `specs/215-website-core-pages/quickstart.md` - Quickstart covers the local development flow, implementation order, compatibility expectations, and required validation commands. ### Agent context update - Completed via `.specify/scripts/bash/update-agent-context.sh copilot` so the Copilot context reflects the current planning artifacts. ### Constitution re-check (post-design) - ✅ The design remains fully local to `apps/website` and preserves the website working contract. - ✅ No database truth, backend form handling, queueing, auth, or platform-side runtime concern is introduced. - ✅ The IA layer remains narrow: route roles, navigation groups, publication rules, and compatibility handling only. - ✅ Validation remains cheap, representative, and website-specific. ## Phase 2 — Implementation Plan (next) ### Story 1 (P1): Canonical core-route contract - Update `src/types/site.ts`, `src/lib/site.ts`, `src/content/pages`, and the published Astro route files so the canonical public core is `/`, `/product`, `/trust`, `/changelog`, `/contact`, `/privacy`, and `/imprint`. - Add the missing `/changelog` and `/imprint` surfaces and replace `/security-trust` as the canonical trust path with `/trust`. - Keep compatibility routes narrow and explicit; any legacy route retained during migration must stay out of primary navigation and must not become a second canonical truth. - Tests / validation: - Update smoke helpers and assertions to reflect the new canonical navigation labels and route set. - Verify sitemap/canonical behavior and route reachability through build proof plus browser smoke tests. ### Story 2 (P1): Navigation and footer reduction to the Spec 215 core - Shrink primary navigation to Product, Trust, Changelog, Contact, and optional `Resources` only when content is substantive. - Move buyer-outcome explanation responsibility into Home and Product so `Solutions` is no longer required as a top-level peer; treat `Solutions` and `Integrations` as retained secondary supporting pages instead of core IA pillars. - Rebuild footer groups around Product, Trust/Legal, Contact, and optional Content, with direct links to `/privacy`, `/imprint`, and the retained secondary `/terms` legal disclosure. - Tests / validation: - Assert brand-to-home behavior, Trust top-level visibility, `/trust -> /contact` reachability, one clear primary CTA, and the new footer grouping. - Add negative assertions that placeholder or deferred routes do not appear in primary navigation. ### Story 3 (P2): Content-backed updates and optional-surface gating - Use the existing `src/content/changelog` collection or equivalent dated entries to make `/changelog` a real progress surface rather than a placeholder. - Keep `/resources` unpublished or unlinked until content exists, keep the editorial `articles` collection unpublished until a later blog/editorial spec, and keep Docs and Pricing out of primary navigation until later specs explicitly activate them. - Rationalize current `/legal` and `/terms` behavior as retained secondary legal surfaces, and current `/solutions` and `/integrations` behavior as retained secondary supporting pages, without letting them inflate the initial IA. - Tests / validation: - Extend smoke coverage for `/changelog`, `/imprint`, and `/changelog -> /contact` reachability. - Verify unpublished optional surfaces stay hidden, the editorial `articles` collection remains undiscoverable, and any compatibility or retained secondary paths stay out of primary navigation. ## Validation Evidence - **Lane**: `fast-feedback` - **Build proof**: `corepack pnpm build:website` completed successfully on 2026-04-19 after the final IA/content changes. - **Browser smoke proof**: `cd apps/website && corepack pnpm exec playwright test` completed successfully on 2026-04-19 with 13 passing smoke tests. - **Reviewer note**: If an Astro dev server is already running on `WEBSITE_PORT`, stop it before rerunning Playwright so the suite does not reuse stale content state.