Page:
System Overview
2
System Overview
Othmane Ataallah edited this page 2026-07-29 08:39:03 +02:00
System Overview — the bigger picture
How our three projects, our tools and our Git workflow fit together. Ten minutes here saves weeks of confusion. Diagrams are Mermaid — Gitea renders them natively.
1. The whole system at a glance
Three products, one contract, one origin server. Every dev has the SAME local setup; Gitea is the only shared machine.
flowchart TB
subgraph TEAM["👥 Team"]
PM["PM<br/>backlog · reviews · decisions<br/>owns openapi.yaml"]
DEVS["3 devs<br/>one per repo"]
end
subgraph GITEA["🗄️ Gitea — ORIGIN (the only shared server)"]
direction LR
RAPI["trizagenda-api<br/>code · issues · board"]
RWEB["trizagenda-web<br/>code · issues · board"]
RMOB["trizagenda-mobile<br/>code · issues · board"]
RTEAM["trizagenda-team<br/>this wiki · shared docs"]
end
subgraph MACHINE["💻 Each dev machine (identical, self-sufficient)"]
direction LR
CLONES["local clones<br/>feature branches"]
RUNTIME["local runtime<br/>API + clients + docker services<br/>(diagram 2)"]
end
DEVS -->|"branch → push → Pull Request"| GITEA
PM -->|"review ≤ 24h · squash merge · milestone tags"| GITEA
GITEA -->|"clone · pull --rebase daily"| CLONES
CLONES --> RUNTIME
classDef origin fill:#e8eef7,stroke:#1a4b8c,stroke-width:2px;
class GITEA origin;
Read it like this: code and decisions flow through Gitea and nowhere else. Nothing is deployed anywhere yet — "the system" runs complete on every dev machine, every day.
2. Runtime — how the three apps exchange data (on YOUR machine)
flowchart LR
subgraph CLIENTS["Clients"]
WEB["🌐 trizagenda-web<br/>React 19 · Vite · :5173<br/>session = httpOnly refresh cookie"]
MOB["📱 trizagenda-mobile<br/>Flutter · emulator<br/>session = X-Refresh-Token header"]
end
subgraph CONTRACT["📜 THE contract"]
SPEC["openapi.yaml v1.2.1<br/>single source of truth<br/>(copy in each repo)"]
PRISM["Prism mock · :4010<br/>fake API serving the spec"]
end
subgraph APISRV["⚙️ trizagenda-api — Spring Boot · :8080/api/v1"]
REST["REST JSON<br/>JWT Bearer 15 min<br/>+ rotating refresh tokens"]
STOMP["WebSocket / STOMP<br/>(M4 — topic contract = spec candidate)"]
end
subgraph COMPOSE["🐳 docker compose up -d (in trizagenda-api/)"]
PG[("PostgreSQL 16 · :5432<br/>THE database — schema owned by Flyway")]
REDIS[("Redis 7 · :6379<br/>rate-limit & cache backend (M6)")]
MINIO[("MinIO · :9000 / UI :9001<br/>S3 files — avatars & attachments")]
MAILPIT["Mailpit · SMTP :1025<br/>inbox UI → http://localhost:8025<br/>catches EVERY dev email (OTP reset)"]
end
WEB -->|"HTTP JSON · cookie flow"| REST
MOB -->|"HTTP JSON · 10.0.2.2:8080<br/>X-Client-Type: mobile"| REST
WEB -.->|"mock-first features"| PRISM
MOB -.->|"mock-first features"| PRISM
SPEC --> PRISM
SPEC -.->|"npm run generate:api → TS types"| WEB
REST --> PG
REST --> REDIS
REST --> MINIO
REST -->|"OTP reset email"| MAILPIT
STOMP -.->|"real-time notifications (M4)"| WEB
STOMP -.->|"real-time notifications (M4)"| MOB
classDef spec fill:#fdf3d8,stroke:#b8860b,stroke-width:2px;
class SPEC spec;
classDef future stroke-dasharray: 5 5;
class STOMP future;
The rules that make this work:
- Clients NEVER talk to the database or to each other — everything crosses the API, which enforces roles/scope from the JWT. The only shared state between web and mobile IS the API's database.
openapi.yamlis the treaty. The API implements it, web generates its TypeScript types from it, Prism mocks it, and nobody invents an endpoint outside it. Spec change = version bump by the PM, announced, copies re-synced (npm run generate:apion web).- Mock-first: new client features are built against Prism (:4010) so nobody waits on
the API dev; auth is the exception — always the real API. At each milestone's
integration checkpoint, that feature flips from mock to real.
- Mobile nuance: the app currently ships a demo-data layer (fake repositories inside
the app) instead of Prism for non-auth domains — same principle, same swap points
(see mobile
ARCHITECTURE.md§6).
- Mobile nuance: the app currently ships a demo-data layer (fake repositories inside
the app) instead of Prism for non-auth domains — same principle, same swap points
(see mobile
- Emails never leave your machine in dev: the API sends real SMTP to Mailpit
(http://localhost:8025). Production swaps in a real SMTP server via
MAIL_*env vars — same code, differentapplication-*.ymlprofile. - The database schema belongs to Flyway migrations (
V*__*.sqlin the API repo) — never edit an applied migration; local reset =docker compose down -v.
3. Git — origin vs your machine
Trunk-based, squash-only, tags per milestone (full rules).
gitGraph
commit id: "main"
commit id: "M1 starts"
branch feat/API-12-rate-limit
checkout feat/API-12-rate-limit
commit id: "feat: limiter"
commit id: "test: limiter"
checkout main
merge feat/API-12-rate-limit id: "PR 12 — squash" type: HIGHLIGHT
branch feat/API-14-blacklist
checkout feat/API-14-blacklist
commit id: "feat: blacklist"
checkout main
merge feat/API-14-blacklist id: "PR 14 — squash"
commit id: "checkpoint fixes" tag: "v0.1.0"
mainis protected — it only moves by squash-merged PRs, so one commit = one issue, andgit logreads like the changelog.- Local machine: your clone, your feature branches (
feat/API-12-slug), your WIP commits — messy is fine there, the squash cleans it up. - Origin (Gitea): protected
main+ your pushed branches + the PR conversation. - Every morning:
git pull --rebase origin mainon your branch — small daily rebases instead of one giant conflict at PR time. - Milestone end: the PM tags
main(v0.1.0…v1.0.0) right after the integration checkpoint passes.
4. The daily loop — issue to merged
flowchart LR
A["📋 Pick the top<br/>'Ready' issue<br/>on the milestone board"] --> B["🌱 branch<br/>feat/XXX-nn-slug"]
B --> C["🔨 code + tests<br/>mvn verify · npm test<br/>flutter analyze && flutter test"]
C --> D["⬆️ push → PR on Gitea<br/>template + screenshots"]
D --> E{"👀 PM review<br/>≤ 24h"}
E -->|"changes requested"| C
E -->|"approved"| F["🔀 squash merge<br/>→ main"]
F --> G["🔁 everyone:<br/>git pull --rebase"]
G --> A
classDef gate fill:#fdecea,stroke:#c0392b;
class E gate;
While a PR waits for review: start the next Ready issue — never idle on a blocked PR.
5. Dev vs production (so nobody confuses the two)
| Dev (your machine) | Production (later) | |
|---|---|---|
| API config | application-dev.yml (safe defaults) |
application-prod.yml — everything from env vars, fail-fast |
| Database | docker Postgres, disposable (down -v) |
managed PostgreSQL, backed up |
| Emails | Mailpit (nothing leaves the machine) | real SMTP (MAIL_* env) |
| Files | docker MinIO | S3-compatible storage |
| Secrets | dev-only values in dev yml | env vars only — never in git |
| API docs | Swagger UI on | off |
Same code, same images, different profile — that's the whole trick.