Skip to content

Shineii86/AniNewsAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

138 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Note

The Old Deployment URL https://aninewsapi.vercel.app Is No Longer Accessible. Use The Current URL: https://aninews.vercel.app

Stars Forks Issues Pull Requests Last Commit License

Node.js Express Vercel License Version Sources Endpoints

A serverless API aggregating anime news from 7 sources in real-time.
Smart caching, keyword search, RSS feeds, date filtering, cursor pagination, and source health monitoring.
Built for speed, reliability, and the anime community.

Table of Contents β€’ Features β€’ API Docs β€’ Quick Start β€’ Deployment β€’ Contributing


πŸ“– Table of Contents


🌸 Overview

AniNewsAPI is a serverless anime news aggregation API that scrapes, deduplicates, and serves articles from 7 major anime news sources β€” all through a clean REST API with zero database setup.

πŸ’‘ No database, no auth for reads, no complex setup. Just deploy to Vercel and you have a production API.

Why AniNewsAPI?

  • πŸ“° 7 Sources β€” ANN, MAL, Crunchyroll, Anime Corner, Otaku USA, Anime Herald, Comic Book
  • ⚑ Smart Caching β€” Two-tier cache (memory + disk) with 10-minute TTL, survives serverless cold starts
  • πŸ” Full-Text Search β€” Relevance-scored search across titles, excerpts, sources, and tags
  • πŸ—žοΈ RSS Feeds β€” Standards-compliant RSS 2.0 for any feed reader
  • πŸ“„ Full Article Extraction β€” Get readable article content by slug
  • 🏷️ Tag Filtering β€” Browse articles by tag with count aggregation
  • πŸ“Š Source Health β€” Real-time per-source health checks, latency, and article counts
  • πŸ”’ CORS Enabled β€” Works from any frontend, no proxy needed
  • πŸš€ Zero-Config Deploy β€” One click to Vercel, or run standalone with Express

How It Works

flowchart TD
    A["🌐 Client Request<br/>(Browser / App / curl)"] --> B["πŸ›‘οΈ Vercel Edge / Express Server<br/>CORS Β· Security Headers Β· Rate Limiting"]
    B --> C{"πŸ’Ύ Cache Check<br/>(node-cache + disk)"}
    C -- HIT --> D["⚑ Return Cached Response<br/>~200ms"]
    C -- MISS --> E["πŸ“° 7 Concurrent Fetchers"]

    E --> E1["ANN"]
    E --> E2["MAL"]
    E --> E3["Crunchyroll"]
    E --> E4["Anime Corner"]
    E --> E5["Otaku USA"]
    E --> E6["Anime Herald"]
    E --> E7["Comic Book"]

    E1 & E2 & E3 & E4 & E5 & E6 & E7 --> F["πŸ”„ RSS / Google News RSS / Web Scraping<br/>3 retries Β· 15s timeout Β· exponential backoff"]
    F --> G["🧹 Deduplicate · Enrich · Cache"]
    G --> H["πŸ“€ Respond<br/>JSON Β· RSS 2.0 XML Β· SSE"]

    style A fill:#1e1e2e,stroke:#a78bfa,color:#f1f5f9
    style B fill:#1e1e2e,stroke:#6366f1,color:#f1f5f9
    style C fill:#1e1e2e,stroke:#f43f8e,color:#f1f5f9
    style D fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
    style E fill:#1e1e2e,stroke:#a855f7,color:#f1f5f9
    style F fill:#1e1e2e,stroke:#eab308,color:#f1f5f9
    style G fill:#1e1e2e,stroke:#06b6d4,color:#f1f5f9
    style H fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
Loading

✨ Features

⚑ Core

  • Real-time scraping from 7 anime news sources

  • Smart caching with 10-minute TTL + disk backup

  • Concurrent fetching β€” all sources hit simultaneously

  • Retry logic β€” 3 attempts per source with exponential backoff

  • Graceful degradation β€” if a source fails, others continue

  • Google News RSS proxy for Cloudflare-protected sources

πŸ” Data

  • Keyword search with relevance scoring (/api/search)

  • Date range filtering β€” ?from=YYYY-MM-DD&to=YYYY-MM-DD

  • Cursor pagination β€” opaque nextCursor for efficient paging

  • RSS 2.0 feed for readers & integrations (/api/rss)

  • Full article extraction by slug (/api/news/:slug)

  • Tag filtering with article counts (/api/news/tags)

