Fleet Studio v2 Architecture
System Overview
Every route under src/app/ is a static server component that exports its own metadata and renders hardcoded JSX matching the legacy HTML site's markup. There is no client-side state, no CMS, and no backend - content changes mean editing the page file directly.
Architecture Diagram
graph TB
subgraph Legacy["Legacy: fleet-studio-site-html"]
LegacyPages["Static HTML pages + CSS"]
end
subgraph FE["fleetstudio-v2 (Next.js)"]
RootLayout["app/layout.js<br/>force-static, legacy CSS imports"]
Pages["app/{about,contact,services/*,work/*,insights/*}"]
ServiceCard["components: ServiceCard<br/>(extracted, reused)"]
Sitemap["app/sitemap.js"]
Robots["app/robots.js"]
end
Docker["Dockerfile"]
LegacyPages -.->|"markup/classes replicated"| Pages
RootLayout --> Pages
Pages -->|"uses"| ServiceCard
Sitemap -->|"reads"| Pages
Docker -->|"containerizes"| FE
How to read this diagram
Arrows mean flow / dependency / "talks to", not button clicks. The dotted line means "source of truth for content/markup," not a runtime dependency.
Core Components
Page routes (src/app/**/page.js)
Each route is a server component exporting metadata for SEO and rendering hardcoded JSX. Services, Work, and Insights are further split into per-topic subpages (e.g. services/ai-consulting, work/healthcare, insights/ai-maturity-gap).
sitemap.js / robots.js
App Router special files generating sitemap.xml and robots.txt dynamically from NEXT_PUBLIC_SITE_URL, replacing static files the legacy HTML site shipped.
ServiceCard component
The one componentized piece of UI, extracted from duplicated markup across the Services pages - everything else stays hardcoded per AGENTS.md's "no component extraction" rule.
Data Flow
There isn't one in the traditional sense - this is a static site. The only "flow" is build-time: page files are compiled and pre-rendered, and sitemap.js/robots.js are evaluated at request/build time to reflect the current route list.
Design Decisions
Hardcode pages instead of componentizing
Context: The legacy site's markup and class names are tightly coupled to its CSS; abstracting into shared components risks class-name drift breaking styles.
Decision: AGENTS.md mandates hardcoding JSX per page and matching legacy class names exactly, with ServiceCard as a deliberate, narrow exception.
JavaScript only, no client components on pages
Context: The site needs to stay statically rendered for SEO and simplicity; adding TypeScript or client-side interactivity would pull the project away from a 1:1 static replica.
Decision: Pages remain server components (no "use client"), no TypeScript, no dynamic state - documented explicitly in AGENTS.md so future changes don't silently drift the architecture.
Technology Stack
| Layer | Technology |
|---|---|
| Framework | Next.js App Router (force-static) |
| Language | JavaScript |
| Styling | Tailwind + imported legacy CSS |
| Deploy | Docker |
| Default branch | main |