Skip to content

Repository files navigation

MidNight Network

A ranking aggregation and leaderboard system for a daily scheduled post-timing competition game on Misskey

日本語版 README はこちら

Overview

MidNight Network is a comprehensive web application for a game where participants join by posting notes on Misskey at a scheduled daily time. When a user posts a specific string, the system aggregates the post timestamps to rank and visualize results.

Key Features

  • 7-Tier (13 with intermediate) Ranking System — Point-based progression from unranked to the highest tier
  • Automated Match Processing — Daily results aggregated from Misskey timeline via cron jobs
  • Multiple Leaderboards — Rank points, win rate, average time, and match time
  • User Profiles & Analytics — Detailed statistics with charts (earned points, heatmaps, radar, post time trends)
  • Streak Tracking — Consecutive participation, within-zone, absence, and flying streaks with bonus points
  • Border Protection — Demotion prevention system for players near rank boundaries
  • Push Notifications — Match results delivered via Web Push API
  • Privacy Controls — Granular visibility settings for leaderboards and profiles

Tech Stack

Layer Technologies
Frontend SvelteKit (Svelte 5), Vite, TanStack Query, TanStack Table, ECharts, Motion
Backend Cloudflare Workers, Elysia, oRPC
Auth Better Auth + MiAuth (Misskey)
Database Cloudflare D1 (SQLite) + Prisma ORM
Shared oRPC contracts, Zod schema validation
Rank Engine Custom TypeScript calculation module
Code Quality Biome (lint + format), Lefthook (git hooks)

Project Structure

This is a pnpm workspace monorepo:

packages/
├── backend/     Cloudflare Workers API server (Elysia + Prisma + D1)
├── frontend/    SvelteKit web application (static adapter)
├── shared/      oRPC contracts & shared types
└── rank-calc/   Ranking calculation engine

Prerequisites

  • Node.js: 24^
  • pnpm: 10^
  • Cloudflare: Account (for D1, KV, R2, Workers, Queues)
  • Misskey: Instance access and API token

Getting Started

1. Clone the repository

git clone https://github.com/Secineralyr/midnight-network.git
cd midnight-network

2. Install dependencies

pnpm install --frozen-lockfile

3. Configure environment variables

Copy the backend template and fill in the required values:

cp packages/backend/.dev.vars.template packages/backend/.dev.vars
Variable Description
MK_HOST Misskey instance hostname
API_TOKEN Misskey API token
WEB_HOST Frontend hostname
BACKEND_HOST Backend hostname
BOT_USER_NAME Bot user name on Misskey
DISABLE_USER_NAME User IDs to exclude (JSON array string[])
ADMIN_USER_NAME Admin user name
WEBHOOK_SECRET Webhook secret key
VAPID_PRIVATE_KEY VAPID private key for push notifications
BETTER_AUTH_SECRET Secret key for auth session encryption (32+ chars)

Frontend — Copy the template and configure:

cp packages/frontend/template.env packages/frontend/.env
Variable Description
VITE_API_ROOT Backend API URL (empty for same-origin)
VITE_MOCK_AUTH Enable mock auth for development
VITE_TARGET_HOUR Match target hour in UTC (default: 15)
VITE_TARGET_MINUTES Match target minutes in UTC (default: 0)
VITE_VAPID_PUBLIC_KEY VAPID public key for push notifications

4. Local database migration

This step is required even if you are not developing, as it generates the Prisma types.

pnpm --filter @midnight-network/backend migrate:local

5. Start development servers (for development)

# Frontend (port 5173)
pnpm front:dev

# Backend (port 8787)
pnpm back:dev

The frontend dev server automatically proxies /api requests to the backend.

6. Build (for deployment)

pnpm -r build

7. Backend wrangler.toml configuration

The following items need to be defined in wrangler. It is recommended to split environments for the modified items.

The following items are primarily required for deployment.

  • routes: The backend allows api and webhook paths for the host
  • kv_namespaces: Replace id with the ID generated by pnpm wrangler kv namespace create <name> (note that two are required: SESSION and CACHE!)
  • r2_buckets: Replace bucket_name with the bucket name generated by pnpm wrangler r2 bucket create <bucket_name>
  • queues (producers and consumers): Replace queue with the name generated by pnpm wrangler queues create <name> (note that producers and consumers must use the same queue!)
  • d1_databases: Replace database_name and database_id with those generated by pnpm wrangler d1 create <name>

Additionally, edit the following items as needed:

Variable Description
ENVIRONMENT Current environment; do not set to production outside of the production environment
GAME_JOIN_POST_TEXT_REGEX Regex pattern for matching note text to aggregate
TARGET_MATCH_HOUR Target aggregation hour in UTC
TARGET_MATCH_MINUTES Target aggregation minutes in UTC
POST_MATCH_RESULT_TITLE Title used when posting aggregation results as a note
POST_MATCH_RESULT_URL Frontend URL included in the result note
POST_MATCH_RESULT_TEMPLATE Result note text template (use curly braces for format placeholders: {title}: title / {ranks}: ranking (top 10) / {valid}: valid record count / {flying}: flying record count / {url}: URL)
DISABLE_POST_MATCH_RESULT Disable posting result notes after aggregation
POST_MATCH_REMIND_TEXT Reminder note text posted before the match
DISABLE_WEBHOOK_BEFORE_TARGET_MATCH How long before the aggregation time to ignore webhook responses (ms)
DISABLE_WEBHOOK_AFTER_TARGET_MATCH How long after the aggregation time to re-enable webhook responses (ms)
VAPID_PUBLIC_KEY VAPID public key for push notifications
DB_QUERY_LOGGING Log the executed query (for debug)