πŸ›‘οΈ Reliability

  • RSS fallback when web scraping is blocked

  • Cross-source deduplication by normalized title

  • Timeout protection β€” 15s per source, never hangs

  • CORS enabled β€” works from any frontend

  • Security headers β€” X-Frame-Options, X-Content-Type-Options

  • Rate limiting β€” 100 req/min per IP with headers

πŸ“Š Monitoring

  • Source health β€” per-source status, article count, latency (/api/sources)

  • Cache statistics β€” hit/miss metrics (/api/stats)

  • Health check β€” uptime, version, node info (/api/health)

  • Cache clear auth β€” API key protected (CACHE_CLEAR_KEY env)

  • OpenAPI 3.0.3 spec β€” machine-readable API definition

🌟 Feature Highlights

Feature Description Status
πŸ“° 7 News Sources ANN, MAL, Crunchyroll, Anime Corner, Otaku USA, Anime Herald, Comic Book βœ…
⚑ Smart Caching Two-tier (memory + disk) with 10-min TTL βœ…
πŸ” Full-Text Search Relevance scoring β€” title (10pts) vs excerpt (3pts) βœ…
πŸ“„ Article Extraction Full content parsing from original URLs βœ…
πŸ—žοΈ RSS 2.0 Feed Standards-compliant XML with media:thumbnail βœ…
πŸ“… Date Filtering ?from=YYYY-MM-DD&to=YYYY-MM-DD on news & search βœ…
πŸ”„ Cursor Pagination Opaque base64url cursors for stable paging βœ…
🏷️ Tag System Tag listing with counts, filter by tag βœ…
πŸ“Š Source Health Real-time fetch status, latency, article counts βœ…
πŸ”’ Cache Auth API key protection for cache clear endpoint βœ…
πŸ“‘ SSE Stream Server-Sent Events for real-time push βœ…
πŸ“‹ OpenAPI Spec Machine-readable 3.0.3 specification βœ…
πŸš€ One-Click Deploy Vercel button deployment βœ…
πŸ—οΈ Express Mode Standalone server with npm start βœ…

πŸ—žοΈ News Sources

Source Key Method Articles Website
Anime News Network ann Google News RSS ~15 animenewsnetwork.com
Anime Corner animecorner RSS Feed ~12 animecorner.me
MyAnimeList myanimelist Direct Scraping ~15 myanimelist.net
Otaku USA Magazine otakuusa Google News RSS ~12 otakuusamagazine.com
Crunchyroll crunchyroll Google News RSS ~15 crunchyroll.com/news
Anime Herald animeherald RSS Feed ~10 animeherald.com
Comic Book comicbook Direct Scraping ~10 comicbook.com/anime

Total: 60+ unique articles after cross-source deduplication

Adding a New Source

  1. Create utils/fetchNewSource.js β€” export async function returning [{ title, slug, source, excerpt, date, image, link, tags }]
  2. Register in utils/sources.js β†’ SOURCES object
  3. Test with npm test, submit a PR

πŸ› οΈ Tech Stack

Technology Purpose Version Documentation
🟒 Node.js JavaScript runtime >= 20 Docs
⚑ Express HTTP server framework 5.1 Docs
β–² Vercel Functions Serverless deployment β€” Docs
πŸ” Cheerio HTML parsing & scraping 1.0 Docs
🌐 Axios HTTP client 1.7 Docs
πŸ“‘ rss-parser RSS/Atom feed parsing 3.13 Docs
πŸ’Ύ node-cache In-memory caching 5.1 Docs
πŸ”€ he HTML entity decoding 1.2 Docs

πŸ“¦ Key Dependencies

{
  "express": "^5.1.0",        // HTTP server
  "axios": "^1.7.2",          // HTTP client for scraping
  "cheerio": "^1.0.0-rc.12",  // HTML parsing
  "rss-parser": "^3.13.0",    // RSS feed parsing
  "node-cache": "^5.1.2",     // In-memory cache
  "he": "^1.2.0"              // HTML entity decoding
}

πŸ—οΈ Architecture

Request Flow

Stage Component Description
1 Client Browser, app, or curl sends request
2 Vercel Edge / Express Routes request, applies CORS + security headers + rate limit
3 Cache Check node-cache with 10-min TTL β€” hit = instant response
4 Fetch Sources 7 concurrent scrapers (3 retries each, 15s timeout)
5 Deduplicate Cross-source dedup by normalized title
6 Enrich & Respond Filter, paginate, sort, format β†’ JSON/RSS/SSE

Caching Architecture

flowchart TD
    A["πŸ“₯ Request"] --> B{"🧠 Memory Cache<br/>(node-cache)"}
    B -- HIT --> C["⚑ Return Cached<br/>~200ms"]
    B -- MISS --> D{"πŸ’Ύ Disk Cache<br/>(JSON files)"}
    D -- HIT --> E["πŸ”„ Promote to Memory<br/>Return"]
    D -- MISS --> F["πŸ“° Fetch from 7 Sources<br/>(concurrent)"]
    F --> G["πŸ’Ύ Cache Result<br/>(memory + disk)"]
    G --> H["πŸ“€ Return Fresh"]

    style A fill:#1e1e2e,stroke:#a78bfa,color:#f1f5f9
    style B fill:#1e1e2e,stroke:#f43f8e,color:#f1f5f9
    style C fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
    style D fill:#1e1e2e,stroke:#6366f1,color:#f1f5f9
    style E fill:#1e1e2e,stroke:#06b6d4,color:#f1f5f9
    style F fill:#1e1e2e,stroke:#eab308,color:#f1f5f9
    style G fill:#1e1e2e,stroke:#a855f7,color:#f1f5f9
    style H fill:#1e1e2e,stroke:#22c55e,color:#f1f5f9
Loading

πŸ’‘ Serverless functions have read-only filesystems except /tmp. The disk cache writes to /tmp on Vercel, surviving across warm invocations.

Source Fetch Strategy

Source Primary Fallback Notes
ANN Google News RSS Direct scraping Cloudflare blocks direct access
Anime Corner RSS Feed Direct scraping RSS has real descriptions
MyAnimeList Direct scraping Page 2 scraping Custom date format parser
Otaku USA Google News RSS Direct scraping 520 errors on direct access
Crunchyroll Google News RSS Direct scraping Blocks direct scraping
Anime Herald RSS Feed Direct scraping RSS has real descriptions
Comic Book Direct scraping RSS Feed Uses subheadline selector

πŸ“ Project Structure

