NoodleMap is my personal map for ramen, udon, and other noodle shops I have eaten at or want to keep track of. The repository is public, but it is primarily maintained as a personal project and operations notebook rather than a contributor-facing open source project.
Live app: https://noodle-map.marulabs.dev/
- Frontend: React, TypeScript, React Router, Vite, Chakra UI, MapLibre GL, Google Maps APIs
- Backend: Go, Gin, SQLite
- API contract: TypeSpec -> OpenAPI -> generated frontend/backend API types
- Local orchestration: Docker Compose
- Deployment: Render Blueprint in
render.yaml - Infrastructure: Terraform for Cloudflare/R2-related resources
- Tooling:
miseis introduced and will be expanded as the main tool version manager
web/: frontend appserver/: Go API serverdb/: SQLite schema, initialization scripts, queries, and seed datatypespec/: TypeSpec API contract sourceapi/openapi.yaml: generated OpenAPI outputterraform/: Terraform configurationdocs/: supporting notes and documentation
Generated files are committed for reviewability:
api/openapi.yamlweb/src/generated/api.tsserver/api/api.gen.go
Do not edit generated files directly. Update typespec/main.tsp first, then regenerate.
Frontend:
cd web
npm run dev
npm run build
npm run lint
npm run formatBackend:
cd server
go run .
go test ./...
go fmt ./...API generation from the repository root:
npm run api:generate
npm run api:checkDocker Compose from the repository root:
docker compose up --buildThe Compose setup starts the API server on http://localhost:8888 and the frontend on http://localhost:8080.
The backend now authenticates exclusively via Google Sign-In, so the following variables must be set in .env / web/.env before go run or docker compose up will work:
GOOGLE_OAUTH_CLIENT_ID(server) — OAuth 2.0 Client ID from Google Cloud Console.VITE_GOOGLE_OAUTH_CLIENT_ID(frontend) — same value as above; the Sign-In button does not render without it.ADMIN_EMAIL(server) — Google account email that should receive admin rights. Without it, no user can access/admin. The first Google login from this address provisions the admin account.
flowchart LR
tsp["typespec/main.tsp"] --> openapi["api/openapi.yaml"]
openapi --> webtypes["web/src/generated/api.ts"]
openapi --> goapi["server/api/api.gen.go"]
When changing routes, request/response shapes, or API-facing models:
- Update
typespec/main.tsp. - Run
npm run api:generate. - Use generated frontend types from
web/src/generated/api.ts. - Keep backend route wiring through the generated
server/apibindings.
mise is already present via .mise.toml.
Current responsibilities:
- Pin Terraform to
1.15.5. - Load local environment values from
.env. - Set AWS checksum options required by the current R2/S3-compatible tooling.
This setup is intentionally small for now. Node.js, npm, Go, and other developer tools may be moved into mise later as the local workflow becomes more standardized.
Terraform lives in terraform/ and currently manages Cloudflare/R2-related infrastructure, including the basemap R2 module. State is configured with an S3-compatible backend pointing at Cloudflare R2.
Typical commands:
cd terraform
terraform init
terraform planApplying changes requires valid Cloudflare/R2 credentials in the environment. .env.example lists the currently expected secret variables.
Render service configuration is defined in render.yaml.
- Backend: Docker web service with a persistent disk for SQLite data.
- Frontend: Render static site.
- Public domains:
noodle-map.marulab.jpandnoodle-map.marulabs.dev. - API traffic from the frontend is rewritten to the Render backend.
Secrets such as GOOGLE_OAUTH_CLIENT_ID, ADMIN_EMAIL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, VITE_GOOGLE_API_KEY, and VITE_GOOGLE_OAUTH_CLIENT_ID are configured outside the repository.
- Japanese UI text is UTF-8. If text looks garbled, reopen the file as UTF-8 before editing.
- Before finishing frontend text changes, run
npm run check:mojibakefromweb/. - After editing any
CLAUDE.md, runnpm run sync-agentsfrom the repository root to update the matchingAGENTS.mdfiles.
