hermes 6d3cb9d678 chore: add Docker deployment files, README, and Prisma migrations
- Add Dockerfile and docker-compose.yml for VPS/LXC deployment.
- Update README with setup, environment variables, and deployment notes.
- Commit initial Prisma migration for SQLite schema.
- Configure Next.js for standalone output and dev origin allowlist.
2026-06-17 04:34:39 +00:00
2026-06-17 00:26:22 +00:00
2026-06-17 00:26:22 +00:00

BiasNews Aggregator

A full-stack news aggregation website that collects articles, uses AI to classify them by political bias (Left / Center / Right), and presents them in side-by-side columns. Includes a protected admin console for discovering news, managing API keys, and configuring automated searches.

Features

  • Public site

    • Three-column layout: Left, Center, Right
    • Search and filter by bias, topic, date, source
    • Article detail pages with AI summary and bias explanation
    • Mobile-responsive design
  • Admin console

    • Secure credential-based login
    • Discover news on demand using NewsAPI, GNews, or Serper web search
    • AI processing via Kimi (OpenAI-compatible API) for:
      • Summarization
      • Bias classification (LEFT / CENTER / RIGHT)
      • Political tags (liberal / moderate / conservative)
      • Importance ranking and credibility scoring
      • Topic extraction
    • Manage published/draft/archived articles
    • Encrypted API key storage with easy rotation
    • Automated search rules with cron scheduling
    • Source credibility and active/inactive toggles

Tech stack

  • Next.js 16 (App Router, TypeScript)
  • Tailwind CSS 4
  • Prisma ORM + SQLite
  • jose for session cookies
  • bcryptjs for password hashing
  • node-cron for scheduled rules
  • openai SDK for Kimi-compatible APIs

Local development

npm install

# Copy environment file and fill in secrets + API keys
cp .env.example .env.local

# Generate admin password hash
npx tsx scripts/generate-admin-hash.ts your-password

# Update ADMIN_PASSWORD_HASH in .env.local

# Apply database migrations and seed default sources
npx prisma migrate dev --name init
npx prisma db seed

# Run dev server
npm run dev

Open:

API keys

Add keys in Admin > API Keys:

Provider Purpose How to get
KIMI AI summarization / bias / ranking https://platform.moonshot.cn
NEWSAPI News articles https://newsapi.org
GNEWS News articles https://gnews.io
WEBSEARCH Web search via Serper https://serper.dev

API keys are encrypted at rest with API_KEY_ENCRYPTION_SECRET.

Deployment (Docker)

# Build image
docker build -t biasnews .

# Run container
docker run -d \
  -p 3000:3000 \
  -e DATABASE_URL="file:./data/dev.db" \
  -e ADMIN_USERNAME=admin \
  -e ADMIN_PASSWORD_HASH="$2b$10$..." \
  -e NEXTAUTH_SECRET="..." \
  -e API_KEY_ENCRYPTION_SECRET="..." \
  -e KIMI_API_URL="https://api.moonshot.cn/v1" \
  -e KIMI_MODEL="moonshot-v1-8k" \
  -v $(pwd)/data:/app/data \
  biasnews

Or use Docker Compose:

docker compose up -d

Automated searches

Create a rule in Admin > Auto Rules. The scheduler loads active rules when the app starts and reschedules whenever rules change. Each rule specifies:

  • Search query
  • Sources to query
  • Cron schedule
  • Max results
  • Minimum rank score threshold
  • Whether to auto-publish results

Architecture notes

  • The admin console is part of the same Next.js app but protected by authentication. It can be accessed from a separate machine (e.g., local laptop) by browsing to the public URL and logging in.
  • If you want a fully separate admin deployment later, the admin API routes are isolated under /api/admin/* and admin pages under /admin/*.
  • SQLite is used for single-node simplicity. For production scale, switch to PostgreSQL by changing the Prisma datasource URL.

Scripts

npm run dev          # Start dev server
npm run build        # Production build
npm run start        # Start production server
npm run db:migrate   # Run Prisma migrations
npm run db:seed      # Seed default sources and admin user
npm run db:studio    # Open Prisma Studio
Description
News aggregator with AI-powered bias classification
Readme 168 KiB
Languages
TypeScript 97.7%
CSS 1.4%
Dockerfile 0.6%
JavaScript 0.3%