Skip to content

kali-kar/quotes-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“œ Quotes API

A production-grade REST API that serves random quotes from famous Indian scholars and scientists β€” built with Node.js, Express, and SQLite. Designed to be deployable anywhere in minutes with zero external dependencies.


🌟 Project Overview

The Quotes API is a stateless, scalable HTTP service that exposes a curated dataset of 25+ quotes from luminaries such as A.P.J. Abdul Kalam, C.V. Raman, Srinivasa Ramanujan, Jagadish Chandra Bose, and more. The architecture is deliberately simple β€” one file-based SQLite database, no background processes β€” making it trivial to run locally or deploy on a PaaS like Render.


✨ Features

Feature Detail
Random quote endpoint Scalable offset-based selection (no ORDER BY RANDOM())
Health check /api/v1/health β€” uptime + timestamp
Rate limiting 60 req / min / IP via express-rate-limit
Security headers helmet + cors
Structured logging pino with pretty-print in dev, JSON in prod
Graceful shutdown SIGTERM / SIGINT handling with connection cleanup
Redis-ready Drop-in store swap when you need distributed rate limiting
Zero external DB SQLite file β€” no Postgres, no MongoDB, no setup

πŸ› οΈ Tech Stack

  • Runtime β€” Node.js 18+ LTS
  • Framework β€” Express.js 4
  • Database β€” SQLite via better-sqlite3
  • Logging β€” pino + pino-pretty
  • Security β€” helmet, cors
  • Rate limiting β€” express-rate-limit
  • Config β€” dotenv

πŸš€ Local Setup

Prerequisites

  • Node.js 18 or newer (node -v)
  • npm 9 or newer (npm -v)

1 β€” Clone & install

git clone https://github.com/your-username/quotes-api.git
cd quotes-api
npm install

2 β€” Configure environment

cp .env.example .env
# Edit .env if you want to change PORT or DB_PATH

3 β€” Seed the database

npm run seed

You should see:

βœ…  Seed complete β€” 25 new row(s) inserted. Total in DB: 25

4 β€” Start the server

# Development (with pretty logs + auto-restart via nodemon)
npm run dev

# Production
npm start

The server will be live at http://localhost:3000.


πŸ“‘ API Endpoints

GET /api/v1/quote

Returns a single random quote.

Response 200 OK:

{
  "success": true,
  "data": {
    "quote": {
      "id": 4,
      "quote": "Dream is not that which you see while sleeping; it is something that does not let you sleep.",
      "author": "A.P.J. Abdul Kalam"
    }
  }
}

GET /api/v1/health

Health check β€” used by load balancers and uptime monitors.

Response 200 OK:

{
  "success": true,
  "data": {
    "status": "ok",
    "uptime": 42.317,
    "timestamp": "2024-06-01T10:00:00.000Z",
    "service": "quotes-api"
  }
}

Error responses

All errors follow the same shape:

{
  "success": false,
  "error": "Route GET /api/v1/does-not-exist not found."
}
Status Scenario
404 Route or resource not found
429 Rate limit exceeded
500 Internal server error

πŸ§ͺ Example Requests (curl)

# Random quote
curl http://localhost:3000/api/v1/quote

# Health check
curl http://localhost:3000/api/v1/health

# With pretty JSON output (requires jq)
curl -s http://localhost:3000/api/v1/quote | jq .

# Check rate-limit headers
curl -I http://localhost:3000/api/v1/quote

☁️ Deployment on Render

Render is a great free-tier PaaS for Node.js APIs. Here's how to deploy:

Step 1 β€” Push to GitHub

git init
git add .
git commit -m "feat: initial production API"
git remote add origin https://github.com/your-username/quotes-api.git
git push -u origin main

Step 2 β€” Create a Render Web Service

  1. Log in at render.com and click New β†’ Web Service
  2. Connect your GitHub repo
  3. Fill in the settings:
Field Value
Name quotes-api
Region Choose closest to your users
Branch main
Runtime Node
Build Command npm install && npm run seed
Start Command npm start
Instance Type Free (or Starter for always-on)

Step 3 β€” Add Environment Variables

In Environment β†’ Add Environment Variable:

Key Value
NODE_ENV production
PORT 10000 (Render sets this automatically)
DB_PATH ./database/quotes.db

⚠️ Persistent disk note: Render's free tier has an ephemeral filesystem β€” the DB resets on each deploy. To persist data across deploys, attach a Render Disk (paid) mounted at /var/data and set DB_PATH=/var/data/quotes.db. The seed script is idempotent and safe to re-run.

Step 4 β€” Deploy

Click Create Web Service. Render will build, seed, and start your API. You'll get a public URL like:

https://quotes-api-xxxx.onrender.com/api/v1/quote

Step 5 β€” Verify

curl https://quotes-api-xxxx.onrender.com/api/v1/health

πŸ—οΈ Project Structure

quotes-api/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app.js              # Express app factory (middlewares + routes)
β”‚   β”œβ”€β”€ server.js           # HTTP server + graceful shutdown
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ env.js          # Centralised env var access
β”‚   β”‚   β”œβ”€β”€ database.js     # SQLite singleton connection
β”‚   β”‚   └── logger.js       # Pino logger instance
β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   └── quoteController.js
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   └── quoteRoutes.js
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   └── quoteService.js # Business logic + scalable random query
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”œβ”€β”€ rateLimiter.js
β”‚   β”‚   β”œβ”€β”€ errorHandler.js
β”‚   β”‚   └── requestLogger.js
β”‚   └── utils/
β”‚       └── response.js     # sendSuccess / sendError helpers
β”œβ”€β”€ database/
β”‚   β”œβ”€β”€ init.sql            # Raw schema (informational)
β”‚   └── seed.js             # Idempotent seed script
β”œβ”€β”€ .env.example
β”œβ”€β”€ package.json
└── README.md

πŸ”Œ Redis (Optional β€” Future Scaling)

The rate limiter uses an in-memory store by default. When you need distributed rate limiting across multiple instances, swap the store in src/middleware/rateLimiter.js:

const RedisStore = require('rate-limit-redis');
const { createClient } = require('redis');

const redisClient = createClient({ url: env.REDIS_URL });
await redisClient.connect();

const rateLimiter = rateLimit({
  // ... existing config ...
  store: new RedisStore({ sendCommand: (...args) => redisClient.sendCommand(args) }),
});

Set REDIS_URL in your .env and install the packages:

npm install rate-limit-redis redis

No other changes required β€” the rest of the codebase remains stateless.


πŸ“„ License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors