Skip to Content
TechnicalArchitecture

Architecture

This page documents the stack, data flow, and folder structure of fe-serenity-code-landing-page.

Stack

LayerTechnology
FrameworkNext.js 16 (App Router)
LanguageTypeScript (strict)
Package ManagerBun
StylingTailwind CSS v4
Global StateZustand
Server StateTanStack Query
API ClientOrval (generated from OpenAPI) + native fetch mutator
i18nnext-intl (EN/ID)
FormsReact Hook Form + Zod
EmailResend + React Email

Data Flow

FE never accesses Payload CMS directly. All data flows through BE Landing Page.

Folder Structure

src/ ├── app/ # Next.js App Router pages & layouts ├── components/ # UI components (kebab-case files) ├── hooks/ # Custom hooks (camelCase files) ├── lib/ │ ├── api/ # Orval-generated client (read-only) │ ├── constants/ │ └── utils/ ├── messages/ # Translation files (en.json, id.json) ├── types/ # Shared TypeScript types └── store/ # Zustand stores (global UI state only)

i18n Convention

Two locales are supported: en (English) and id (Indonesian). Message files live in src/messages/.

Every component must scope its useTranslations call to its own namespace — never call it without an argument:

// correct const t = useTranslations('hero'); t('title.l1'); // wrong — dotted-path access on root namespace const t = useTranslations(); t('hero.title.l1');

Namespaces follow the top-level keys in src/messages/en.json — that file is the source of truth. Both locale files must be updated in the same commit whenever a key is added or removed. Run bun check:i18n to verify sync and detect unused keys before committing.

Last updated on