There are also cron execution settings. These exist because triggers.cron alone cannot control individual processes, so these definitions are used for that control. Therefore, you must assign the cron trigger string you want to execute to the corresponding process.

Variable Description
CRON_DAILY Aggregation process
CRON_DAILY_REMIND Reminder post process

8. Frontend wrangler.toml configuration

When deploying the frontend with Cloudflare Workers, the following items need to be defined in wrangler. It is recommended to split environments for the modified items.

  • routes: Allow any path for the host

Dev Container (VS Code)

A Dev Container configuration is included for VS Code:

  1. Install the Dev Containers extension
  2. Open the project and select "Reopen in Container"
  3. Dependencies are installed automatically on first launch
  4. Configure packages/backend/.dev.vars as described above
  5. Start development with pnpm front:dev / pnpm back:dev

Forwarded Ports:

Port Service
5173 Frontend (SvelteKit dev server)
8787 Backend (Wrangler dev server)

Available Scripts

Root (all packages)

Command Description
pnpm install Install all dependencies
pnpm check Run Biome lint + format check
pnpm check:write Auto-fix lint and format issues
pnpm typecheck Type-check all packages
pnpm build Build all packages
pnpm test Run all tests
pnpm front:dev Start frontend dev server
pnpm back:dev Start backend dev server

Backend

Command Description
pnpm --filter @midnight-network/backend dev Start Wrangler dev server
pnpm --filter @midnight-network/backend build Build (generate types + compile)
pnpm --filter @midnight-network/backend migrate:local Apply D1 migrations locally
pnpm --filter @midnight-network/backend migrate:remote Apply D1 migrations to production
pnpm --filter @midnight-network/backend deploy Deploy to Cloudflare Workers
pnpm --filter @midnight-network/backend auth:gen Update Prisma definitions when Better Auth definitions change
pnpm --filter @midnight-network/backend prisma:format Format Prisma files
pnpm --filter @midnight-network/backend prisma:mig Write diff from Prisma definitions to migration file (may be inaccurate; manually defining is generally recommended)

Frontend

Command Description
pnpm --filter @midnight-network/frontend dev Start Vite dev server
pnpm --filter @midnight-network/frontend build Build static site
pnpm --filter @midnight-network/frontend test Run Playwright E2E tests

Deployment

CI/CD (GitHub Actions)

Automated CI and deployment workflows are configured in .github/workflows/.

CI

Runs on pull requests:

  • Lint & format check (Biome)
  • Local D1 migration (for Prisma type generation)
  • Build all packages
  • Typecheck
  • Tests

Deploy

Runs automatically on push:

  • Builds shared packages, backend, and frontend
  • Replaces wrangler.toml with the production/staging version stored in GitHub Secrets
  • Deploys backend and frontend to Cloudflare Workers via wrangler deploy
  • Runs remote D1 migrations after backend deployment
  • Frontend VITE_* environment variables are injected at build time

Required GitHub Secrets

Secret Description
CLOUDFLARE_API_TOKEN Wrangler API token (Workers edit permission)
CLOUDFLARE_ACCOUNT_ID Cloudflare account ID
BACKEND_WRANGLER_TOML Full contents of the backend wrangler.toml for this environment
FRONTEND_WRANGLER_TOML Full contents of the frontend wrangler.toml for this environment
VITE_API_ROOT Frontend API root (empty for same-origin)
VAPID_PUBLIC_KEY VAPID public key for push notifications
D1_DB_NAME D1 database name

Note: Worker Secrets (e.g. API_TOKEN, WEBHOOK_SECRET, BETTER_AUTH_SECRET) must be configured directly on Cloudflare (via Dashboard or wrangler secret put). They are not managed by the deployment workflow.

Manual Deployment

Backend

Deploy as a Cloudflare Worker

pnpm --filter @midnight-network/backend deploy
# Using environment-based deployment is recommended
# pnpm --filter @midnight-network/backend deploy --env <env>

Required Cloudflare resources:

  • D1 Database: Main data store
  • KV Namespaces: SESSION (auth sessions), CACHE (general cache)
  • R2 Bucket: Rank status snapshots
  • Queue: Rerun job processing

Configure resource bindings in packages/backend/wrangler.toml.

Frontend

The frontend is built as a static site using @sveltejs/adapter-static:

pnpm --filter @midnight-network/frontend build

Output is generated in packages/frontend/dist/ and can be deployed to any static hosting service (Cloudflare Workers, Vercel, Netlify, etc.). Deploying to Cloudflare Workers is generally recommended.

pnpm --filter @midnight-network/frontend deploy
# Using environment-based deployment is recommended
# pnpm --filter @midnight-network/frontend deploy --env <env>

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

The source code of this project is licensed under AGPL-3.0-or-later. See LICENSE for details.

However, images and assets (excluding manifest files) in the packages/frontend/static/ directory are not open source and are provided under a proprietary license. See packages/frontend/static/LICENSE for details.

If you fork this project, you must replace the proprietary assets with your own.

About

A ranking aggregation and leaderboard system

Resources

Code of conduct

Contributing

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages