Node.js/Express API with blog, mail, assets, tags, counters, and guestbook. Redis is used for caching/counters; JWT for auth; Helmet, rate limiting, IP whitelist, validation, and centralized error handling are enabled.
- Auth: JWT login/logout with token revocation.
- Mail:
POST /api/mail/sendEmail. - Guestbook: read/write/delete (password-protected).
- Blog:
- Get all/offset, get by slug (public or auth); drafts are 404 for guests and never cached.
- Create/update/publish/unpublish; supports
featuredImage. - Cache controls: server cache TTL and client
Cache-Controlmax-age are configurable. - Cache management endpoints to clear a slug or all.
- Tags: list, get by slug, create, delete.
- Assets: upload/delete/cache-clear, proxy/resizing, OpenGraph generation.
- Counters: get/set/increment; key whitelist enforced.
- Health: Redis/SMTP check.
Precedence: env vars > static.config.json. Defaults live in static.config.json; config/default.ts loads them with env overrides.
Key settings
- Ports/paths:
PORT,API_ROOT,ASSET_ROOT. - Auth:
ACCESS_TOKEN_SECRET(JWT). - Mail:
MAIL_HOST,MAIL_PORT,MAIL_SECURE,MAIL_USER,MAIL_PASS. - Guestbook password:
SECRET_PASSWORD. - Redis:
REDIS_HOST,REDIS_PORT,REDIS_PASSWORD. - Rate limiter: toggle + per-route in
static.config.json. - Blog cache:
- Server cache:
BLOG_CACHE_TTL(fallback tostatic.blog.cache_ttl, default 86400s). - Client cache header:
BLOG_CACHE_CLIENT_AGE(fallback tostatic.blog.cache_client_age, default 300s). - OG cache toggle:
BLOG_OG_CACHE.
- Server cache:
- IP whitelist:
IP_WHITELIST(comma-separated). - CORS:
CORS_ORIGINS(comma-separated).
npm install
# copy .env from .env.example and adjust
npm run dev # nodemon
# npm start # productionDefault base URL: http://localhost:3001/api.
- Health:
GET /api/health - Auth:
POST /api/auth/login,POST /api/auth/logout - Mail:
POST /api/mail/sendEmail - Guestbook:
GET /api/guestbook?password=...,POST /api/guestbook,DELETE /api/guestbook/:id - Blog:
GET /api/blog/all?page=&limit=GET /api/blog/offset?min=&max=&tagsContains=&titleContains=GET /api/blog/:slug(drafts 404 for guests; no cache for drafts)POST /api/blog/newPUT /api/blog/edit/update/:slugPUT /api/blog/edit/publish/:slugDELETE /api/blog/:slug- Cache:
DELETE /api/blog/cache/delete/:slug,DELETE /api/blog/cache/clear/
- Tags:
GET /api/tags/,GET /api/tags/:slug,POST /api/tags/,DELETE /api/tags/:slug - Assets:
POST /api/assets/upload,DELETE /api/assets/delete/:folder/:id,DELETE /api/assets/cache/clear/:id,DELETE /api/assets/cache/all,GET /assets/proxy/...,GET /assets/opengraph/get - Counters:
GET /api/counter/:name,POST /api/counter/:name,POST /api/counter/:name/increment
- Blog drafts: never cached; guests receive 404; authenticated users see all.
- Cache headers for public blog responses use
cache_client_age; server cache TTL usescache_ttl. - Helmet, rate limiting, IP whitelist, validation, and centralized error handling are enabled.
Whitelisted keys are defined in constants/redis.constant.ts. Only mapped keys are accepted by counter routes.
If Redis runs in Docker, set REDIS_HOST to the container hostname or service name; default is localhost.
-
Mail (
/api/mail)-
POST /sendEmail- Send contact email.- Body:
{ name, email, message, subject? }
- Body:
-