Production-Ready REST API

Bunastack API

A NestJS backend with authentication, content management, media, and notifications — 70+ documented endpoints, secured by default.

70+Endpoints
23DB Entities
16Modules
GET /api/v1/posts · 200 OK
{
"statusCode": 200,
"message": "OK",
"data": [
{
"id": "3f9c…a1",
"nameLocalized": [
{ "lang": "en-us", "value": "Welcome to our blog" },
{ "lang": "vi-vn", "value": "Chào mừng đến blog" }
],
"slugLocalized": [
{ "lang": "en-us", "value": "welcome-to-our-blog" },
{ "lang": "vi-vn", "value": "chao-mung-den-blog" }
],
"status": "PUBLISHED"
}
{ /* … more items */ }
],
"meta": {
"paging": {
"currentPage": 1,
"itemsPerPage": 20,
"totalItems": 145,
"totalPages": 8
}
}
}
statusCode — result codedata — list of recordsmeta.paging — pagination

Built on a proven stack

Modern, battle-tested technologies — chosen for performance, type safety, and long-term maintainability.

Framework

NestJS 11API framework
TypeScript 5Typed end-to-end
Express 5HTTP server

Data

PostgreSQL 18Relational database
MikroORM 7TypeScript ORM
RedisCache & throttling

Security

JWTAccess & refresh tokens
Argon2Password hashing
HelmetSecurity headers

Storage

AWS S3Object storage
MinIOSelf-hosted S3
Sharp 0.34Image thumbnails

Notifications

NodemailerSMTP email
Expo PushPush notifications
WebhooksSlack & Teams

Tooling

SwaggerOpenAPI docs
Vitest 4Unit & E2E tests
DockerLocal & prod setup
App Architecture

Clean layers, one-way flow, easy to extend

The API follows clean architecture — controllers handle transport, services own business logic, and repositories talk to the database. Each layer depends on abstractions, not concrete implementations.

  • Controller → Service → Repository
  • Dependency injection throughout
  • Stateless, horizontally scalable
  • Feature-based module folders
SOLIDDRYKISSNo SELECT *No N+1Testable
Clean architecture
One-way flow, top to bottom
SOLID
Transport
Controllers · DTOs · Guards
post.controller.tscreate-post.dto.tspermission.guard.ts
Business Logic
Services · validators · workflows
post.service.tspost.validator.tsversioning.service.ts
Data Access
Repositories · MikroORM · PostgreSQL
post.repository.tspost.entity.tsmigrations/
Stateless services ✓Dependency injection ✓Feature-based modules ✓Testable by design ✓
Authentication & Authorization

Who can log in, what they can do — decided server-side

The API authenticates every identity and authorizes every action. Tokens are short-lived and rotated, permissions come from the database on each request, and access can be revoked via ban/version bump (Redis) from anywhere.

  • Email & OAuth login
  • Short-lived access + rotating refresh
  • RBAC resolved from DB per request
  • Revoke access from any device
How token rotation works

Each access token is short-lived, so a leaked token expires on its own. When it does, the refresh cookie — stored HttpOnly — is exchanged server-side for a brand-new access + refresh pair. The old refresh token is invalidated instantly, so it can never be replayed.

Revoked in one call

Revoking bans the user / bumps token version (Redis) and invalidates refresh tokens — access tokens expire shortly, from anywhere.

Argon2 hashinghttpOnly cookiesRate limitedAudit logged
Authentication flow
Every request, end to end
SECURED
✓
Sign in
Email / OAuth · Argon2 hashing
✓
Issue tokens
httpOnly cookie (access + refresh, 15m + 14d) — no token in JS memory
3
Validate request
BetterAuthGuard · stateless JWT + Redis ban/version if enabled
4
Check permissions
PermissionGuard · effective RBAC from DB
5
Token control
Ban/version bump · rotation on refresh (Redis)
Token lifecycle
Access token2 min TTL
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…
Sent with every request · validated on the server
Refresh tokenrotating
HttpOnly cookie · SameSite=Strict · 14 days
Exchanged for a new access + refresh token on expiry
Supported sign-in methods
emailGoogleAppleGithub
Content Management

Posts, categories & menus — one content API

Manage the building blocks of your site: posts, categories, products, and menus. All localized, validated, and versioned — ready to power any frontend.

  • Full CRUD for posts, categories & menus
  • Localized fields & real-time slug check
  • Nested categories & drag-drop menus
  • Publish workflow & version history
PostsCategoriesProductsMenus
Content tree
Posts, categories & menus in one API
CRUD
NewsHow we ship faster
PUBLISHED
BlogTeam culture at Bunastack
DRAFT
DocAPI versioning guide
PUBLISHED
PageQ3 product roadmap
SCHEDULED
Multilingual ✓Slug validation ✓Publish workflow ✓Versioned ✓
Roles & Permissions

Role-based access control, enforced on every request

Define roles, map granular permissions, and gate every API route and admin screen by effective access — resolved from the database on each request, never trusted from the client.

  • Create roles with custom permission sets
  • 35+ permissions across every module
  • Guards on routes and endpoints
  • Effective permissions from DB per request