AniNewsAPI/
β”œβ”€β”€ πŸ“‚ api/                            # 🌐 Vercel serverless functions
β”‚   β”œβ”€β”€ πŸ“‚ cache/
β”‚   β”‚   └── πŸ“„ clear.js                #    πŸ” Cache management (API key protected)
β”‚   β”œβ”€β”€ πŸ“„ health.js                   #    πŸ’š Health check endpoint
β”‚   β”œβ”€β”€ πŸ“„ news.js                     #    πŸ“° Main news endpoint (pagination, filtering)
β”‚   β”œβ”€β”€ πŸ“‚ news/
β”‚   β”‚   β”œβ”€β”€ πŸ“„ [slug].js               #    πŸ“„ Full article by slug
β”‚   β”‚   └── πŸ“„ tags.js                 #    🏷️ Tag listing & filtering
β”‚   β”œβ”€β”€ πŸ“„ openapi.js                  #    πŸ“‹ OpenAPI 3.0.3 specification
β”‚   β”œβ”€β”€ πŸ“„ rss.js                      #    πŸ—žοΈ RSS 2.0 XML feed
β”‚   β”œβ”€β”€ πŸ“„ search.js                   #    πŸ” Full-text search with scoring
β”‚   β”œβ”€β”€ πŸ“„ sources.js                  #    πŸ“Š Per-source health & stats
β”‚   β”œβ”€β”€ πŸ“„ stats.js                    #    πŸ“ˆ Cache hit/miss statistics
β”‚   └── πŸ“„ stream.js                   #    πŸ“‘ Server-Sent Events
β”‚
β”œβ”€β”€ πŸ“‚ public/
β”‚   β”œβ”€β”€ πŸ“„ index.html                  #    🏠 Landing page
β”‚   β”œβ”€β”€ πŸ“„ manifest.json               #    πŸ“± PWA manifest
β”‚   β”œβ”€β”€ πŸ“„ og-image.png                #    πŸ–ΌοΈ Open Graph image
β”‚   └── πŸ“„ og-image.svg                #    πŸ–ΌοΈ Open Graph vector
β”‚
β”œβ”€β”€ πŸ“‚ utils/                          # βš™οΈ Core logic
β”‚   β”œβ”€β”€ πŸ“„ cacheHandler.js             #    πŸ’Ύ Two-tier cache (memory + disk)
β”‚   β”œβ”€β”€ πŸ“„ constants.js                #    πŸ“Œ Shared config & defaults
β”‚   β”œβ”€β”€ πŸ“„ contentParser.js            #    πŸ“„ Full-article content extraction
β”‚   β”œβ”€β”€ πŸ“„ dateParser.js               #    πŸ“… Multi-format date parsing
β”‚   β”œβ”€β”€ πŸ“„ fetchANN.js                 #    πŸ“° Anime News Network fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchAnimeCorner.js         #    πŸ“° Anime Corner fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchAnimeHerald.js         #    πŸ“° Anime Herald fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchComicBook.js           #    πŸ“° Comic Book fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchCrunchyroll.js         #    πŸ“° Crunchyroll fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchMyAnimeList.js         #    πŸ“° MyAnimeList fetcher
β”‚   β”œβ”€β”€ πŸ“„ fetchOtakuNews.js           #    πŸ“° Otaku USA fetcher
β”‚   β”œβ”€β”€ πŸ“„ generateSlug.js             #    πŸ”— URL-safe slug generator
β”‚   └── πŸ“„ sources.js                  #    πŸ“‹ Centralized source registry
β”‚
β”œβ”€β”€ πŸ“‚ data/                           # πŸ’Ύ Disk cache files (auto-generated)
β”‚
β”œβ”€β”€ πŸ“„ server.js                       # πŸš€ Express server entry point
β”œβ”€β”€ πŸ“„ index.js                        # β–² Vercel serverless entry point
β”œβ”€β”€ πŸ“„ test.js                         # πŸ§ͺ Integration test suite
β”œβ”€β”€ πŸ“„ vercel.json                     # β–² Vercel routing & headers config
β”œβ”€β”€ πŸ“„ package.json                    # πŸ“¦ Dependencies & scripts
β”œβ”€β”€ πŸ“„ CHANGELOG.md                    # πŸ“ Version history
β”œβ”€β”€ πŸ“„ CONTRIBUTING.md                 # 🀝 Contribution guidelines
β”œβ”€β”€ πŸ“„ LICENSE                         # πŸ“œ MIT License
└── πŸ“„ README.md                       # πŸ“– This file

πŸš€ Quick Start

Prerequisites

Requirement Minimum Recommended
πŸ“¦ Node.js 20.x 20.x LTS
πŸ“¦ npm 9.0+ 10.x
πŸ’» OS Windows, macOS, Linux Any

πŸ”§ Installation

# 1️⃣ Clone the repository
git clone https://github.com/Shineii86/AniNewsAPI.git
cd AniNewsAPI

# 2️⃣ Install dependencies
npm install

# 3️⃣ Start development server
npm run dev

🌐 Open http://localhost:3000 in your browser.

πŸ—οΈ Build for Production

# Start production server
npm start

# Run tests
npm test

🐳 Alternative Package Managers

# Using yarn
yarn install
yarn dev

# Using pnpm
pnpm install
pnpm dev

# Using bun
bun install
bun dev

βš™οΈ Configuration

Environment Variables

Variable Default Description
CACHE_TTL 600 Cache duration in seconds (10 minutes)
PORT 3000 Server port (Express mode only)
CACHE_CLEAR_KEY β€” API key for POST /api/cache/clear (optional)
API_URL http://localhost:3000 Base URL for test suite

Vercel Configuration

The vercel.json file handles:

  • Rewrites β€” Maps clean URLs to serverless functions
  • Headers β€” CORS, caching, and rate limit headers
  • Environment β€” Sets CACHE_TTL for production

πŸ“‘ API Endpoints

GET /api/news

Latest anime news from all or specific sources.

Param Type Default Description
limit 1-100 20 Max articles per page
offset >=0 0 Pagination offset
cursor string β€” Pagination cursor (from meta.nextCursor)
sort latest|oldest latest Sort order
source string all Filter by source key
from YYYY-MM-DD β€” Start date filter
to YYYY-MM-DD β€” End date filter
refresh boolean false Bypass cache
# Basic usage
curl "https://aninews.vercel.app/api/news?limit=10"

# Filter by source with pagination
curl "https://aninews.vercel.app/api/news?source=crunchyroll&limit=10&offset=10"

# Date range filtering
curl "https://aninews.vercel.app/api/news?from=2026-05-20&to=2026-05-27"

# Cursor-based pagination (use nextCursor from previous response)
curl "https://aninews.vercel.app/api/news?limit=20&cursor=eyJvZmZzZXQiOjIwfQ"
πŸ“„ Example Response
{
  "success": true,
  "data": [
    {
      "title": "Demon Slayer Season 4 Announced",
      "slug": "ann-demon-slayer-season-4-announced",
      "source": "Anime News Network",
      "excerpt": "The official website confirmed...",
      "date": "2026-05-27T10:30:00.000Z",
      "image": "https://example.com/image.jpg",
      "link": "https://www.animenewsnetwork.com/news/...",
      "tags": ["news", "anime"]
    }
  ],
  "meta": {
    "total": 62,
    "returned": 10,
    "offset": 0,
    "limit": 10,
    "hasMore": true,
    "nextCursor": "eyJvZmZzZXQiOjEwfQ",
    "source": "all",
    "sort": "latest",
    "from": "2026-05-20",
    "to": "2026-05-27",
    "responseTime": "234ms",
    "timestamp": "2026-05-27T12:00:00.000Z"
  }
}

GET /api/search

Full-text search with relevance scoring. Title matches rank higher than excerpt matches.

Param Required Description
q Yes Search query (min 2 chars)
source No Filter by source key
limit No Max results (1-100)
offset No Pagination offset
from No Start date (YYYY-MM-DD)
to No End date (YYYY-MM-DD)

Scoring Algorithm:

  • Title match: +10 points per search term
  • Excerpt match: +3 points per search term
  • Tiebreaker: newest date first
curl "https://aninews.vercel.app/api/search?q=demon+slayer"
curl "https://aninews.vercel.app/api/search?q=manga&source=ann&limit=5"
curl "https://aninews.vercel.app/api/search?q=crunchyroll&from=2026-05-20&to=2026-05-27"

GET /api/news/tags

List available tags with article counts, or filter articles by tag.

# List all tags with counts
curl "https://aninews.vercel.app/api/news/tags"

# Filter articles by tag
curl "https://aninews.vercel.app/api/news/tags?tag=official"

# Filter by tag and source
curl "https://aninews.vercel.app/api/news/tags?tag=news&source=ann"
πŸ“„ Example Response (tag listing)
{
  "success": true,
  "data": {
    "tags": [
      { "name": "anime", "count": 45 },
      { "name": "news", "count": 38 },
      { "name": "official", "count": 22 }
    ],
    "totalTags": 15,
    "totalArticles": 62
  },
  "meta": { "timestamp": "2026-05-27T12:00:00.000Z" }
}

GET /api/news/:slug

Full article content extraction from the original URL.

curl "https://aninews.vercel.app/api/news/ann-demon-slayer-season-4-announced"
πŸ“„ Example Response
{
  "success": true,
  "data": {
    "title": "Demon Slayer Season 4 Announced",
    "slug": "ann-demon-slayer-season-4-announced",
    "source": "Anime News Network",
    "excerpt": "The official website confirmed...",
    "date": "2026-05-27T10:30:00.000Z",
    "link": "https://www.animenewsnetwork.com/news/...",
    "content": "<p>Full article HTML content...</p>",
    "author": "John Doe",
    "publishDate": "2026-05-27"
  },
  "meta": { "cached": false, "timestamp": "2026-05-27T12:00:00.000Z" }
}

GET /api/rss

Standards-compliant RSS 2.0 XML feed. Works with any feed reader.

Param Default Description
source all Filter by source
limit 20 Max items
curl "https://aninews.vercel.app/api/rss"
curl "https://aninews.vercel.app/api/rss?source=crunchyroll&limit=10"

GET /api/sources

Per-source health monitoring. Returns fetch status, article counts, and latency.

curl "https://aninews.vercel.app/api/sources"
πŸ“„ Example Response
{
  "success": true,
  "data": [
    {
      "key": "ann",
      "name": "Anime News Network",
      "status": "healthy",
      "articleCount": 15,
      "latency": "1234ms",
      "lastFetch": "2026-05-27T12:00:00.000Z",
      "lastError": null
    },
    {
      "key": "crunchyroll",
      "name": "Crunchyroll",
      "status": "degraded",
      "articleCount": 0,
      "latency": "15001ms",
      "lastFetch": "2026-05-27T11:55:00.000Z",
      "lastError": { "message": "Timeout", "time": "2026-05-27T11:55:00.000Z" }
    }
  ],
  "meta": {
    "total": 7,
    "healthy": 6,
    "degraded": 1,
    "responseTime": "2345ms"
  }
}

GET /api/health Β· GET /api/stats

Health check and cache statistics.

curl "https://aninews.vercel.app/api/health"
curl "https://aninews.vercel.app/api/stats"

POST /api/cache/clear

Manual cache flush. Requires API key when CACHE_CLEAR_KEY is set.

# Clear all caches
curl -X POST "https://aninews.vercel.app/api/cache/clear" \
  -H "X-Api-Key: your-secret-key"

# Clear specific cache key
curl -X POST "https://aninews.vercel.app/api/cache/clear" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-secret-key" \
  -d '{"key": "news_all"}'

GET /api/stream

Server-Sent Events stream. Sends an initial burst of status data then closes.

curl -N "https://aninews.vercel.app/api/stream"

⚠️ Vercel Hobby functions timeout at 10s. This endpoint sends a single burst and closes. For real-time updates, poll /api/news?refresh=true.


GET /api/openapi

OpenAPI 3.0.3 specification in JSON format. Use with Swagger UI, Postman, or any OpenAPI-compatible tool.

curl "https://aninews.vercel.app/api/openapi"

πŸ“‹ API Response Schema

Article Object

Field Type Description Example
title string Article headline "Demon Slayer Season 4"
slug string URL-safe identifier "ann-demon-slayer-season-4"
source string Display name of source "Anime News Network"
excerpt string Article description/summary "The official website..."
date string ISO 8601 publish date "2026-05-27T10:30:00.000Z"
image string Thumbnail URL "https://..."
link string Original article URL "https://..."
tags string[] Category tags ["news", "anime"]

Pagination Meta

Field Type Description
total number Total matching articles
returned number Articles in this response
offset number Current offset
limit number Page size
hasMore boolean Whether more pages exist
nextCursor string|null Opaque cursor for next page
source string Source filter applied
sort string Sort order applied
responseTime string Server processing time

🌐 Deployment

β–² Vercel (Recommended)

Deploy with Vercel

  1. Click the button above (or import manually on vercel.com)
  2. Vercel auto-detects the project β€” no config needed
  3. Your API is live! πŸŽ‰
# Or use Vercel CLI
npx vercel --prod

πŸ–₯️ Standalone Server

# Clone and install
git clone https://github.com/Shineii86/AniNewsAPI.git
cd AniNewsAPI && npm install

# Start production server
npm start
# β†’ http://localhost:3000

🐳 Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

πŸ“œ Available Scripts

Command Description Details
npm run dev πŸ”₯ Start development server Runs on localhost:3000
npm start πŸš€ Start production server NODE_ENV=production node server.js
npm test πŸ§ͺ Run integration tests Tests all 12 endpoints
npm run build πŸ“¦ Build (no-op for serverless) Vercel handles this

⚑ Performance

Metric Value
⚑ Cached response ~200ms
πŸ”„ Fresh fetch (all 7 sources) ~3-6s
πŸ’Ύ Cache TTL 10 minutes
πŸ” Retry attempts 3 per source
⏱️ Timeout per source 15 seconds
πŸ“° Total articles (avg) 60+ after dedup
πŸ“¦ Total codebase ~50KB

Optimization Features

  • πŸ’Ύ Two-tier cache β€” Memory-first with disk fallback
  • ⚑ Concurrent fetching β€” All 7 sources hit simultaneously
  • πŸ”„ Exponential backoff β€” 1s, 2s, 3s delays on retry
  • 🧹 Auto-cleanup β€” Stale rate limit buckets purged every 5 min
  • πŸ“ Disk persistence β€” Source metrics survive serverless cold starts
  • πŸ—œοΈ Minimal deps β€” Only 6 production dependencies

