Files
agw/AGENTS.md
Felix Förtsch 4e3aa682ac abgeordnetenwatch PWA + backend
feature-based React PWA with Hono backend:
- feed from abgeordnetenwatch.de API (polls by topic + politician)
- follow topics, search and follow politicians
- geo-based politician discovery via Nominatim
- push notifications for new polls via web-push
- service worker with offline caching
- deploy to Uberspace 8 (systemd, PostgreSQL, web backend proxy)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 08:14:22 +01:00

3.6 KiB

Agent Instructions

These instructions are authoritative for work in this repository.

Project Overview

Abgeordnetenwatch PWA + Backend — a progressive web app that lets users follow Bundestag/Landtag topics and politicians, displaying a personalized feed of votes with push notifications for new votes. The PWA queries the Abgeordnetenwatch API directly for browsing; the backend polls for new votes and sends Web Push notifications to subscribed devices.

Stack — PWA (root)

Layer Tool
Runtime Bun
Build Vite + TanStack Router Plugin + vite-plugin-pwa (injectManifest)
UI React 19 + shadcn/ui + Tailwind CSS v4
Routing TanStack Router (file-based, src/routes/)
State Zustand (UI), localStorage (Follows)
Validation Zod
Code Quality Biome + simple-git-hooks + lint-staged
Testing Vitest + Testing Library

Stack — Backend (server/)

Layer Tool
Runtime Node 22 (production via tsx), Bun (development)
Framework Hono + @hono/node-server
Database PostgreSQL + Drizzle ORM
Job Queue pg-boss (cron: poll-checker every 15 min)
Push web-push (VAPID)
Validation Zod
Testing Vitest

Architecture

src/                          PWA source
├── features/                 Feature modules (feed, topics, politicians, location, settings)
│   └── <feature>/            components/, hooks/, lib/, index.ts
├── shared/                   Shared code
│   ├── components/ui/        shadcn components
│   ├── hooks/                use-device-id, use-follows, use-push, use-pwa-update
│   └── lib/                  aw-api, constants, push-client, utils
├── routes/                   TanStack Router file-based routes
├── sw.ts                     Custom service worker (precache + push handlers)
├── app.tsx                   RouterProvider
├── app.css                   Tailwind v4 + shadcn theme
└── main.tsx                  Entry point

server/                       Backend source
├── src/
│   ├── features/push/        Push subscription routes + service
│   ├── shared/
│   │   ├── db/               Drizzle client + schema (push_subscriptions, device_follows, seen_polls, politician_mandates)
│   │   ├── jobs/             pg-boss client + poll-checker cron
│   │   └── lib/              env validation, AW API client (server-side), web-push helper
│   ├── app.ts                Hono app assembly
│   └── index.ts              Entry point
├── drizzle.config.ts
├── package.json
└── .env.example              DATABASE_URL, PORT, VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT

Deployment

  • PWA: static files deploy to Uberspace at /var/www/virtual/<user>/html/agw/
  • Backend: deployed as a supervisord service on Uberspace at ~/services/agw-backend/
  • Backend API is reverse-proxied at /agw-api/ via uberspace web backend
  • ./deploy.sh builds and deploys both PWA and backend
  • Apache .htaccess handles SPA routing

Commands — PWA (root)

  • bun dev — start dev server
  • bun run build — production build
  • bun run test — run tests
  • bun run lint — biome check
  • bun run lint:fix — biome auto-fix

Commands — Backend (server/)

  • bun dev — start with file watching
  • bun start — start with Node + tsx (production)
  • bun run db:generate — generate Drizzle migrations
  • bun run db:migrate — run Drizzle migrations
  • bun run test — run tests
  • bun run lint — biome check