Super admin bypassPrivilege escalation blockedPermission matrixAudit-ready
Role → Permission matrix
What each role can actually do
RBAC
Super Admin8 permissions
posts.viewposts.createposts.editposts.deleteusers.viewusers.editroles.viewroles.edit
Editor6 permissions
posts.viewposts.createposts.editposts.deletecategories.viewcategories.create
Viewer4 permissions
posts.viewproducts.viewcategories.viewaudit_logs.view
Permission set (35+)
posts.viewposts.createposts.editposts.deleteusers.viewusers.editroles.viewroles.edit
Content Versioning

Every change becomes a version you can restore

Posts, categories, and products are automatically versioned on every update, delete, and bulk delete — review the full history and roll back any change in one click, without losing anything.

  • Auto-revision on update & delete
  • Full version history per record
  • One-click restore any version
  • Rollback keeps history — restore again
PostsCategoriesProductsBulk delete versioned
Post · “How we ship”
Version history
5 versions
v5
2 min ago
Published
v4
Yesterday
Draft
v3
3 days ago
Restored
v2
5 days ago
Edited
v1
1 week ago
Created
One click to restore any version
Rollbacks create a new revision, so history is never lost.
Security

Hardened against the OWASP Top 10, by default

Every endpoint is validated, throttled, and guarded before it reaches your business logic. Passwords are hashed with Argon2, tokens stay short-lived, and files are checked by content — not just by extension.

  • Validate every input at the boundary
  • Rate limit auth & write endpoints
  • Argon2 password hashing
  • MIME-sniffed file uploads
Helmet headersCORS allowlisthttpOnly cookiesAudit logged
Security layers
Every request passes through
OWASP-AWARE
Input validation
class-validator · whitelist · reject unknown fields
Rate limiting
Redis-throttled auth & write endpoints
Security headers
Helmet · CSP · HSTS
Password hashing
Argon2 — memory-hard, never stored plain
Token expiry
Short-lived access · rotating refresh
CORS allowlist
Only trusted origins can call the API
SQLi ✓XSS ✓CSRF ✓SSRF ✓Path traversal ✓Mass assignment ✓
File Manager

Upload once, serve everywhere

Upload images, video, audio, and documents with MIME validation — stored in S3 or self-hosted MinIO with thumbnails generated for you.

  • Single & bulk upload
  • S3 or self-hosted MinIO
  • Auto thumbnails for images (768px & 360px)
  • File manager with bulk delete
MIME sniffing10MB per file5 files per callAttach to posts & products
Media library
Upload once, reuse everywhere
S3 READY
IMGthumb ✓
hero-banner.webp
248 KB
VID
product-demo.mp4
4.2 MB
AUD
intro-audio.mp3
1.1 MB
PDF
specs.pdf
860 KB
IMGthumb ✓
about-team.webp
512 KB
VID
tutorial.mp4
8.6 MB
AUD
podcast.mp3
3.4 MB
PDF
brochure.pdf
1.9 MB
Thumbnails for images only
WebP, PNG, JPG, GIF, SVG — auto-generated on upload. Video, audio & documents keep their original file.
original
768px
360px
Upload · MIME-validated · 10MB max
Themes

Per-user themes, stored and synced

Save each user's theme and language in their preferences — light, dark, system, or a themed palette. The API stores it once, and every client applies the same choice.

  • Light, dark & system themes
  • Themed palettes (Medieval, Feudal, Wabi-sabi)
  • Saved per user via preferences API
  • One API call to read & update
LightDarkSystemThemed palettes
User preferences
Theme saved per user, applied everywhere
SYNCED
Light
light
Dark
dark
System
system
ACTIVE
Medieval Europe
medieval-europe
Feudal Japan
feudal-japan
Wabi-sabi
wabi-sabi
Stored in user preferences
theme: "Medieval Europe"
language: "en-us"
Languages

One content model, every language

Store name, slug, description, and body for each language in a single entity — the API serves the right translation to the right audience, and clients pick what they need.

  • Localized name, slug, description & body
  • 11 language codes ready in shared definitions
  • Pick translations per request
  • Same structure, zero duplication
en-usvi-vnja-jpko-kr+7 more
Supported languages
One content model, many audiences
11 READY
en-usEnglish
DEFAULT
vi-vnTiếng Việt
th-thไทย
zh-cn简体中文
es-esEspañol
fr-frFrançais
de-deDeutsch
ru-ruРусский
pt-ptPortuguês
ja-jp日本語
ko-kr한국어
Same entity, localized content
en-usWelcome to our blog
vi-vnChào mừng đến blog
ja-jpブログへようこそ
Testing

Tested at every layer, ready to ship

Unit tests cover business logic in isolation, while E2E suites run real HTTP flows against a dedicated test database — so you get an API that's verified, not just shipped.

  • Unit tests for services & validators
  • 22+ E2E suites with Supertest
  • Dedicated test database
  • Auth, roles & rate-limit covered
VitestSupertestCoverage reportsRun locally
Test suite
Unit + E2E
GREEN
Unit test files
17
E2E suites
22
Test cases
1200+
Vitest ✓Supertest ✓Test DB ✓Coverage reports ✓
Contact

Let's build something great

Have a project in mind or want to learn more? Reach out — we usually reply within one business day.

Reach Us Directly

Prefer a direct line?

Pick whichever channel suits you — we read everything and get back fast.

Average response time: under 24 hours

Get in touch

Please feel free to contact us if you have any questions.

We typically respond within one business day.

© 2026 Bunastack. All rights reserved.