|
| 1 | +# Tecnova Platform Architecture |
| 2 | + |
| 3 | +This document captures the current Tecnova Nagasaki operations platform and its |
| 4 | +planned expansion scope. |
| 5 | + |
| 6 | +The first diagram is a compact current-state overview. The detailed map below it |
| 7 | +keeps the broader current and planned scope in one Mermaid `architecture-beta` |
| 8 | +diagram. Mermaid brand logos require renderer-level icon-pack registration, so |
| 9 | +the portable diagrams use text labels and the brand logos are shown as badges. |
| 10 | + |
| 11 | +## Current Implementation Overview |
| 12 | + |
| 13 | +<p align="center"> |
| 14 | + <img src="https://img.shields.io/badge/Next.js-16-000?logo=next.js&logoColor=white" alt="Next.js 16"> |
| 15 | + <img src="https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=black" alt="React 19"> |
| 16 | + <img src="https://img.shields.io/badge/Hono-4-E36002?logo=hono&logoColor=white" alt="Hono 4"> |
| 17 | + <img src="https://img.shields.io/badge/Cloudflare_Workers-F38020?logo=cloudflare&logoColor=white" alt="Cloudflare Workers"> |
| 18 | + <img src="https://img.shields.io/badge/Cloudflare_D1-SQLite-F38020?logo=cloudflare&logoColor=white" alt="Cloudflare D1"> |
| 19 | + <img src="https://img.shields.io/badge/Drizzle_ORM-0.45-C5F74F?logo=drizzle&logoColor=black" alt="Drizzle ORM"> |
| 20 | + <img src="https://img.shields.io/badge/Google_Sheets-API-34A853?logo=googlesheets&logoColor=white" alt="Google Sheets API"> |
| 21 | + <img src="https://img.shields.io/badge/Google_OAuth-Better_Auth-4285F4?logo=google&logoColor=white" alt="Google OAuth and Better Auth"> |
| 22 | + <img src="https://img.shields.io/badge/Vercel-Deploy-000?logo=vercel&logoColor=white" alt="Vercel"> |
| 23 | + <img src="https://img.shields.io/badge/GitHub_Actions-CI-2088FF?logo=githubactions&logoColor=white" alt="GitHub Actions"> |
| 24 | +</p> |
| 25 | + |
| 26 | +```mermaid |
| 27 | +flowchart LR |
| 28 | + subgraph devices["Operation Devices"] |
| 29 | + ipad["Reception iPad"] |
| 30 | + pc["Admin PC"] |
| 31 | + end |
| 32 | +
|
| 33 | + subgraph frontend["Vercel Frontend"] |
| 34 | + checkin["Checkin PWA<br/>Next.js 16 / React 19<br/>ZXing QR Scan"] |
| 35 | + admin["Admin Dashboard<br/>Next.js 16 / React 19"] |
| 36 | + ui["Shared UI<br/>shadcn/ui / Tailwind CSS<br/>apiFetch / MeProvider"] |
| 37 | + end |
| 38 | +
|
| 39 | + subgraph api["Cloudflare Workers API"] |
| 40 | + hono["Hono REST API"] |
| 41 | + betterAuth["Better Auth<br/>Google OAuth Sessions"] |
| 42 | + d1[("Cloudflare D1<br/>SQLite")] |
| 43 | + end |
| 44 | +
|
| 45 | + subgraph data["Current Data Model"] |
| 46 | + participants[("participants")] |
| 47 | + events[("events")] |
| 48 | + sessions[("sessions")] |
| 49 | + mentors[("mentors")] |
| 50 | + authTables[("Better Auth tables")] |
| 51 | + end |
| 52 | +
|
| 53 | + subgraph google["Google Workspace"] |
| 54 | + oauth["Google OAuth"] |
| 55 | + sheets["Student Google Sheet<br/>Sheets API"] |
| 56 | + gas["GAS Webhook"] |
| 57 | + drive["Drive Folders"] |
| 58 | + end |
| 59 | +
|
| 60 | + subgraph repo["Monorepo And Delivery"] |
| 61 | + workspace["pnpm / Turborepo<br/>TypeScript / Zod / Drizzle"] |
| 62 | + ci["GitHub Actions<br/>Biome / Type Check"] |
| 63 | + deploy["Wrangler + Vercel Deploy"] |
| 64 | + end |
| 65 | +
|
| 66 | + ipad --> checkin |
| 67 | + pc --> admin |
| 68 | + checkin --> ui |
| 69 | + admin --> ui |
| 70 | + checkin --> hono |
| 71 | + admin --> hono |
| 72 | +
|
| 73 | + hono --> betterAuth |
| 74 | + betterAuth --> oauth |
| 75 | + betterAuth --> mentors |
| 76 | + hono --> d1 |
| 77 | + d1 --> participants |
| 78 | + d1 --> events |
| 79 | + d1 --> sessions |
| 80 | + d1 --> mentors |
| 81 | + d1 --> authTables |
| 82 | +
|
| 83 | + hono --> sheets |
| 84 | + hono -. waitUntil .-> gas |
| 85 | + gas --> drive |
| 86 | +
|
| 87 | + workspace --> checkin |
| 88 | + workspace --> admin |
| 89 | + workspace --> hono |
| 90 | + workspace --> d1 |
| 91 | + ci --> deploy |
| 92 | + deploy --> checkin |
| 93 | + deploy --> admin |
| 94 | + deploy --> hono |
| 95 | + deploy --> d1 |
| 96 | +
|
| 97 | + classDef device fill:#f8fafc,stroke:#64748b,color:#0f172a; |
| 98 | + classDef frontend fill:#e8f3ff,stroke:#2563eb,color:#0f172a; |
| 99 | + classDef backend fill:#fff7ed,stroke:#f97316,color:#0f172a; |
| 100 | + classDef db fill:#ecfdf5,stroke:#16a34a,color:#0f172a; |
| 101 | + classDef external fill:#fefce8,stroke:#ca8a04,color:#0f172a; |
| 102 | + classDef ops fill:#f5f3ff,stroke:#7c3aed,color:#0f172a; |
| 103 | +
|
| 104 | + class ipad,pc device; |
| 105 | + class checkin,admin,ui frontend; |
| 106 | + class hono,betterAuth backend; |
| 107 | + class d1,participants,events,sessions,mentors,authTables db; |
| 108 | + class oauth,sheets,gas,drive external; |
| 109 | + class workspace,ci,deploy ops; |
| 110 | +``` |
| 111 | + |
| 112 | +## Detailed Architecture Map |
| 113 | + |
| 114 | +```mermaid |
| 115 | +architecture-beta |
| 116 | + group people(internet)[People And Devices] |
| 117 | + service child_kiosk(server)[Child And Reception iPad] in people |
| 118 | + service mentor_phone(server)[Mentor Smartphone Future] in people |
| 119 | + service admin_pc(server)[Admin PC Browser] in people |
| 120 | + service researcher_pc(server)[Researcher Analysis PC Future] in people |
| 121 | + service parent_browser(server)[Parent Browser Future] in people |
| 122 | +
|
| 123 | + group frontend(cloud)[Vercel Frontend Apps] |
| 124 | + service checkin_app(server)[apps checkin Next PWA Current] in frontend |
| 125 | + service admin_app(server)[apps admin Next Web Current] in frontend |
| 126 | + service mentor_app(server)[apps mentor Next PWA Future] in frontend |
| 127 | + service analytics_app(server)[Analytics Dashboard Future] in frontend |
| 128 | + service parent_app(server)[Parent View Future] in frontend |
| 129 | +
|
| 130 | + group edge(cloud)[Cloudflare Edge Platform] |
| 131 | + service worker(server)[apps api Hono Workers Current] in edge |
| 132 | + service d1(database)[Cloudflare D1 SQLite Current] in edge |
| 133 | + service r2(disk)[Cloudflare R2 Future] in edge |
| 134 | + service public_api(server)[Public API Future] in edge |
| 135 | + service api_keys(server)[API Key Auth Future] in edge |
| 136 | +
|
| 137 | + group auth(cloud)[Authentication Boundary] |
| 138 | + service better_auth(server)[Better Auth Current] in auth |
| 139 | + service google_oauth(internet)[Google OAuth Current] in auth |
| 140 | + service mentor_allowlist(database)[Mentors Allowlist Current] in auth |
| 141 | + service session_cookie(disk)[Session Cookies Current] in auth |
| 142 | +
|
| 143 | + group google(internet)[Google Workspace Services] |
| 144 | + service student_sheet(disk)[Student Sheet Current] in google |
| 145 | + service teacher_sheet(disk)[Teacher Sheet Future Sync] in google |
| 146 | + service sheets_api(server)[Google Sheets API Current] in google |
| 147 | + service gas_drive(server)[GAS Drive Webhook Current] in google |
| 148 | + service drive_folder(disk)[Participant Drive Folders Current] in google |
| 149 | + service form_feed(server)[Google Form Feed External] in google |
| 150 | +
|
| 151 | + group core(server)[Current Backend Domain] |
| 152 | + service participants(database)[Participants Current] in core |
| 153 | + service events(database)[Events Current] in core |
| 154 | + service sessions(database)[Sessions Current] in core |
| 155 | + service mentors(database)[Mentors Current] in core |
| 156 | + service auth_tables(database)[Better Auth Tables Current] in core |
| 157 | +
|
| 158 | + group planned(server)[Planned Domain Model] |
| 159 | + service activity_logs(database)[Activity Logs Future] in planned |
| 160 | + service activity_categories(database)[Activity Categories Future] in planned |
| 161 | + service equipment(database)[Equipment Master Future] in planned |
| 162 | + service collaborators(database)[Collaborators Future] in planned |
| 163 | + service reflection_ocr(server)[Vision LLM OCR Future] in planned |
| 164 | + service csv_export(disk)[CSV Export Future] in planned |
| 165 | + service offline_sync(server)[Offline Sync Future] in planned |
| 166 | + service crowd_status(server)[Crowd Status Future] in planned |
| 167 | +
|
| 168 | + group packages(disk)[Monorepo Shared Packages] |
| 169 | + service ui_pkg(disk)[packages ui Current] in packages |
| 170 | + service shared_pkg(disk)[packages shared Current] in packages |
| 171 | + service db_pkg(disk)[packages db Current] in packages |
| 172 | + service schemas_pkg(disk)[Zod Schemas Current] in packages |
| 173 | + service sheets_client(disk)[Sheets Client Current] in packages |
| 174 | + service migrations(disk)[Drizzle Migrations Current] in packages |
| 175 | +
|
| 176 | + group delivery(cloud)[Delivery And Operations] |
| 177 | + service github(server)[GitHub Repository Current] in delivery |
| 178 | + service actions(server)[GitHub Actions Current] in delivery |
| 179 | + service ci(server)[Biome And Type Check Current] in delivery |
| 180 | + service deploy_api(server)[Wrangler Deploy Current] in delivery |
| 181 | + service vercel_deploy(server)[Vercel Deploy Current] in delivery |
| 182 | + service secrets(disk)[Wrangler And Vercel Secrets Current] in delivery |
| 183 | + service ops_manual(disk)[Runbook And Rehearsal Current] in delivery |
| 184 | + service legacy_import(disk)[Prior Year D1 Import Future] in delivery |
| 185 | +
|
| 186 | + child_kiosk:R --> L:checkin_app |
| 187 | + mentor_phone:R --> L:mentor_app |
| 188 | + admin_pc:R --> L:admin_app |
| 189 | + researcher_pc:R --> L:analytics_app |
| 190 | + parent_browser:R --> L:parent_app |
| 191 | +
|
| 192 | + checkin_app:R --> L:worker |
| 193 | + admin_app:R --> L:worker |
| 194 | + mentor_app:R --> L:worker |
| 195 | + analytics_app:R --> L:worker |
| 196 | + parent_app:R --> L:public_api |
| 197 | +
|
| 198 | + checkin_app:T --> B:ui_pkg |
| 199 | + admin_app:T --> B:ui_pkg |
| 200 | + mentor_app:T --> B:ui_pkg |
| 201 | + checkin_app:B --> T:shared_pkg |
| 202 | + admin_app:B --> T:shared_pkg |
| 203 | + mentor_app:B --> T:shared_pkg |
| 204 | +
|
| 205 | + worker:L --> R:better_auth |
| 206 | + better_auth:R --> L:google_oauth |
| 207 | + better_auth:B --> T:session_cookie |
| 208 | + better_auth:T --> B:mentor_allowlist |
| 209 | + mentor_allowlist:R --> L:mentors |
| 210 | +
|
| 211 | + worker:B --> T:d1 |
| 212 | + d1:B --> T:participants |
| 213 | + d1:B --> T:events |
| 214 | + d1:B --> T:sessions |
| 215 | + d1:B --> T:mentors |
| 216 | + d1:B --> T:auth_tables |
| 217 | + d1:R --> L:activity_logs |
| 218 | + d1:R --> L:activity_categories |
| 219 | + d1:R --> L:equipment |
| 220 | + d1:R --> L:collaborators |
| 221 | +
|
| 222 | + worker:R --> L:sheets_api |
| 223 | + sheets_api:R --> L:student_sheet |
| 224 | + teacher_sheet:R --> L:student_sheet |
| 225 | + form_feed:R --> L:teacher_sheet |
| 226 | + worker:R --> L:gas_drive |
| 227 | + gas_drive:R --> L:drive_folder |
| 228 | +
|
| 229 | + public_api:B --> T:api_keys |
| 230 | + public_api:L --> R:worker |
| 231 | + public_api:R --> L:crowd_status |
| 232 | + worker:R --> L:r2 |
| 233 | + r2:R --> L:reflection_ocr |
| 234 | + reflection_ocr:R --> L:activity_logs |
| 235 | + activity_logs:B --> T:csv_export |
| 236 | + activity_logs:R --> L:analytics_app |
| 237 | + sessions:R --> L:crowd_status |
| 238 | + offline_sync:L --> R:checkin_app |
| 239 | + offline_sync:R --> L:worker |
| 240 | +
|
| 241 | + db_pkg:R --> L:d1 |
| 242 | + migrations:R --> L:d1 |
| 243 | + schemas_pkg:R --> L:shared_pkg |
| 244 | + shared_pkg:R --> L:worker |
| 245 | + sheets_client:R --> L:sheets_api |
| 246 | +
|
| 247 | + github:R --> L:actions |
| 248 | + actions:R --> L:ci |
| 249 | + actions:R --> L:deploy_api |
| 250 | + actions:R --> L:vercel_deploy |
| 251 | + deploy_api:R --> L:worker |
| 252 | + deploy_api:B --> T:migrations |
| 253 | + vercel_deploy:R --> L:checkin_app |
| 254 | + vercel_deploy:R --> L:admin_app |
| 255 | + vercel_deploy:R --> L:mentor_app |
| 256 | + secrets:T --> B:worker |
| 257 | + secrets:T --> B:checkin_app |
| 258 | + secrets:T --> B:admin_app |
| 259 | + ops_manual:R --> L:child_kiosk |
| 260 | + legacy_import:R --> L:d1 |
| 261 | +``` |
| 262 | + |
| 263 | +## Legend |
| 264 | + |
| 265 | +- `Current` means the component exists in the repository or is already described |
| 266 | + as deployed in the handoff notes. |
| 267 | +- `Future` means planned Phase 1.5 or Phase 2 scope from the requirements and |
| 268 | + MVP documentation. |
| 269 | +- `/api/*` and `/checkin/*` both pass through Better Auth and the `mentors` |
| 270 | + allowlist. Planned `/public/v1/*` traffic is separated behind API key auth. |
| 271 | +- The private teacher-managed sheet remains outside the in-house database. The |
| 272 | + platform reads and writes only the student-facing sheet columns required for |
| 273 | + operations. |
| 274 | +- Cloudflare D1 stores operational data as UTC epoch milliseconds, while event |
| 275 | + dates and user-facing displays are resolved in JST. |
| 276 | + |
| 277 | +## Mermaid Notes |
| 278 | + |
| 279 | +- GitHub Markdown renders Mermaid blocks when they are fenced with the |
| 280 | + `mermaid` language identifier. |
| 281 | +- Mermaid `architecture-beta` starts with `architecture-beta` and supports |
| 282 | + `group`, `service`, and directional edge declarations. |
| 283 | +- Built-in architecture icons are limited to `cloud`, `database`, `disk`, |
| 284 | + `internet`, and `server`; richer vendor icons require registered icon packs. |
0 commit comments