84 lines
3.1 KiB
Markdown
84 lines
3.1 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
bun install
|
|
bun run dev
|
|
```
|
|
|
|
The development server runs on port `4000`.
|
|
|
|
Useful commands:
|
|
|
|
```bash
|
|
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 connection
|
|
- `LEADERBOARD_DATABASE_URL` — optional read-only leaderboard database
|
|
- `REDIS_URL` — Redis connection for counters and SSE
|
|
- `NEXTAUTH_URL`, `NEXTAUTH_SECRET` — authentication configuration
|
|
- `DISCORD_CLIENT_ID`, `DISCORD_CLIENT_SECRET` — Discord OAuth
|
|
- `DISCORD_BOT_TOKEN`, `DISCORD_GUILD_ID` — Discord role and profile lookups
|
|
- `ADMIN_DISCORD_IDS` — comma-separated Discord IDs allowed into admin tools
|
|
- `BASE_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:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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`; configure `VIDEO_UPLOAD_DIR` only if the mounted path differs.
|
|
- Rotate credentials if an environment file, build cache, logs, or deployment host may have been exposed.
|