BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
nextjs application that serves as a proxy api Helldivers 1 alongside a frontend to process and view the data.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗This is an application that consumes the official Helldivers 1 API, caches and rebroadcasts it to avoid high load on official servers, and stores historic data that the official API discards. It also offers account management and API keys for third parties to access the data to build their own apps.
The frontend is a live campaign dashboard with an interactive galaxy
map, a scrollytelling event log, and a real-time notification system.
All pages receive live campaign updates via client-side polling
(useLiveData hook, setInterval + fetch, 10s interval, with an
immediate refetch on visibilitychange when the tab comes back into
focus). The app runs as an installable Progressive Web App with a
Serwist-backed service worker, supports offline mode via a cached
last-poll payload in localStorage, and delivers browser and push
notifications when campaign events transition state.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) on Node.js 26, React 19 |
| Styling | Tailwind CSS v4 (@theme in src/app/layout.css) |
| Database | PostgreSQL via Prisma 7 (@prisma/adapter-pg) |
| Auth | BetterAuth (Discord + GitHub OAuth, optional) |
| Real-time | Client polling + BroadcastChannel leader election |
| Notifications | Sonner toasts + Web Notifications API + web-push |
| PWA | Serwist (@serwist/next) service worker |
| Observability | Sentry SDK wired to a self-hosted GlitchTip (optional) |
| Analytics | Umami v3, self-hosted, cookieless (optional) |
| Testing | Vitest (unit + jsdom) + a Vitest HTTP smoke config |
| Deployment | Docker images published to ghcr.io, deployed on a VPS |
The application is made from 2 large sections:
Detailed docs: /docs/frontend-layout (in-app) — covers the full
state machine, CSS var pipeline, and breakpoint matrix.
computeMapStateAtEvent.useScrollEvent syncs the selected
event card to the viewport's current scroll position; the map
reacts in sync./archives the FAB defaults to pinned so the map is at rest when
the user reaches the event log. A class-layering system (--sticky
for the persistent pinned state, --pinning for the 400ms slide
animation) keeps the entrance animation from re-triggering on
mount.public/scripts/headerGPU.js. The pinned map tracks
the header's offset and mirrors its live background via three CSS
custom properties published on <html> (--header-offset,
--header-bg, --header-glass-filter).useLiveData singleton per tab polls
/api/h1/live every 10 seconds, with BroadcastChannel leader
election so only one tab dispatches Web Notifications per session.src/sw.js + Serwist precaches the app
shell, and the last poll payload is cached in localStorage for
offline fallback.On startup, it runs instrumentation.js (once) which will:
check if openapi spec exists (or generate it in dev mode)
check if database connection exists and is valid
initialize the database:
h1_season, h1_status, h1_statistic, h1_event, h1_event_progress). Past seasons referenced by lagged event slots are skipped per queryUpsertEvent's event.season !== season guard rather than being seeded as empty rows.start a worker thread that will continiously update the database from the official Helldivers API. It simply queries the /api/h1/update endpoint every UPDATE_INTERVAL seconds using the UPDATE_KEY token.
Next.js route handlers under src/app/api/ expose Helldivers data in
several formats. The GET /api/h1/* endpoints are the core public
surface; the rest are internal (auth, healthcheck, analytics/error
tunnels).
GET /api/h1/update
h1_* tables via the shared bucket-upsert pipeline.key query parameter matching the server's
UPDATE_KEY environment variable — this is the same token
the background worker uses.GET /api/h1/rebroadcast
h1_* tables.action: string — one of get_campaign_status,
get_snapshotseason: integer — required when action is get_snapshotGET /api/h1/campaign
season query parameter.GET /api/h1/live
useLiveData client hook. Powers the live
dashboard, event-transition toasts, and push notifications.GET /api/h1/stats (not implemented)
Internal routes not listed above:
GET/POST /api/auth/[...all] — BetterAuth handlers (only when
BETTER_AUTH_SECRET is set; otherwise auth is disabled).GET /api/healthcheck — used by Docker / upstream monitoring.POST /api/notifications/subscribe — push notification
subscription endpoint (only when Web Push keys are configured).POST /api/umami, POST /api/glitchtip — same-origin proxy tunnels
so self-hosted analytics and error reporting aren't blocked by ad
blockers (only when the corresponding env vars are set).BETTER_AUTH_SECRET)All user-facing features below are gated behind BetterAuth. When
BETTER_AUTH_SECRET is not set, the sign-in UI is hidden, /profile
redirects home, and the auth API returns 503 — the public
dashboard, /archives, and the /api/h1/* rebroadcast endpoints
all still work without authentication.
The application uses nextjs running on node@26, prisma and postgres. It is deployed on a VPS in a docker container.
.env.development file based on .example.envnpm installnpm run dev to start the server locallyWhen using the docker container, the database you are connecting to needs to already exist. It will not create it for you.
docker build -f ./Dockerfile.migrate -t ghcr.io/elfensky/helldiversbot-migrate:staging .
docker build -f ./Dockerfile.app -t ghcr.io/elfensky/helldiversbot:staging .
--no-cache --progress=plain for clean rebuildsdocker buildx build --platform linux/amd64 -f ./Dockerfile.app -t ghcr.io/elfensky/helldiversbot:staging . to cross-compile for x86_64docker compose up to run the containers locallydocker push ghcr.io/elfensky/helldiversbot:staging to push the image to ghcr.io:staging image:production image alongside and create a new Release (using Release.md)npx prisma migrate reset
reset all data in db
npx prisma generate
reads your Prisma schema and generates the Prisma Client.
npx prisma migrate dev
npx prisma migrate dev --name init
Purpose: This command generates and applies a new migration based on your Prisma schema changes. It creates migration files that keep a history of changes.
Use Case: Use this when you want to maintain a record of database changes, which is essential for production environments or when working in teams. It allows for version control of your database schema.
Benefits: This command also includes checks for applying migrations in a controlled manner, ensuring data integrity.
npx prisma db push
Purpose: This command is used to push your current Prisma schema to the database directly. It applies any changes you've made to your schema without creating migration files.
Use Case: It’s particularly useful during the development phase when you want to quickly sync your database schema with your Prisma schema without worrying about migration history.
Caution: It can overwrite data if your schema changes affect existing tables or columns, so it’s best for early-stage development or prototyping.
cx scan create --project-name "helldivers.bot" --branch "develop" --scan-types "sast, sca, iac-security" -s . --debug
cx scan create --project-name "helldivers.bot" --branch "develop" --scan-types "container-security" --containers-local-resolution --container-images "ghcr.io/elfensky/helldiversbot:local" -s . --debug
AGPL-3.0-only — relicensed from MIT on 2026-08-12.
This project is served over a network, which is the case AGPL exists for. Plain GPL's copyleft triggers on distribution: anyone who runs a fork as a hosted API never distributes a copy, so they would owe nothing. AGPL §13 closes that — if you run a modified version and let people interact with it over a network, you have to offer them the source.
Everything released up to and including v0.91.0 remains available under MIT; the change binds
what comes after. MIT grants the right to sublicense, so contributions made under it can be
carried forward — thanks to everyone who has contributed.