[ARCHIVED 2026-08-19] 역사 자료 — 현행 규범이 아니다. 아카이브 사유와 대체 문서는 docs/README.md의 Archive 섹션을 참조.
Software Architecture
Updated: 2026-07-27
Barbelic now uses the React app as the single frontend source.
The previous vanilla frontend layers were removed. Do not use src/app, src/core, src/features, src/mobile, src/desktop, src/dom, top-level css, or top-level app.js as implementation references.
Current Runtime
index.html
-> src/react/vite/main.tsx
-> src/react/app.tsx
-> src/react/appController.tsx
-> src/react/mobileApp.tsx / src/react/desktopApp.tsx
-> src/react/services/*
-> src/react/ui/mobile/* / src/react/ui/desktop/*The static web app wrapper remains:
public/manifest.webmanifest- Vite dev/build config
api/auth/test-admin/session
Offline service worker support is currently removed; restoring offline support is a separate task. The app shell is React.
Ownership Model
Claude Design owns the UI surface:
- screen composition
- flow choreography
- presentation components
- CSS
- local UI state
- fixtures for standalone design preview
Codex owns the functional bridge:
- Supabase auth/data access
- Kakao, Google, and Apple provider modules and shared PKCE callback plumbing
- data normalization and persistence
- app integration callbacks
- contract tests
- deployment and verification
The intended split is container/presentational React:
src/react/
app.tsx composition and current integration root
services/ data/auth/Supabase bridge
contracts/ living integration contracts
ui/ future Claude-owned presentational screensDesign Contract
src/react/contracts/designContract.ts is the live source of truth for semantic data-lg-* markers.
Rules:
- Claude can change layout, classes, tags, wrappers, and visual hierarchy freely.
- Codex must not use CSS classes as hidden functional contracts.
- If a DOM-level integration marker is needed, it goes through
data-lg-*. - If Claude adds a marker, Codex registers it in
designContract.ts. - Tests fail when React source uses an unregistered marker or when a registered marker no longer exists in
src/react.
The contract protects the integration surface. It is not a design system.
Data Boundary
src/react/services/barbelicApi.ts is the typed data facade consumed by the app shell. It delegates implementation to focused domain service modules:
src/react/services/supabaseAuth.ts: Supabase client creation, provider-neutral PKCE completion, sign-in redirect, sign-outsrc/react/services/auth/providers/*: independent Kakao, Google, and Apple metadata/error modulessrc/react/services/auth/socialAuthFlow.ts: shared web/iOS OAuth start and code-only callback parsingsrc/react/services/domains/authProfileDomain.ts: auth state, current profile, and onboarding profile datasrc/react/services/domains/workoutDomain.ts: workout, session, plan, and daily condition mutationssrc/react/services/domains/catalogDomain.ts: exercise catalog, archetypes, details, aliases, and external mappingssrc/react/services/domains/importDomain.ts: Wodup JSONL upload, import start, and import pollingsrc/react/services/domains/statsDomain.ts: screen RPC packages and materialized stats read modelssrc/react/services/domains/adminDomain.ts: admin/debug/export operationssrc/react/services/barbelicRepository.ts: strict adapter for the one current Supabase contractsrc/react/services/barbelicMappers.ts: current RPC-row-to-view-model mapping and current write DTO constructionsrc/react/services/barbelicShared.ts: shared constants, date helpers, and display normalization
UI files should still receive data via props/callbacks rather than importing Supabase or repository modules directly.
Session Hierarchy
The app stores and renders workout data as:
day
sessions[]
exercises[]
sets[]Completed records come from sessions > session_exercises > exercise_sets.
Planned or missed records come from planned_sessions > planned_sets.
The UI should keep source: "sessions" | "planned_sessions" when deletion or editing needs to know which table owns the row.
Patterns In Use
- Container / Presentational Components: planned direction for
src/react/ui/**. - Domain Service / Repository Adapter: app code calls
barbelicApi.ts, which delegates to domain services, and Supabase reads/writes stay behind strict repository adapters. - Contract Module:
designContract.tskeepsdata-lg-*markers executable and testable. - Fixture-Driven Design: Claude may keep preview data under
src/react/ui/fixtures/**. - Progressive Extraction: existing
screens-*.jsxfiles can be extracted one screen at a time.
Adding A New Screen
- Claude creates or updates a presentational screen under
src/react/ui/screens/**when possible. - Claude uses fixtures under
src/react/ui/fixtures/**for standalone preview. - Claude requests any new
data-lg-*markers in the PR notes. - Codex registers markers in
src/react/contracts/designContract.ts. - Codex wires real data and callbacks from
src/react/app.tsxor a focused controller. - Codex updates tests and verifies Supabase flows.
Claude Handoff Rule
When handing work to Claude, Codex should describe:
- screen purpose
- states
- data shape
- callback needs
- stress cases
- required semantic markers if any
Codex should not prescribe spacing, palette, card shape, DOM nesting, or class names unless the user explicitly decided those details.