Zero inbound ports
cloudflared dials outward. The VM firewall allows SSH only — no 80, no 443, no TLS cert on the box.
Bun/ElysiaJS API, two Vue SPAs, one VM behind a Cloudflare Tunnel.
ภาษาไทย — เอกสารส่วนที่อธิบายความหมายของระบบมีฉบับภาษาไทยแล้วที่ หน้าเอกสารภาษาไทย หรือใช้ปุ่มเปลี่ยนภาษาบนแถบด้านบน
If you are new to the project, start at Why this system exists — the goal, the risks it exists to remove, and how success is judged. Then what each role has to do for the three journeys end to end.
If you are deploying today, start at Current state & blockers. The stack deploys cleanly and you will still not be able to log in from the two *.pages.dev URLs — that is a cookie-domain constraint, not a bug, and it is covered there.
| Section | What it answers |
|---|---|
| Why this system exists | The goal, the objectives behind it, and how you would know it worked |
| Domain context | The vocabulary, the bounded contexts, and which part owns which rule |
| What each role does | Contractor, safety officer and inspector — what each must do, and what they are refused |
| Using the Contractor app | Every module of the contractor app, and the steps to use each one |
| Using the Safety app | Every module of the other app, both the officer and the inspector halves |
| System architecture | Where things run, how a request travels, why the box has no open ports |
| Data model / ER | The 25 tables, what actually relates to what, and what only looks like it does |
| Permit lifecycle | The status machine and who may move it |
| CI/CD pipelines | The three workflows, their gates, and the secrets each needs |
| Deployment 10–13 | The normative deploy files, mirrored into all three repos |
| Current state & blockers | What is live, what is pending, what will bite you |
| Open items — needs a human | Everything waiting on a person: a decision to make, or an action code cannot take |
| Doc drift | Where the normative files no longer match production |
The built site is a folder of static files. It must be served over HTTP — double-clicking index.html will not work, because every asset is referenced by an absolute path (/assets/...) which file:// resolves to your filesystem root.
Build and package (on a machine with this repo):
bun install
bun run docs:build
cd docs/.vitepress && zip -r ~/e-safework-docs.zip distThat produces a ~12 MB zip. Copy it anywhere.
Open it (on the other Mac or PC — nothing from this repo needed):
unzip e-safework-docs.zip && cd dist
npx serve # or: bunx serveThen open the URL it prints, usually http://localhost:3000.
Use serve rather than python3 -m http.server: this site uses clean URLs, and Python's server does not fall back to .html, so every direct link and every page refresh answers 404. Tested — serve handles it, http.server does not.
dist/ is a website and has to be served. To hand someone actual files they can double-click — no server, no install — export the human-facing pages as PDFs:
bun run docs:pdf # writes docs-pdf/, English and ThaiRenders through headless Chrome, so the mermaid diagrams come out drawn rather than blank. Pass paths to pick your own pages: ./scripts/export-docs-pdf.sh /guide/ci-cd.
| Repo | Runs as | Reaches production via |
|---|---|---|
smart-work-permit-api | Docker image on the VM | GHCR image → SSH → docker compose up -d --wait |
smart-work-permit-contractor-frontend | Static SPA | Cloudflare Pages project esw-contractor |
smart-work-permit-frontend (Safety + Inspector) | Static SPA | Cloudflare Pages project esw-safety |
The umbrella repo you are reading holds the docs and the cross-repo glue only — all three application repos are gitignored here and are independent git repositories.