3.1 KiB
Erika
Erika is a Next.js application for a creator landing page, Discord-authenticated forms, admin form management, submission results, Discord notifications, and XP/voice leaderboards.
Requirements
- Bun 1.3+
- PostgreSQL
- Redis for visitor counts and server-sent events
- Discord OAuth and bot credentials for authentication and role-based access
Development
bun install
bun run dev
The development server runs on port 4000.
Useful commands:
bun run lint # ESLint
bunx tsc --noEmit # Type checking
bun test # Unit and domain tests
bun run db:generate # Generate a Drizzle migration
bun run db:migrate # Apply migrations
Environment
Create .env.local for local development. The application uses these groups of variables:
DATABASE_URL— primary PostgreSQL connectionLEADERBOARD_DATABASE_URL— optional read-only leaderboard databaseREDIS_URL— Redis connection for counters and SSENEXTAUTH_URL,NEXTAUTH_SECRET— authentication configurationDISCORD_CLIENT_ID,DISCORD_CLIENT_SECRET— Discord OAuthDISCORD_BOT_TOKEN,DISCORD_GUILD_ID— Discord role and profile lookupsADMIN_DISCORD_IDS— comma-separated Discord IDs allowed into admin toolsBASE_URL— canonical public URL used in links and OAuth callbacks- platform credentials used by follower-count integrations
Never commit .env or .env.local, and never expose credentials through NEXT_PUBLIC_ variables. Before deployment, run:
bun run secrets:scan
Main areas
/— public profile and links/form— public form listing and submission/admin— protected administration dashboard/leaderboard/xp— XP leaderboard/leaderboard/vc— voice activity leaderboard/sse/[topic]— authenticated realtime updates/api/upload— authenticated image uploads stored in PostgreSQL/admin/upload— admin video publishing workspace for YouTube and TikTok
Forms use server actions for authorization, persistence, validation, Discord webhooks, and cache invalidation. Public form drafts are stored locally in the browser.
Docker
bun run up
bun run logs
bun run down
The application listens on port 3000 inside the container. nginx shares the application network namespace and provides the public port configured in docker-compose.yml, including SSE proxy settings.
The production image is built in separate dependency, build, and runner stages. Runtime environment variables are injected by Compose rather than copied into the image.
Security notes
- Admin server actions require the authenticated Discord ID to be in
ADMIN_DISCORD_IDS. - Form access checks allowed and denied Discord roles.
- Uploaded image contents are checked against their declared image type before storage.
- TikTok OAuth is a private setup utility and requires an admin session plus verified OAuth state.
- Video files are stored under
/nfs/erika; configureVIDEO_UPLOAD_DIRonly if the mounted path differs. - Rotate credentials if an environment file, build cache, logs, or deployment host may have been exposed.