# clawnify/openpersonaltraining architecture

> Architecture diagram of the GitHub repository clawnify/openpersonaltraining, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/clawnify/openpersonaltraining
- Repository: https://github.com/clawnify/openpersonaltraining

## Overview

OpenPersonalTraining is a personal-training and coaching platform. Trainers use its dashboard to review activity, manage clients, assemble and share exercise-based workouts, schedule sessions, and track payments. The Preact client routes screens through shared app state and an API client to a Hono server backed by D1. The README also documents a public, no-login workout link, PDF saving, and JSON APIs for agent-driven administration. Some links are documented rather than visible in the sampled server excerpt; those are identified as such.

Main entry points: [`src/client/app.tsx`](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/app.tsx) (App and routing), [`src/client/context.tsx`](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/context.tsx) (Shared context), [`src/client/components/client-detail.tsx`](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/client-detail.tsx) (Client details), [`src/server/index.ts`](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/index.ts) (HTTP API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Trainer interface"]
  node_app["App and routing<br/>[app.tsx]"]
  node_dashboard["Dashboard<br/>[dashboard.tsx]"]
end

subgraph group_state["Client state and API"]
  node_state_hook["App state<br/>[use-app.ts]"]
  node_context["Shared context<br/>[context.tsx]"]
  node_api_client["API client<br/>[api.ts]"]
end

subgraph group_coaching["Coaching workflows"]
  node_client_list["Client list<br/>[client-list.tsx]"]
  node_client_detail["Client details<br/>[client-detail.tsx]"]
  node_client_form["Client editor<br/>[create-client.tsx]"]
  node_exercise_library["Exercise library"]
  node_workout_list["Workout list<br/>[workout-list.tsx]"]
  node_workout_builder["Workout builder"]
  node_schedule["Schedule<br/>[schedule.tsx]"]
  node_session_form["Session editor<br/>[create-session.tsx]"]
  node_payment_list["Payment ledger<br/>[payment-list.tsx]"]
  node_payment_form["Payment editor<br/>[create-payment.tsx]"]
end

subgraph group_server["API and persistence"]
  node_api_server["HTTP API<br/>[index.ts]"]
  node_db_helper["Database access<br/>[db.ts]"]
  node_d1[("Cloudflare D1")]
  node_exercise_seed["Exercise dataset seed<br/>[seed-exercises.ts]"]
  node_demo_seed["Demo data seed<br/>[seed-demo.ts]"]
end

subgraph group_integrations["Sharing and integrations"]
  node_workout_share["Public workout sharing<br/>[index.ts]"]
  node_exercise_images["jsDelivr images"]
end

node_trainer(("Trainer"))
node_client_phone(("Client phone or PDF"))
node_agent(("Clawnify agent"))

node_trainer -->|"uses"| node_app
node_app -->|"renders"| node_dashboard
node_app -->|"renders"| node_client_list
node_app -->|"renders"| node_client_detail
node_app -->|"renders"| node_exercise_library
node_app -->|"renders"| node_workout_list
node_app -->|"renders"| node_workout_builder
node_app -->|"renders"| node_schedule
node_app -->|"renders"| node_payment_list
node_app -->|"loads state"| node_state_hook
node_app -->|"provides state"| node_context
node_client_list -->|"opens editor"| node_client_form
node_client_detail -->|"opens editor"| node_client_form
node_client_detail -->|"opens editor"| node_session_form
node_client_detail -->|"opens editor"| node_payment_form
node_schedule -->|"opens editor"| node_session_form
node_payment_list -->|"opens editor"| node_payment_form
node_client_list -->|"reads state"| node_context
node_client_detail -->|"reads state"| node_context
node_exercise_library -->|"reads state"| node_context
node_workout_builder -->|"reads state"| node_context
node_schedule -->|"reads state"| node_context
node_payment_list -->|"reads state"| node_context
node_context -->|"exposes state"| node_state_hook
node_state_hook -->|"calls"| node_api_client
node_api_client -->|"requests JSON API"| node_api_server
node_agent -.->|"uses JSON API"| node_api_server
node_api_server -->|"calls database access"| node_db_helper
node_db_helper -.->|"accesses"| node_d1
node_api_server -->|"loads seed data"| node_exercise_seed
node_api_server -->|"loads seed data"| node_demo_seed
node_workout_builder -.->|"manages sharing"| node_workout_share
node_workout_share -.->|"serves public workout"| node_client_phone
node_client_phone -.->|"saves PDF"| node_client_phone
node_exercise_library -.->|"shows images"| node_exercise_images

click node_app "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/app.tsx"
click node_dashboard "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/dashboard.tsx"
click node_client_list "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/client-list.tsx"
click node_client_detail "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/client-detail.tsx"
click node_client_form "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-client.tsx"
click node_exercise_library "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/exercise-library.tsx"
click node_workout_list "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/workout-list.tsx"
click node_workout_builder "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/workout-builder.tsx"
click node_schedule "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/schedule.tsx"
click node_session_form "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-session.tsx"
click node_payment_list "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/payment-list.tsx"
click node_payment_form "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-payment.tsx"
click node_state_hook "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/hooks/use-app.ts"
click node_context "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/context.tsx"
click node_api_client "https://github.com/clawnify/openpersonaltraining/blob/main/src/client/api.ts"
click node_api_server "https://github.com/clawnify/openpersonaltraining/blob/main/src/server/index.ts"
click node_db_helper "https://github.com/clawnify/openpersonaltraining/blob/main/src/server/db.ts"
click node_exercise_seed "https://github.com/clawnify/openpersonaltraining/blob/main/src/server/seed-exercises.ts"
click node_demo_seed "https://github.com/clawnify/openpersonaltraining/blob/main/src/server/seed-demo.ts"
click node_workout_share "https://github.com/clawnify/openpersonaltraining/blob/main/src/server/index.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_dashboard,node_client_phone toneBlue
class node_state_hook,node_context,node_api_client toneAmber
class node_client_list,node_client_detail,node_client_form,node_exercise_library,node_workout_list,node_workout_builder,node_schedule,node_session_form,node_payment_list,node_payment_form toneMint
class node_api_server,node_db_helper,node_d1,node_exercise_seed,node_demo_seed toneRose
class node_workout_share,node_exercise_images,node_trainer,node_agent toneIndigo
```

## Components

### Trainer interface

- [App and routing](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/app.tsx): `src/client/app.tsx`
- [Dashboard](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/dashboard.tsx): `src/client/components/dashboard.tsx`

### Client state and API

- [App state](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/hooks/use-app.ts): `src/client/hooks/use-app.ts`
- [Shared context](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/context.tsx): `src/client/context.tsx`
- [API client](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/api.ts): `src/client/api.ts`

### Coaching workflows

- [Client list](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/client-list.tsx): `src/client/components/client-list.tsx`
- [Client details](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/client-detail.tsx): `src/client/components/client-detail.tsx`
- [Client editor](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-client.tsx): `src/client/components/create-client.tsx`
- [Exercise library](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/exercise-library.tsx): `src/client/components/exercise-library.tsx`
- [Workout list](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/workout-list.tsx): `src/client/components/workout-list.tsx`
- [Workout builder](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/workout-builder.tsx): `src/client/components/workout-builder.tsx`
- [Schedule](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/schedule.tsx): `src/client/components/schedule.tsx`
- [Session editor](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-session.tsx): `src/client/components/create-session.tsx`
- [Payment ledger](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/payment-list.tsx): `src/client/components/payment-list.tsx`
- [Payment editor](https://github.com/clawnify/openpersonaltraining/blob/main/src/client/components/create-payment.tsx): `src/client/components/create-payment.tsx`

### API and persistence

- [HTTP API](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/index.ts): `src/server/index.ts`
- [Database access](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/db.ts): `src/server/db.ts`
- **Cloudflare D1**
- [Exercise dataset seed](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/seed-exercises.ts): `src/server/seed-exercises.ts`
- [Demo data seed](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/seed-demo.ts): `src/server/seed-demo.ts`

### Sharing and integrations

- [Public workout sharing](https://github.com/clawnify/openpersonaltraining/blob/main/src/server/index.ts): `src/server/index.ts`
- **jsDelivr images**

### Other components

- **Trainer**
- **Client phone or PDF**
- **Clawnify agent**

## Connections

- Trainer → App and routing: uses (evidence: `src/client/app.tsx`)
- App and routing → Dashboard: renders (evidence: `src/client/app.tsx`)
- App and routing → Client list: renders (evidence: `src/client/app.tsx`)
- App and routing → Client details: renders (evidence: `src/client/app.tsx`)
- App and routing → Exercise library: renders (evidence: `src/client/app.tsx`)
- App and routing → Workout list: renders (evidence: `src/client/app.tsx`)
- App and routing → Workout builder: renders (evidence: `src/client/app.tsx`)
- App and routing → Schedule: renders (evidence: `src/client/app.tsx`)
- App and routing → Payment ledger: renders (evidence: `src/client/app.tsx`)
- App and routing → App state: loads state (evidence: `src/client/app.tsx`)
- App and routing → Shared context: provides state (evidence: `src/client/app.tsx`)
- Client list → Client editor: opens editor (evidence: `src/client/components/client-list.tsx`)
- Client details → Client editor: opens editor (evidence: `src/client/components/client-detail.tsx`)
- Client details → Session editor: opens editor (evidence: `src/client/components/client-detail.tsx`)
- Client details → Payment editor: opens editor (evidence: `src/client/components/client-detail.tsx`)
- Schedule → Session editor: opens editor (evidence: `src/client/components/schedule.tsx`)
- Payment ledger → Payment editor: opens editor (evidence: `src/client/components/payment-list.tsx`)
- Client list → Shared context: reads state (evidence: `src/client/components/client-list.tsx`)
- Client details → Shared context: reads state (evidence: `src/client/components/client-detail.tsx`)
- Exercise library → Shared context: reads state (evidence: `src/client/components/exercise-library.tsx`)
- Workout builder → Shared context: reads state (evidence: `src/client/components/workout-builder.tsx`)
- Schedule → Shared context: reads state (evidence: `src/client/components/schedule.tsx`)
- Payment ledger → Shared context: reads state (evidence: `src/client/components/payment-list.tsx`)
- Shared context → App state: exposes state (evidence: `src/client/context.tsx`)
- App state → API client: calls (evidence: `src/client/hooks/use-app.ts`)
- API client → HTTP API: requests JSON API (evidence: `README.md`)
- Clawnify agent → HTTP API: uses JSON API (evidence: `README.md`)
- HTTP API → Database access: calls database access (evidence: `src/server/index.ts`)
- Database access → Cloudflare D1: accesses
- HTTP API → Exercise dataset seed: loads seed data (evidence: `src/server/index.ts`)
- HTTP API → Demo data seed: loads seed data (evidence: `src/server/index.ts`)
- Workout builder → Public workout sharing: manages sharing (evidence: `README.md`)
- Public workout sharing → Client phone or PDF: serves public workout (evidence: `README.md`)
- Client phone or PDF → Client phone or PDF: saves PDF (evidence: `README.md`)
- Exercise library → jsDelivr images: shows images (evidence: `README.md`)
