# Implementation Plan: Website Visual Foundation **Branch**: `214-website-visual-foundation` | **Date**: 2026-04-18 | **Spec**: `specs/214-website-visual-foundation/spec.md` **Input**: Feature specification from `specs/214-website-visual-foundation/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 the existing workspace contracts defined by the website working contract. - Build the visual foundation on the current Astro 6 + Tailwind CSS v4 stack by formalizing semantic token roles, typography hierarchy, spacing rules, surface logic, interaction semantics, and page-level consistency rules. - Keep Astro-native primitives as the canonical implementation surface and treat `shadcn/ui` as an adaptation/reference contract rather than introducing React plus official `shadcn/ui` as a new required runtime layer. - Apply the foundation across representative page families already present in `apps/website` so landing, trust/legal, and content-heavy surfaces read as one controlled enterprise website instead of locally styled variants. ## 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 component primitives, Playwright browser smoke tests **Storage**: Static filesystem content, styles, assets, and content collections under `apps/website/src` and `apps/website/public`; no database **Testing**: Root build proof via `corepack pnpm build:website` plus Playwright browser 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 public routes, keep reading/navigation flows zero-hydration by default, and keep UI refinements within a low-JS, accessibility-first posture **Constraints**: Preserve `@tenantatlas/website`, `WEBSITE_PORT`, and root `dev:website` / `build:website` workflows; do not introduce platform runtime coupling; do not promote website semantics into a shared cross-surface design system; keep any `shadcn/ui` usage adapted to website-owned tokens and primitives **Scale/Scope**: 9 published public routes, existing layout/primitives/sections/content directories, and one website-local visual foundation spanning landing, trust/legal, and content-heavy page families ## 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 planned work stays inside `apps/website` and introduces no `/admin`, `/admin/t/{tenant}/...`, or `/system` runtime behavior. - Read/write separation: Pass. The feature changes public presentation and component composition only; it introduces no website write workflow, backend form handler, queue, or remote call path. - Workspace isolation: Pass. The website remains runtime-independent from `apps/platform`, and the plan preserves the explicit website working contract boundaries. - Data minimization: Pass. The feature only reorganizes or extends public styles, content composition, and component semantics; it introduces no tenant data, secrets, auth state, or operational records. - Test governance (TEST-GOV-001): Pass. Validation remains in `fast-feedback` using the existing website build and local Playwright smoke suite, with no database, auth, provider, or heavy-suite defaults. - Proportionality / no premature abstraction: Pass. The plan extends the current Astro/Tailwind foundation with a narrow website-local semantic layer instead of introducing React, a CMS, or a shared website-platform design system. - Persisted truth / new state: Pass. No database schema, persisted entity, queue lifecycle, or new application state family is introduced. - UI semantics / few layers: Pass. The added semantics stay limited to design tokens, primitive contracts, and page-composition rules for the website, not a reusable cross-app interpretation framework. - Website working contract: Pass. The plan keeps changes local to `apps/website` except for preserving existing root workflow compatibility, and it introduces no new API, auth, DTO, or shared-package coupling to `apps/platform`. Status: ✅ No constitution violations for this feature. The implementation 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 representative public page families plus root static build proof - **Affected validation lanes**: fast-feedback - **Why this lane mix is the narrowest sufficient proof**: The feature changes runtime website rendering, styling, and composition but stays within a static Astro site. Build proof catches asset and route breakage; a focused Playwright smoke suite catches browser-visible regressions in navigation, CTA visibility, representative content surfaces, and mobile usability without introducing 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 browser assertions remain local to `apps/website/tests/smoke` - **Heavy-family additions, promotions, or visibility changes**: none - **Closing validation and reviewer handoff**: Re-run the website build and smoke suite after token, primitive, or page-family changes. Reviewers should verify that Home, trust/legal, and another content-heavy route still load cleanly, navigation and footer links remain reachable, CTA hierarchy stays visible, and no unnecessary client framework hydration is introduced. - **Budget / baseline / trend follow-up**: none beyond the existing small website smoke-suite runtime - **Review-stop questions**: Does validation remain fast-feedback only? Did any change introduce hidden React/runtime coupling, broaden the smoke suite beyond representative website flows, or create new platform-facing contracts? - **Escalation path**: document-in-feature - **Why no dedicated follow-up spec is needed**: This feature’s validation scope is tightly bounded to the website’s local rendering and navigation behavior. A separate test-governance spec is only needed if the website later gains interactive workflows, API-backed forms, or broader browser coverage. ## Project Structure ### Documentation (this feature) ```text specs/214-website-visual-foundation/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── website-visual-foundation.contract.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, Badge, Card, Input, Textarea, Grid, Stack │ │ ├── sections/ # PageHero, FeatureGrid, TrustGrid, CTASection, LogoStrip │ │ └── content/ # Eyebrow, Headline, Lead, Callout, Metric, audience/trust helpers │ ├── content/ # Route content and future content collections │ ├── layouts/ │ │ └── BaseLayout.astro │ ├── lib/ # Site metadata, SEO, and helper config │ ├── pages/ # Published public routes │ ├── styles/ │ │ ├── global.css │ │ └── tokens.css │ └── types/ └── tests/ └── smoke/ ``` **Structure Decision**: Keep the existing website structure and formalize the design foundation inside the current `styles`, `primitives`, `sections`, `content`, and `layout` layers. The implementation should encode semantic design rules in the Astro-native foundation already present instead of introducing a second component stack. ## Complexity Tracking None. ## Proportionality Review - **Current operator problem**: Website contributors and reviewers lack a canonical, website-local visual contract, so styling decisions drift across pages and primitives and dilute enterprise trust. - **Existing structure is insufficient because**: The current site already has tokens, gradients, rounded cards, and reusable primitives, but those choices are only partially codified. They do not yet define the semantic token roles, page-family rules, or `shadcn/ui` usage boundaries needed to prevent future drift. - **Narrowest correct implementation**: Extend the current Astro/Tailwind foundation with explicit semantic token mapping, primitive contracts, and page-consistency rules, then apply those rules to representative routes. Do not add a new client framework, platform coupling, or shared website-platform design system. - **Ownership cost created**: Ongoing maintenance of token semantics, shared primitives, and a small browser smoke suite that protects representative public routes. - **Alternative intentionally rejected**: Continuing page-local styling was rejected because it preserves drift; full React plus official `shadcn/ui` was rejected because it adds unnecessary runtime and maintenance cost; a shared cross-surface design system was rejected because the feature is intentionally website-only. - **Release truth**: Current-release truth for `apps/website` ## Phase 0 — Outline & Research (complete) - Output: `specs/214-website-visual-foundation/research.md` - Key decisions captured: - Preserve the website working contract and keep all visual-language work local to `apps/website`. - Build the foundation on semantic token layering in Tailwind CSS v4 and CSS custom properties rather than page-local utility drift. - Keep Astro-native primitives as the canonical implementation surface and adapt any `shadcn/ui` usage to that layer instead of adding React as a new runtime dependency. - Use representative page families already in the repo to drive the foundation: landing, trust/legal, and content-heavy surfaces. - Validate with root build proof plus the existing Playwright smoke suite for representative public routes. ## Phase 1 — Design & Contracts (complete) ### Data model - Output: `specs/214-website-visual-foundation/data-model.md` - No database schema changes are required; the model is a website-local design contract expressed through token roles, primitive contracts, and page-family consistency rules. ### Design contract - Output: `specs/214-website-visual-foundation/contracts/website-visual-foundation.contract.yaml` - This feature has no HTTP or API contract changes. The contract artifact captures the website-local visual foundation rules that implementation must satisfy. ### Quickstart - Output: `specs/214-website-visual-foundation/quickstart.md` - Quickstart covers local development, representative implementation order, and the required validation commands. ### Agent context update - Completed via `.specify/scripts/bash/update-agent-context.sh copilot` so the Copilot context reflects the current website stack and this feature’s 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, or platform-side runtime concern is introduced. - ✅ The semantic layer remains narrow: tokens, primitives, and page-family rules only. - ✅ Validation remains cheap, representative, and website-specific. ## Phase 2 — Implementation Plan (next) ### Story 1 (P1): Semantic token and rule foundation - Normalize the existing palette and CSS variables into an explicit semantic role model for colors, surfaces, borders, shadows, radius, and typography. - Encode the spacing model and section rhythm into the current Astro foundation so `Container`, `Section`, `SectionHeader`, `Card`, `Button`, `Input`, and `Textarea` expose one canonical visual language. - Keep the site static and light-first, with focus states, contrast, and mobile readability treated as foundation rules rather than page-local cleanup. - Tests / validation: - Confirm the website still builds via `corepack pnpm build:website`. - Re-run smoke coverage for Home and Product, explicitly proving focus visibility, readable contrast, non-color-only semantics, and clear navigation-vs-CTA differentiation. ### Story 2 (P1): Representative page-family alignment - Apply the foundation consistently across representative page families already present in the app: landing (`/` or `/product`), trust/legal (`/security-trust`, `/privacy`, `/terms`), and other content-heavy routes. - Reduce style drift in hero, section intro, callout, stat, and card usage so CTA emphasis, section spacing, surface elevation, and progressive-disclosure layering behave consistently across routes. - Ensure the footer, navigation shell, and CTA placement logic match the foundation’s page-level rules. - Tests / validation: - Extend or adjust browser smoke coverage to assert representative headings, CTA visibility, shell/navigation stability, and progressive-disclosure layering across at least three page families. - Verify mobile navigation remains usable. ### Story 3 (P2): `shadcn/ui` usage contract in code - Encode `shadcn/ui` usage constraints through local primitives and variant APIs so future component work is forced back through website-owned tokens, surfaces, and interaction semantics. - Keep Astro-native wrappers as the primary authoring path; any borrowed `shadcn/ui` pattern must be translated into local primitives instead of exposing uncontrolled library defaults. - Avoid introducing React, Radix, or extra framework/runtime weight unless a later explicit spec proves a concrete need. - Tests / validation: - Re-run build and smoke coverage after primitive API changes. - Review representative components to ensure no page-local style override bypasses the shared token and primitive model.