init project

This commit is contained in:
root
2026-06-25 19:06:59 -04:00
parent c5dfee6efb
commit 5d017f533a
349 changed files with 31330 additions and 0 deletions
@@ -0,0 +1,43 @@
# Technology Profile
## Required capabilities
The production stack must support SSR or SSG, strict TypeScript, locale-aware route generation, server-readable cookies, CSP nonces or hashes, accessible native dialogs or an equivalent proven overlay primitive, CSS logical properties, automated component tests, Playwright-style browser tests, and deterministic visual-regression fixtures.
## Default profile when architecture has not selected a stack
This profile is a default, not a retroactive approval:
- React-compatible SSR framework with file-based routing
- TypeScript in strict mode
- CSS Modules plus global semantic custom properties
- no runtime CSS-in-JS dependency for static marketing layout
- server components or server rendering for page shell, metadata, locale, and theme attributes
- client code limited to navigation drawer, theme selector, locale selector, tour, demo form, and analytics adapter
- schema validation at network boundaries
- first-party API endpoint or server action for demo submission
- Playwright-compatible browser testing
Exact framework and dependency versions are pinned at repository creation and recorded in the decision log. Do not let the package manager quietly select floating major versions, because apparently version drift enjoys surprise appearances during deadlines.
## Styling constraints
CSS variables contain all visual tokens. Components may use CSS Modules, scoped styles, or an equivalent build-time strategy, but may not embed raw brand colors, physical left/right spacing, or duplicated light/dark values. Utility classes are permitted only if generated from the same semantic token source and if class ordering does not become the design system.
## Repository baseline
```text
src/
app-or-pages/
components/
content/locales/
lib/analytics/
lib/localization/
lib/theme/
styles/tokens.css
styles/globals.css
public/assets/
tests/a11y/
tests/browser/
tests/visual/
```
@@ -0,0 +1,26 @@
export type Locale = "en" | "fr" | "ar";
export type Direction = "ltr" | "rtl";
export type EvidenceStatus = "approved" | "illustrative" | "pending" | "expired" | "rejected";
export type ThemePreference = "light" | "dark" | "system";
export interface LinkModel { id: string; label: string; href: string; external?: boolean; }
export interface SiteHeaderProps { locale: Locale; direction: Direction; links: LinkModel[]; login?: LinkModel; onDemo(): void; }
export interface DrawerProps extends SiteHeaderProps { open: boolean; onOpenChange(open: boolean): void; returnFocusRef?: HTMLElement | null; }
export interface LocaleSelectorProps { locale: Locale; routeId: string; hash?: string; onLocaleChange(locale: Locale): void; }
export interface ThemeSelectorProps { preference: ThemePreference; onPreferenceChange(value: ThemePreference): void; }
export interface HeroModel { eyebrow: string; title: string; body: string; primaryLabel: string; secondaryLabel: string; }
export interface ProductPreviewModel { status: EvidenceStatus; caption: string; locale: Locale; direction: Direction; theme: "light"|"dark"; assetId?: string; }
export interface LifecycleItem { id: string; title: string; description: string; icon: string; }
export interface ComparisonModel { title: string; body: string; before: { title: string; items: string[] }; after: { title: string; items: string[] }; }
export interface WorkflowStep { id: string; ordinal: string; title: string; description: string; }
export interface RoleCard { id: string; title: string; description: string; }
export interface ModuleCard { id: string; title: string; description: string; evidenceStatus: EvidenceStatus; }
export interface MetricDefinition { id: string; title: string; definition: string; publishedValue?: never; }
export interface IntegrationCategory { id: string; label: string; verifiedPartners?: never; }
export interface SecurityCheck { id: string; title: string; description: string; certificationBadge?: never; }
export interface PricingModel { mode: "quote-only" | "approved-pricing"; title: string; body: string; factors: string[]; note: string; }
export interface FaqItem { id: string; question: string; answer: string; }
export interface DemoFormValues { fullName: string; workEmail: string; company: string; fleetSize: string; market?: string; preferredLanguage?: Locale; message?: string; }
export type DemoFormState = "idle"|"validating"|"submitting"|"success"|"recoverable_error"|"terminal_error";
export interface DemoFormProps { state: DemoFormState; values: DemoFormValues; fieldErrors: Partial<Record<keyof DemoFormValues,string>>; formError?: string; onSubmit(values: DemoFormValues): Promise<void>; }
export interface TourProps { steps: WorkflowStep[]; activeIndex: number; open: boolean; onOpenChange(open:boolean): void; onStepChange(index:number): void; }
@@ -0,0 +1,13 @@
import manifest from "../localization/ROUTE_MANIFEST_v1.0.json";
type Locale = "en"|"fr"|"ar";
export function localizedPath(routeId:string, locale:Locale):string {
const route = manifest.routes.find((item) => item.id === routeId);
if (!route) throw new Error(`Unknown route: ${routeId}`);
const slug = route.slugs[locale];
return slug ? `/${locale}/${slug}` : `/${locale}`;
}
export function hreflangLinks(origin:string, routeId:string) {
const alternates = manifest.locales.map((locale) => ({ rel:"alternate", hreflang:locale, href:new URL(localizedPath(routeId, locale as Locale),origin).href }));
alternates.push({ rel:"alternate", hreflang:"x-default", href:new URL(localizedPath(routeId,"en"),origin).href });
return alternates;
}
@@ -0,0 +1,10 @@
export const locales = ["en", "fr", "ar"] as const;
export type Locale = typeof locales[number];
export const defaultLocale: Locale = "en";
export const directionByLocale: Record<Locale,"ltr"|"rtl"> = { en:"ltr", fr:"ltr", ar:"rtl" };
export const localeCookie = "hpc-locale";
export const localeStorageKey = "hpc.locale";
export const campaignQueryAllowlist = ["utm_source","utm_medium","utm_campaign","utm_content","gclid"] as const;
export const rootDetectionOrder = ["cookie","accept-language","default-en"] as const;
export function isLocale(value: unknown): value is Locale { return typeof value === "string" && (locales as readonly string[]).includes(value); }
export function isolateLtr(value: string): { dir:"ltr"; value:string } { return { dir:"ltr", value }; }
@@ -0,0 +1,8 @@
export const themeCookie = "hpc-theme";
export const themeStorageKey = "hpc.theme.preference";
export const themePreferences = ["light","dark","system"] as const;
export type ThemePreference = typeof themePreferences[number];
export type ResolvedTheme = "light"|"dark";
export function isThemePreference(v:unknown): v is ThemePreference { return typeof v === "string" && (themePreferences as readonly string[]).includes(v); }
export function resolveTheme(preference:ThemePreference, systemDark:boolean):ResolvedTheme { return preference === "system" ? (systemDark ? "dark" : "light") : preference; }
export const themeCookieAttributes = { path:"/", sameSite:"lax" as const, maxAgeSeconds:31536000, secureInProduction:true };