Phase 0: scaffold three-service backend (api/worker/frontend)

api/ (ElysiaJS+Bun WS gateway skeleton), worker/ (Rust, Redis dirty-chunk
stream consumer behind a swappable RenderBackend trait), frontend/
(ElysiaJS+Pug+Tailwind4+Alpine, one server-rendered page) — all three
verified running locally. docker-compose wires them up with postgres,
redis, minio (rendered tile/mesh object storage), and Caddy as reverse
proxy.
This commit is contained in:
2026-08-08 14:10:04 +02:00
commit 4c7cc26281
26 changed files with 1653 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
import { Elysia } from "elysia";
import pug from "pug";
import { join } from "path";
// Phase 0 skeleton: one server-rendered page. The real map viewer (Leaflet 2D + Babylon 3D
// canvases, server selector, chat box, marker tool) lands starting Phase 1 — this just proves
// the Pug+Tailwind+Alpine rendering pipeline end to end.
const renderIndex = pug.compileFile(join(import.meta.dir, "views/index.pug"));
const app = new Elysia()
.get("/", () => new Response(renderIndex({}), { headers: { "Content-Type": "text/html" } }))
.get("/health", () => ({ status: "ok" }))
.get("/css/tailwind.css", () => Bun.file(join(import.meta.dir, "public/css/tailwind.css")))
.listen(Number(process.env.PORT ?? 3001));
console.log(`[frontend] listening on :${app.server?.port}`);
+1
View File
@@ -0,0 +1 @@
@import "tailwindcss";
+12
View File
@@ -0,0 +1,12 @@
doctype html
html(lang="en")
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1")
title MCMapper
link(rel="stylesheet" href="/css/tailwind.css")
script(defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js")
body.bg-neutral-900.text-neutral-100.min-h-screen.flex.items-center.justify-center
div(x-data="{ ready: true }")
h1.text-2xl.font-semibold MCMapper
p.text-neutral-400(x-show="ready") Backend scaffold is up. Map viewer lands in Phase 1.