Skip to content

[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

txt
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:

txt
src/react/
  app.tsx                  composition and current integration root
  services/                data/auth/Supabase bridge
  contracts/               living integration contracts
  ui/                      future Claude-owned presentational screens

Design 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-out
  • src/react/services/auth/providers/*: independent Kakao, Google, and Apple metadata/error modules
  • src/react/services/auth/socialAuthFlow.ts: shared web/iOS OAuth start and code-only callback parsing
  • src/react/services/domains/authProfileDomain.ts: auth state, current profile, and onboarding profile data
  • src/react/services/domains/workoutDomain.ts: workout, session, plan, and daily condition mutations
  • src/react/services/domains/catalogDomain.ts: exercise catalog, archetypes, details, aliases, and external mappings
  • src/react/services/domains/importDomain.ts: Wodup JSONL upload, import start, and import polling
  • src/react/services/domains/statsDomain.ts: screen RPC packages and materialized stats read models
  • src/react/services/domains/adminDomain.ts: admin/debug/export operations
  • src/react/services/barbelicRepository.ts: strict adapter for the one current Supabase contract
  • src/react/services/barbelicMappers.ts: current RPC-row-to-view-model mapping and current write DTO construction
  • src/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:

txt
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.ts keeps data-lg-* markers executable and testable.
  • Fixture-Driven Design: Claude may keep preview data under src/react/ui/fixtures/**.
  • Progressive Extraction: existing screens-*.jsx files can be extracted one screen at a time.

Adding A New Screen

  1. Claude creates or updates a presentational screen under src/react/ui/screens/** when possible.
  2. Claude uses fixtures under src/react/ui/fixtures/** for standalone preview.
  3. Claude requests any new data-lg-* markers in the PR notes.
  4. Codex registers markers in src/react/contracts/designContract.ts.
  5. Codex wires real data and callbacks from src/react/app.tsx or a focused controller.
  6. 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.