A modern web app for posting βhalf-baked ideasβ so others can pick them up, discuss, and contribute.
- Frontend: React (Vite), React Router, TanStack Query, Tailwind, Framer Motion
- Backend: Node/Express, Prisma ORM, Zod validation, JWT auth
- Database: MySQL 8 (Docker) + Adminer UI
- Observability: Prometheus, mysqld_exporter, Grafana (API & DB metrics)
- Orchestration: Docker Compose
This README is sanitized: no passwords or secrets. Configure those in
.env(never commit it).
- Features
- System diagrams
- Tech stack
- Project structure
- Setup (Docker)
- API quickstart
- Observability
- Troubleshooting
- License
- β¨ Polished landing page (glassy/gradient theme)
- π€ Auth: register & login with clear validation messages (Zod)
- π Post ideas with tags, status, and optional GitHub repo link
- π Filterable feed (tag & search) with clean idea cards
- π βContributionsβ CTA opens the ideaβs GitHub repo
- β€οΈ βLooking for helpβ chip for ideas needing collaborators
- π§ Health check:
GET /health - π Metrics:
GET /metrics(OpenMetrics via prom-client) - ποΈ Adminer DB UI for quick inspection
- π Prometheus + Grafana dashboards (API latency, req/sec, MySQL stats)
Frontend: React 18, Vite, React Router, TanStack Query, TailwindCSS, Framer Motion
Backend: Node 20, Express, Prisma, Zod, jsonwebtoken, bcryptjs
Database: MySQL 8 + Adminer
Observability: prom-client (Node), Prometheus, mysqld_exporter, Grafana
Orchestration: Docker Compose
halfbake/
ββ client/ # Vite React app
ββ server/ # Express API + Prisma
β ββ prisma/ # schema.prisma
β ββ src/
β β ββ routes/ # auth.ts, ideas.ts
β β ββ middleware/ # auth.ts (requireAuth)
β β ββ utils/ # db.ts (Prisma client)
β β ββ metrics.ts # prom-client registration + /metrics
β β ββ server.ts # app wiring
β ββ scripts/wait-for-mysql.cjs
ββ observability/
β ββ prometheus.yml # scrape config (API + MySQL exporter)
β ββ grafana/ # optional provisioning (datasources/dashboards)
ββ assets/ # PNG diagrams used in this README
ββ docker-compose.yml
ββ README.md
- Docker Desktop running
- Free ports: 5173, 8080, 8081, 9090, 3000
# Database connection (service host is "mysql" inside Compose)
DATABASE_URL="mysql://<DB_USER>:<DB_PASSWORD>@mysql:3306/<DB_NAME>"
# Auth
JWT_SECRET="<generate a long random secret>" # e.g. openssl rand -hex 48
JWT_EXPIRES_IN="604800" # 7 days (in seconds)
CLIENT_ORIGIN="http://localhost:5173"Tip: generate a secret on macOS/Linux β
openssl rand -hex 48
docker compose up -d
# clean rebuild & wipe data:
# docker compose down -v && docker compose up -d --build- Frontend β http://localhost:5173
- API health β http://localhost:8080/health β
{"ok":true} - Adminer β http://localhost:8081 (Server:
mysql, user/password you created, DB name from.env) - Metrics (raw) β http://localhost:8080/metrics
- Prometheus β http://localhost:9090 β Status β Targets should show
api,mysql,prometheusas UP - Grafana β http://localhost:3000 (set admin password on first login)
# Register
curl -s -X POST http://localhost:8080/api/auth/register -H 'Content-Type: application/json' -d '{"email":"you@example.com","password":"P@ssw0rd!","name":"You"}'
# Login (copy "token" from the response)
curl -s -X POST http://localhost:8080/api/auth/login -H 'Content-Type: application/json' -d '{"email":"you@example.com","password":"P@ssw0rd!"}'
# Use token for authorized routes
TOKEN="paste-token-here"
# Create an idea
curl -s -X POST http://localhost:8080/api/ideas -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"title":"Mock idea","summary":"Small idea","tags":["web","ai"],"repoUrl":"https://github.com/you/project"}'
# List ideas
curl -s "http://localhost:8080/api/ideas?q=mock"If you wiped the DB but kept an old token, idea creation can fail with a foreign key error (ownerId). Login again to mint a fresh token.
- Scrapes targets every 15s (API
/metricsandmysql-exporter:9104/metrics). - Try these expressions (Prometheus Expression browser or Grafana Explore):
sum by (route, method) (rate(http_request_duration_seconds_count[2m]))
histogram_quantile(0.9, sum by (le, route, method) (rate(http_request_duration_seconds_bucket[5m])))
mysql_up
mysql_global_status_threads_connected
- Connections β Data sources β Add β Prometheus
URL:http://prometheus:9090β Save & test - Explore β pick Prometheus β paste queries above β Run query
- To save charts: Dashboards β New β Add visualization β Prometheus, paste a query, pick Time series, Apply, Save.
Requests/sec by route & method

API not responding
docker compose logs server --tail=200Prometheus mysql target DOWN
- Ensure exporter is running:
docker compose ps mysql-exporter - Provide exporter creds (DSN env or mount
observability/.my.cnf) - Grant minimal privileges to the exporter user:
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO '<exporter_user>'@'%';
FLUSH PRIVILEGES;Foreign key ownerId error
- You reset the DB while using an old JWT. Login again to refresh the token.
MIT β have fun building!



