Consenti

Backend — Installation

ℹ️The API package requires Node.js 22 or later. You need Node 24 to use node:sqlite which shipped as a stable built-in in.

npm install

bash
npm install @consenti/api

Add to your existing Express app

createConsenti returns a router you mount on your existing server. No new process, no separate port — it lives inside your app at /consenti.

app.ts
ts
import express from 'express'
import { createConsenti } from '@consenti/api'

const app = express()

const consenti = createConsenti({
  storage: { driver: 'node:sqlite', path: './consenti-data' },  // directory, not a file
  auth: { mode: 'local', adminEmail: '[email protected]', adminPassword: process.env.CONSENTI_ADMIN_PASSWORD! },
  dashboard: true,
})

app.use(consenti.router)  // mounts all routes under /consenti

app.listen(3000, () => {
  console.log('Server at http://localhost:3000')
  console.log('Admin at http://localhost:3000/consenti/')
})

Standalone — no existing server

Use the plain node:http handler when you have no existing HTTP framework.

server.ts
ts
import { createServer } from 'node:http'
import { createConsenti } from '@consenti/api'

const consenti = createConsenti({
  storage: { driver: 'node:sqlite', path: './consenti-data' },
  auth: {
    mode: 'local',
    adminEmail: '[email protected]',
    adminPassword: process.env.CONSENTI_ADMIN_PASSWORD!,
  },
  dashboard: true,
})

await consenti.ready   // wait for DB + bootstrap

const server = createServer(consenti.handler)
server.listen(3001, () => {
  console.log('Admin dashboard → http://localhost:3001/consenti/')
  console.log('REST API        → http://localhost:3001/consenti/api/v1/')
})

With Fastify

app.ts
ts
import Fastify from 'fastify'
import { createConsenti } from '@consenti/api'

const fastify = Fastify()
const consenti = createConsenti({
  storage: { driver: 'node:sqlite', path: './consenti-data' },
  auth: { mode: 'local', adminEmail: '[email protected]', adminPassword: process.env.CONSENTI_ADMIN_PASSWORD! },
  dashboard: true,
})

await fastify.register(consenti.fastifyHandler)
await fastify.listen({ port: 3000 })

With Next.js App Router

app/consenti/[...path]/route.ts
ts
import { createConsenti } from '@consenti/api'
import type { NextRequest } from 'next/server'

let consenti: Awaited<ReturnType<typeof createConsenti>>

async function getConsenti() {
  if (!consenti) {
    consenti = createConsenti({
      storage: { driver: 'node:sqlite', path: './consenti-data' },
      auth: {
        mode: 'local',
        adminEmail: process.env.CONSENTI_ADMIN_EMAIL!,
        adminPassword: process.env.CONSENTI_ADMIN_PASSWORD!,
      },
    })
  }
  return consenti
}

async function consentiHandler(req: NextRequest) {
  const c = await getConsenti()
  return c.handleRequest(req)
}

export { consentiHandler as GET, consentiHandler as POST, consentiHandler as PUT, consentiHandler as DELETE, consentiHandler as PATCH }
💡The consenti.handler is a standard http.IncomingMessage → http.ServerResponse handler. Any Node.js HTTP framework can wrap it.

First run

On first start, Consenti:

  1. Creates the storage directory at the configured storage.path with db/, profiles/, and logs/ subdirectories
  2. Runs all migrations (creates visitors, consent_records, consent_history, profiles, admin_users, audit_logs tables and DB indexes)
  3. Creates the admin user from auth.adminEmail + auth.adminPassword
  4. Seeds the default profile (profileId: '0')

Subsequent starts run pending migrations only.

Environment variables

All config fields can be set via environment variables. Code config takes precedence over env vars.

.env
bash
# Auth
CONSENTI_ADMIN_EMAIL=[email protected]
CONSENTI_ADMIN_PASSWORD=your-strong-password
CONSENTI_ADMIN_JWT_SECRET=your-jwt-secret   # auto-generated if not set (sessions expire on restart)

# Storage
CONSENTI_DB_DRIVER=node:sqlite              # default: json
CONSENTI_DB_PATH=./consenti-data            # directory path
CONSENTI_DB_URI=postgresql://...            # server drivers (pg, mysql, mongodb)
CONSENTI_DB_DATABASE=consenti               # database name override

# Routing
CONSENTI_BASE_PATH=/cmp                     # change /consenti prefix (default: /consenti)

# Rate limiting
CONSENTI_RATE_LIMIT_WINDOW_MS=60000         # default: 60000
CONSENTI_RATE_LIMIT_MAX_REQUESTS=60         # default: 60

# Body size
CONSENTI_MAX_BODY_SIZE=1048576              # default: 1 MB

# Node.js
NODE_ENV=production                         # suppresses stack traces in error responses