πŸ“ Changelog Highlights

Version Date Key Changes
4.2.0 2026-05-28 Code style overhaul β€” AlisaReactionBot-style documentation across all 26 files
4.1.6 2026-05-27 Full excerpts, no truncation β€” removed 200-char limit from all 7 fetchers
4.1.5 2026-05-27 Real excerpts for Comic Book, Anime Corner, Anime Herald
4.1.4 2026-05-27 Sources endpoint now does live health checks
4.1.3 2026-05-27 Persist source metrics to disk for serverless survival
4.1.0 2026-05-26 Date range filtering, cursor pagination, search scoring

πŸ“ See CHANGELOG.md for the full version history.


πŸ”§ Troubleshooting

Problem Cause Solution
❌ npm install fails Node.js version too old Upgrade to Node.js 20+ (node -v)
❌ No articles returned All sources down Check /api/sources for health status
❌ Cache always empty Serverless cold start Normal β€” first request after idle is slow
❌ Rate limited (429) Exceeded 100 req/min Wait for X-RateLimit-Reset seconds
❌ CORS errors Frontend domain blocked CORS is * β€” check browser extension
❌ RSS feed empty No cached articles Hit /api/news first to populate cache
❌ Article content empty Source blocked parsing Falls back to "View original article" link
❌ 404 on API routes Wrong URL format Use /api/news not /news
❌ Deploy fails on Vercel Build error Check npm run build locally first
❌ Tests failing Server not running Start server first with npm run dev

πŸ› Debug Mode

# Run with verbose logging
NODE_ENV=development npm run dev

# Run tests against local server
API_URL=http://localhost:3000 npm test

# Check cache state
curl http://localhost:3000/api/stats
curl http://localhost:3000/api/health

❓ FAQ

πŸ“° How do I add a new news source?
1. Create utils/fetchNewSource.js exporting an async function that returns an array of article objects: [{ title, slug, source, excerpt, date, image, link, tags }]
2. Register it in utils/sources.js β€” add an import and entry to the SOURCES object
3. Run npm test to verify, then submit a PR
πŸ”„ How often does the data refresh?
The cache TTL is 10 minutes by default. After that, the next request triggers a fresh fetch from all 7 sources. You can force a refresh with ?refresh=true or change the TTL with the CACHE_TTL environment variable.
πŸ“‘ Can I use this in my frontend app?
Yes! CORS is enabled for all origins (*). Just make fetch requests to the API endpoints. No API key needed for read operations. Example: fetch('https://aninews.vercel.app/api/news?limit=10')
πŸ—žοΈ How do I subscribe to the RSS feed?
Add https://aninews.vercel.app/api/rss to any feed reader (Feedly, Inoreader, NetNewsWire, etc.). You can filter by source: /api/rss?source=crunchyroll
πŸ“Š How does deduplication work?
Articles are deduplicated by normalized title β€” punctuation is stripped, whitespace is collapsed, and compared case-insensitively. The first occurrence (from the source that responded fastest) wins.
πŸ”’ Is the cache clear endpoint secure?
When CACHE_CLEAR_KEY is set, the endpoint requires an X-Api-Key header. Without the env var, the endpoint is open β€” so set it in production. Read endpoints (/api/news, etc.) are always open.
⏱️ Why is the first request slow?
On serverless (Vercel), the first request after idle triggers a "cold start" β€” the function initializes and fetches from all 7 sources (~3-6s). Subsequent requests hit the cache (~200ms). Warm functions stay alive for ~5 minutes.
🌐 Can I self-host this?
Yes! Use npm start to run the Express server on any VPS, Docker container, or PaaS. The Vercel serverless functions are optional β€” server.js handles everything.

πŸ—ΊοΈ Roadmap

🎯 Planned Features

  • πŸ” API key authentication β€” Per-user rate limits and usage tracking
  • πŸ“Š Admin dashboard β€” Web UI for cache management and source monitoring
  • πŸŒ™ Dark/light mode β€” Theme toggle for the landing page
  • πŸ“± PWA support β€” Install as app on mobile devices
  • πŸ”” Webhook notifications β€” Push new articles to Discord/Slack
  • πŸ“ˆ Analytics β€” Track popular endpoints and search queries
  • πŸ—„οΈ Database option β€” Optional Supabase/Postgres for persistence
  • 🌐 Multi-language β€” Support for Japanese, Korean news sources
  • πŸ€– AI summaries β€” Auto-generate article summaries
  • πŸ“¦ NPM package β€” Client SDK for easy integration

