init project
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
# ADR-0001: Repository Foundation and Runtime Architecture
|
||||
|
||||
- **Status:** Accepted for Phase 10
|
||||
- **Date:** 2026-06-25
|
||||
- **Decision owners:** Architecture and Engineering
|
||||
- **Supersedes:** Phase 9 open issues P9-010 and P9-017
|
||||
- **Scope:** Marketing-site repository foundation only
|
||||
|
||||
## Context
|
||||
|
||||
Phase 9 requires a server-rendered multilingual application that establishes locale, document direction, theme, metadata, canonical links, and `hreflang` before hydration. It also requires strict TypeScript, logical CSS, a CSP-compatible no-flash theme strategy, limited browser JavaScript, deterministic validation, and browser-based accessibility and visual checks.
|
||||
|
||||
The project name changed from `homePageCar` to `RentalDriveGo` at Phase 10. The original Phase 9 package is retained byte-for-byte under `contracts/phase9`; implementation copies carry the new product name. Legacy cookie and storage identifiers remain intentionally unchanged because they are part of the approved Phase 9 technical contract and changing them would break continuity without an approved migration.
|
||||
|
||||
## Decision
|
||||
|
||||
### Application framework and rendering
|
||||
|
||||
Use **Next.js 16.2.9 App Router** with **React 19.2.7** and **strict TypeScript 6.0.3**.
|
||||
|
||||
All locale pages use dynamic server rendering. The request proxy creates a unique CSP nonce and forwards it through the request headers so Next.js can attach the nonce to framework scripts and styles. Dynamic rendering is accepted as the cost of correct per-request CSP nonces and pre-hydration locale/theme behavior. Static export is explicitly out of scope.
|
||||
|
||||
The public route model is:
|
||||
|
||||
```text
|
||||
/ -> locale negotiation and redirect
|
||||
/en -> English, LTR
|
||||
/fr -> French, LTR
|
||||
/ar -> Arabic, RTL
|
||||
```
|
||||
|
||||
The route manifest in `src/contracts/phase9/route-manifest.json` is the route authority. The framework's experimental typed-route generator is not enabled because it produced an incompatible generated JSX namespace with the pinned React/TypeScript toolchain. Route integrity is instead enforced by deterministic manifest validation and browser tests.
|
||||
|
||||
### Locale and direction
|
||||
|
||||
The server resolves locale from an explicit route first. Root negotiation uses the first valid value from:
|
||||
|
||||
1. `hpc-locale` cookie
|
||||
2. `Accept-Language`
|
||||
3. English fallback
|
||||
|
||||
Each locale layout renders the correct `<html lang>` and document-level `dir` value before hydration. Arabic uses `dir="rtl"`; application CSS uses logical properties. Atomic LTR values remain subject to the Phase 9 bidi-isolation contract when those components are implemented.
|
||||
|
||||
### Theme and no-flash bootstrap
|
||||
|
||||
Theme preference is `light`, `dark`, or `system` and is read server-side from `hpc-theme`. The server emits an initial theme attribute. A nonce-bearing inline bootstrap executes in `<head>` before interactive components, resolves local storage and system color preference, and updates only `data-theme-preference` and `data-theme`.
|
||||
|
||||
The CSP uses:
|
||||
|
||||
```text
|
||||
script-src 'self' 'nonce-{requestNonce}' 'strict-dynamic'
|
||||
style-src 'self' 'nonce-{requestNonce}'
|
||||
```
|
||||
|
||||
Production CSP does not permit `unsafe-inline` or `unsafe-eval`. Development alone permits `unsafe-eval` for the framework toolchain. Theme color-scheme behavior is expressed in CSS from the resolved data attribute, not through an inline style mutation.
|
||||
|
||||
### Styling
|
||||
|
||||
Use **CSS Modules** for component scope and global semantic CSS custom properties for tokens. `src/styles/tokens.css` remains checksum-identical to the Phase 9 source token file. Application styles may not introduce raw brand colors or physical left/right layout declarations. CI validators enforce both constraints.
|
||||
|
||||
No runtime CSS-in-JS system or utility framework is included. That avoids a second token authority and unnecessary client/runtime cost.
|
||||
|
||||
### Client JavaScript boundary
|
||||
|
||||
Server components are the default. Client components are limited to current interaction boundaries:
|
||||
|
||||
- locale selector
|
||||
- theme controller and selector
|
||||
|
||||
Future Phase 11 components may add client code only where interaction requires it. CRM submission, analytics, dialogs, product tour, and login routing are not implemented until their governing Phase 9 issues are approved.
|
||||
|
||||
### Testing and quality stack
|
||||
|
||||
- Unit and contract behavior: Vitest 4.1.9 with V8 coverage
|
||||
- DOM component utilities: Testing Library
|
||||
- Browser, accessibility, and visual checks: Playwright 1.61.1
|
||||
- Automated accessibility scan: axe-core through `@axe-core/playwright`
|
||||
- Linting: ESLint 9.39.4 with Next.js and TypeScript rules
|
||||
- Formatting: Prettier 3.8.4
|
||||
- Package audit: pnpm audit
|
||||
|
||||
Canonical visual baselines use Chromium. Functional browser coverage is configured for Chromium, Firefox, WebKit, mobile Chromium, and mobile WebKit emulation. Phase 9's browser-policy ownership issue remains open; this configuration is a verification baseline, not a unilateral support-policy claim.
|
||||
|
||||
### Package and runtime management
|
||||
|
||||
Use **Node.js 24.17.0** and **pnpm 11.9.0**, pinned in `package.json`, `.node-version`, `.nvmrc`, and the CI workflow. All direct dependencies use exact versions. The lockfile is committed and CI installs with `--frozen-lockfile`.
|
||||
|
||||
The pnpm workspace applies a 24-hour minimum package-release age, except for explicitly pinned packages selected during this architecture decision. Package build scripts are allowlisted. Dependabot opens reviewed update proposals rather than silently advancing versions.
|
||||
|
||||
### Deployment target
|
||||
|
||||
The deployable artifact is a **vendor-neutral OCI container** running the Next.js standalone Node server on Linux. No cloud provider, domain, CDN, region, or managed service is invented. The container is suitable for an approved OCI-compatible platform once infrastructure ownership is decided.
|
||||
|
||||
Required runtime inputs:
|
||||
|
||||
- `SITE_ORIGIN`: approved absolute public origin
|
||||
- `PUBLIC_RELEASE_APPROVED`: remains `false` until release gates close
|
||||
- `PORT`: defaults to `3000`
|
||||
- `HOSTNAME`: defaults to `0.0.0.0` in the container
|
||||
|
||||
When release approval is false, metadata is `noindex` and `robots.txt` disallows crawling.
|
||||
|
||||
### Repository conventions
|
||||
|
||||
```text
|
||||
contracts/phase9/ immutable authoritative Phase 9 package
|
||||
src/app/ App Router routes and metadata
|
||||
src/components/ reusable application components
|
||||
src/content/locales/ implementation locale resources
|
||||
src/contracts/phase9/ runtime-consumable contract copies
|
||||
src/lib/ localization, theme, and security primitives
|
||||
src/styles/ exact tokens and global semantic CSS
|
||||
scripts/ deterministic repository validators
|
||||
tests/ unit, browser, accessibility, and visual tests
|
||||
docs/ ADR, dependency record, issue register, reports
|
||||
```
|
||||
|
||||
Files use UTF-8, LF line endings, strict TypeScript, named domain modules, and no barrel exports by default. Code paths may not silently resolve product, legal, analytics, security, pricing, evidence, or integration decisions.
|
||||
|
||||
## Consequences
|
||||
|
||||
Positive consequences:
|
||||
|
||||
- Locale, direction, theme, and metadata are correct before hydration.
|
||||
- The Phase 9 contract remains auditable and checksum-verifiable.
|
||||
- CSP nonces work with the framework's server rendering model.
|
||||
- The scaffold does not ship fabricated integrations, destinations, evidence, or claims.
|
||||
- A vendor-neutral container avoids premature infrastructure lock-in.
|
||||
|
||||
Costs and tradeoffs:
|
||||
|
||||
- Per-request nonces force dynamic rendering and reduce static CDN opportunities.
|
||||
- The app cannot be publicly released until critical and high Phase 9 issues close.
|
||||
- The renamed product has no approved final logo asset; the shell uses a temporary text mark only.
|
||||
- Browser and assistive-technology coverage still requires execution in approved CI/device environments.
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
- **Static export:** rejected because request-specific CSP nonces and server-readable preference cookies would be weakened.
|
||||
- **Client-only locale/theme setup:** rejected because it would permit wrong-language, wrong-direction, or wrong-theme first paint.
|
||||
- **Runtime CSS-in-JS or an unrelated utility token system:** rejected because it would create duplicate token authorities and more browser work.
|
||||
- **Prototype conversion:** rejected by scope and because Phase 8 prototype behavior is research evidence, not production source.
|
||||
- **Invented hosting provider or public domain:** rejected because neither is approved.
|
||||
|
||||
## Primary references
|
||||
|
||||
- Next.js Content Security Policy guide: https://nextjs.org/docs/app/guides/content-security-policy
|
||||
- Next.js Proxy convention: https://nextjs.org/docs/app/getting-started/proxy
|
||||
- Next.js metadata API: https://nextjs.org/docs/app/api-reference/functions/generate-metadata
|
||||
- Next.js 16.2 release: https://nextjs.org/blog/next-16-2
|
||||
- Node.js downloads: https://nodejs.org/en/download/current
|
||||
- pnpm 11 release: https://pnpm.io/blog/releases/11.0
|
||||
- Playwright release notes: https://playwright.dev/docs/release-notes
|
||||
@@ -0,0 +1,63 @@
|
||||
# ADR-0002: Phase 11 Foundation Architecture
|
||||
|
||||
- **Status:** Accepted for implementation; browser evidence pending
|
||||
- **Date:** 2026-06-25
|
||||
- **Scope:** Design tokens, theme, localization, routing, metadata, application shell, and global states
|
||||
- **Supersedes:** No Phase 9 or Phase 10 product decision
|
||||
|
||||
## Context
|
||||
|
||||
Phase 11 must extend the Phase 10 repository without mutating the immutable Phase 9 contract, weakening CSP, inventing unresolved destinations, or creating a second styling, routing, or localization authority.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Token pipeline
|
||||
|
||||
Keep Phase 9 raw and semantic token files unchanged. Add `src/styles/component-tokens.css` as an additive component-facing layer. Application CSS may not consume raw palette tokens or literal colors.
|
||||
|
||||
### Theme persistence and bootstrap
|
||||
|
||||
Keep `hpc-theme` as the server-readable canonical preference and `hpc.theme.preference` as a client continuity copy. Preference remains distinct from resolved theme. The nonce-bearing head bootstrap resolves before paint. A CSS media-query fallback gives readable system-dark behavior when JavaScript is delayed or unavailable. Same-window theme selectors synchronize through a custom event; cross-tab selectors synchronize through the storage event.
|
||||
|
||||
### Locale routing and negotiation
|
||||
|
||||
The route path remains the active locale authority. Root negotiation uses the locale cookie, then `Accept-Language`, then English. Locale switching resolves the current semantic route ID, preserves only allowlisted campaign parameters, and preserves only hashes approved for that route.
|
||||
|
||||
### Translation loading
|
||||
|
||||
Server components load typed catalogs through `getMessages`. Interaction-only global states use a small client shell-catalog map. Missing-key and type parity remain CI failures. No runtime fallback silently substitutes English for French or Arabic.
|
||||
|
||||
### Formatting
|
||||
|
||||
Centralized `Intl` formatters require an explicit locale and, where relevant, time zone or currency. Language never implies market, country, currency, or jurisdiction. Gregorian dates and Latin digits remain the inherited baseline until product research approves alternatives.
|
||||
|
||||
### Font loading
|
||||
|
||||
Use the pinned local Fontsource variable packages for Inter and Noto Sans Arabic. Arabic receives its own line-height and does not inherit forced Latin metrics.
|
||||
|
||||
### Application shell composition
|
||||
|
||||
The locale layout owns document attributes, theme bootstrap, skip navigation, header, footer, and theme controller. The header is server-rendered except for route-aware navigation, selectors, and the native modal mobile drawer. The drawer uses `<dialog>` for modal semantics, Escape behavior, background interaction blocking, and focus containment, with explicit focus return.
|
||||
|
||||
### Unresolved destinations
|
||||
|
||||
Authoritative route-manifest paths are generated for login and legal routes, but those pages render localized noindex pending shells. Demo, contact, and login actions do not receive invented production integrations. They remain visibly disabled or lead to an explicit pending route.
|
||||
|
||||
### Metadata
|
||||
|
||||
A single server helper generates canonical URLs, reciprocal `hreflang`, Open Graph locale data, social summary metadata, and release-safe robots behavior from route IDs. No structured organization, review, rating, pricing, or contact data is emitted.
|
||||
|
||||
### CSS organization
|
||||
|
||||
- `tokens.css`: immutable Phase 9 tokens
|
||||
- `component-tokens.css`: Phase 11 component-facing roles
|
||||
- `globals.css`: reset, typography, focus, selection, accessibility utilities
|
||||
- CSS Modules: component and page layout
|
||||
|
||||
### Visual regression
|
||||
|
||||
Playwright Chromium is the canonical snapshot engine. Functional projects remain Chromium, Firefox, WebKit, mobile Chromium, and mobile WebKit. Snapshot generation and approval are blocked until the pinned browser environment can execute.
|
||||
|
||||
## Consequences
|
||||
|
||||
The application foundation is traceable and does not encode unresolved product decisions. The cost is an explicit set of pending route shells and disabled conversion destinations until owners close the inherited gates. Full acceptance still requires Node 24.17.0 CI, Playwright execution, and reviewed visual snapshots.
|
||||
@@ -0,0 +1,26 @@
|
||||
# ADR-0003: Phase 12 component-system architecture
|
||||
|
||||
- Status: Accepted for implementation; release acceptance remains gated
|
||||
- Date: 2026-06-25
|
||||
- Owners: Frontend architecture, design systems, accessibility
|
||||
|
||||
## Context
|
||||
|
||||
Phase 12 requires a reusable marketing component system without assembling the homepage or inventing unresolved product content. Phase 11 approved semantic CSS modules, native platform behavior, server components by default, and a production shell rather than Storybook.
|
||||
|
||||
## Decision
|
||||
|
||||
1. Keep CSS Modules as the only component styling method and consume only component-facing semantic tokens.
|
||||
2. Use native HTML primitives where they provide reliable behavior: `button`, `a`, `details`, `progress`, form controls, and `dialog`.
|
||||
3. Add client boundaries only to controls with state, browser APIs, keyboard roving focus, or overlays.
|
||||
4. Use a guarded component-lab route as the approved Storybook-equivalent fixture surface. It returns not found unless `COMPONENT_FIXTURES_ENABLED=true`.
|
||||
5. Implement the icon set as a small, tree-shakeable internal SVG map to avoid adding a second dependency or shipping an entire icon library.
|
||||
6. Keep unresolved claims, destinations, customer evidence, pricing, CRM submission, and approved media represented as blocked inventory entries or disabled typed states.
|
||||
7. Add Phase 12 inventory and manifest validators. The package dependency graph remains unchanged.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Phase 13 receives stable import paths and explicit section patterns.
|
||||
- Browser, accessibility, and visual fixtures are deterministic and cannot be exposed accidentally under the default production environment.
|
||||
- The internal icon map requires deliberate review when adding icons, which is preferable to casual dependency archaeology.
|
||||
- Runtime acceptance still depends on executing the pinned Node 24.17.0 and pnpm 11.9.0 suites in an environment with registry and browser access.
|
||||
Reference in New Issue
Block a user