# 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 ```bash 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: - Public site: http://localhost:3000 - Admin console: http://localhost:3000/admin ## 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) ```bash # 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: ```bash 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 ```bash 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 ```