# 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