βœ… Completed

  • πŸ“° 7 news sources with concurrent fetching
  • πŸ’Ύ Two-tier caching (memory + disk)
  • πŸ” Full-text search with relevance scoring
  • πŸ“… Date range filtering
  • πŸ”„ Cursor-based pagination
  • πŸ—žοΈ RSS 2.0 feed
  • πŸ“„ Full article extraction
  • 🏷️ Tag filtering with counts
  • πŸ“Š Source health monitoring
  • πŸ“‹ OpenAPI 3.0.3 specification
  • πŸ“‘ SSE stream
  • πŸ”’ Cache clear authentication
  • πŸš€ One-click Vercel deployment
  • πŸ“– Comprehensive documentation

🀝 Contributing

Contributions are welcome and appreciated! Here's how you can help:

πŸ› Report Bugs

Found something broken?

Open an Issue

πŸ’‘ Suggest Features

Have an idea for the notebook?

Start a Discussion

πŸ”€ Submit PRs

Ready to contribute code?

Fork & Submit

πŸ”„ How to Contribute

# 1️⃣ Fork the repository
# Click the "Fork" button on GitHub

# 2️⃣ Clone your fork
git clone https://github.com/YOUR_USERNAME/AniNewsAPI.git
cd AniNewsAPI

# 3️⃣ Create a feature branch
git checkout -b feature/amazing-feature

# 4️⃣ Make your changes
# Edit files, add features, fix bugs...

# 5️⃣ Test your changes
npm test

# 6️⃣ Commit your changes
git commit -m 'feat: add amazing feature'

# 7️⃣ Push to your fork
git push origin feature/amazing-feature

# 8️⃣ Open a Pull Request
# Go to GitHub and create a PR

πŸ“‹ Guidelines

  • βœ… Follow the existing code style and documentation conventions
  • βœ… Write meaningful commit messages (use conventional commits)
  • βœ… Run npm test before submitting
  • βœ… Update CHANGELOG.md with your changes
  • βœ… Keep PRs focused β€” one feature or fix per PR
  • βœ… Add JSDoc comments for new functions
  • ❌ Don't commit node_modules or cache files
  • ❌ Don't add unrelated changes to a single PR

πŸ› Reporting Bugs

  1. Check existing issues first
  2. Create a new issue with:
    • Clear title and description
    • Steps to reproduce
    • Expected vs actual behavior
    • API endpoint and parameters used

πŸ’‘ Suggesting Features

  1. Check the Roadmap for planned features
  2. Open a feature request with:
    • Clear description of the feature
    • Use case / motivation
    • Example API usage if applicable

πŸ™ Acknowledgements

πŸ“° News Sources

Source About
Anime News Network Industry-leading anime journalism
Anime Corner Community-driven anime news & polls
MyAnimeList The largest anime/manga database
Otaku USA Magazine English-language anime culture magazine
Crunchyroll Official streaming platform news
Anime Herald Anime news, reviews & editorials
Comic Book Anime & manga coverage at ComicBook

πŸ› οΈ Technologies

  • Express β€” Fast, unopinionated web framework
  • Cheerio β€” Fast, flexible HTML parsing
  • Axios β€” Promise-based HTTP client
  • rss-parser β€” RSS/Atom feed parser
  • node-cache β€” In-memory caching
  • Vercel β€” Serverless deployment platform

πŸ“ Resources


πŸ“„ License

License: MIT

This project is licensed under the MIT License.

Free to use, modify, and distribute β€” see the LICENSE file for details.


πŸ‘€ Author

Shinei Nouzen
Full-Stack Developer & Anime Enthusiast

GitHub Telegram Instagram Email


⭐ Star History

Star History Chart

⭐ If you found this project useful, please consider giving it a star!


Made With ❀️ For The Anime Community

Β© 2026 Shineii86. All Rights Reserved.

About

Powerful Anime News API - real-time aggregation from 7 sources with smart caching, keyword search, RSS feeds, and full-article extraction.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors