Skip to content

Flowfull-Node.js

Official Starter Kit

The official Node.js/TypeScript implementation of Flowfull, maintained by the Pubflow team.

Overview

flowfull-node is the production-ready, official starter kit for building Flowfull backends with Node.js and TypeScript. It includes all 7 core concepts, best practices, and is regularly updated.

Features

  • TypeScript-first - Full type safety
  • Bun Runtime - Fast, modern JavaScript runtime (Node.js 18+ also supported)
  • Hono Framework - Lightweight, fast web framework
  • Kysely ORM - Type-safe SQL query builder
  • Zod Validation - Schema validation for environment and data
  • All 7 Core Concepts - Bridge Validation, HybridCache, Trust Tokens, etc.
  • Production-Ready - Battle-tested patterns and security

Installation

Prerequisites

  • Bun 1.0+ (recommended) or Node.js 18+
  • PostgreSQL, MySQL, or LibSQL database
  • Redis (optional, for HybridCache)

Quick Start

bash
# Clone the official starter kit
git clone https://github.com/pubflow/flowfull-node.git my-backend
cd my-backend

# Install dependencies
bun install

# Copy environment template
cp .env.example .env

# Edit .env with your configuration
# FLOWLESS_URL, BRIDGE_SECRET, DATABASE_URL, etc.

# Run migrations
bun run migrate

# Start development server
bun run dev

Server runs at: http://localhost:3000

Project Structure

flowfull-node/
├── src/
│   ├── lib/
│   │   ├── bridge/           # Bridge Validation
│   │   │   ├── validator.ts
│   │   │   └── validation-modes.ts
│   │   ├── cache/            # HybridCache
│   │   │   ├── hybrid-cache.ts
│   │   │   ├── lru.ts
│   │   │   └── redis.ts
│   │   ├── auth/             # Auth Middleware
│   │   │   └── middleware.ts
│   │   ├── database/         # Database
│   │   │   ├── index.ts
│   │   │   └── kysely.ts
│   │   ├── trust-tokens/     # Trust Tokens (PASETO)
│   │   │   ├── email-verification.ts
│   │   │   ├── password-reset.ts
│   │   │   └── invitation.ts
│   │   └── config/           # Configuration
│   │       ├── env.ts
│   │       └── trust-tokens.ts
│   ├── routes/               # API Routes
│   │   ├── auth/
│   │   ├── users/
│   │   └── index.ts
│   └── index.ts              # Entry Point
├── migrations/               # Database Migrations
│   ├── 001_create_users.ts
│   ├── 002_create_sessions.ts
│   └── 003_create_trust_tokens.ts
├── scripts/                  # Utility Scripts
│   └── generate-paseto-keys.ts
├── .env.example             # Environment Template
├── package.json
├── tsconfig.json
└── README.md

Technology Stack

TechnologyPurposeVersion
BunRuntime1.0+
TypeScriptLanguage5.0+
HonoWeb Framework4.0+
KyselyORM0.27+
ZodValidation3.22+
PASETOTrust Tokens3.1+
RedisCache7.0+

Environment Configuration

See the complete Environment Configuration guide.

Required Variables

env
# Flowless Configuration
FLOWLESS_URL=https://your-instance.pubflow.com
BRIDGE_SECRET=your-bridge-secret

# Database
DATABASE_TYPE=postgresql
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# Server
PORT=3000
NODE_ENV=development

# Security
VALIDATION_MODE=STANDARD

Optional Variables

env
# Cache
CACHE_ENABLED=true
REDIS_URL=redis://localhost:6379

# Trust Tokens
PASETO_PRIVATE_KEY=k4.secret.xxx
PASETO_PUBLIC_KEY=k4.public.xxx

# Email Provider
EMAIL_PROVIDER=zeptomail
ZEPTOMAIL_API_KEY=xxx

# URLs
FRONTEND_URL=https://yourdomain.com
BACKEND_URL=https://api.yourdomain.com

Core Concepts Implementation

1. Bridge Validation

typescript
import { validateBridgeSession } from './lib/bridge/validator';

const session = await validateBridgeSession(sessionId, {
  ip: request.ip,
  userAgent: request.headers['user-agent'],
  deviceId: request.headers['x-device-id']
});

See: Bridge Validation Guide

2. HybridCache

typescript
import { hybridCache } from './lib/cache/hybrid-cache';

const user = await hybridCache.get('user', userId, async () => {
  return await db.selectFrom('users')
    .where('id', '=', userId)
    .selectAll()
    .executeTakeFirst();
});

See: HybridCache Guide

3. Trust Tokens

typescript
import { V4 } from 'paseto';

const token = await V4.sign({
  userId,
  email,
  type: 'email_verification',
  exp: new Date(Date.now() + 86400000).toISOString()
}, process.env.PASETO_PRIVATE_KEY);

See: Trust Tokens Guide

4. Auth Middleware

typescript
import { Hono } from 'hono';
import { requireAuth, optionalAuth } from './lib/auth/middleware';

const app = new Hono();

// Protected route
app.get('/api/profile', requireAuth(), async (c) => {
  const userId = c.get('user_id');
  return c.json({ userId });
});

// Optional auth
app.get('/api/posts', optionalAuth(), async (c) => {
  const userId = c.get('user_id'); // undefined if not authenticated
  // Your logic
});

See: Auth Middleware Guide

5. Multi-Database Support

typescript
import { db } from './lib/database';

// Works with PostgreSQL, MySQL, LibSQL, Neon, PlanetScale
const users = await db.selectFrom('users')
  .selectAll()
  .execute();

See: Multi-Database Guide

API Routes

Example: Protected User Route

typescript
// src/routes/users/profile.ts
import { Hono } from 'hono';
import { requireAuth } from '../../lib/auth/middleware';
import { hybridCache } from '../../lib/cache/hybrid-cache';
import { db } from '../../lib/database';

const app = new Hono();

app.get('/profile', requireAuth(), async (c) => {
  const userId = c.get('user_id');

  // Get from cache (LRU → Redis → Database)
  const user = await hybridCache.get('user', userId, async () => {
    return await db.selectFrom('users')
      .where('id', '=', userId)
      .selectAll()
      .executeTakeFirst();
  });

  if (!user) {
    return c.json({ error: 'User not found' }, 404);
  }

  return c.json({ user });
});

export default app;

Database Migrations

Creating a Migration

typescript
// migrations/004_create_posts.ts
import { Kysely } from 'kysely';

export async function up(db: Kysely<any>): Promise<void> {
  await db.schema
    .createTable('posts')
    .addColumn('id', 'varchar(255)', (col) => col.primaryKey())
    .addColumn('user_id', 'varchar(255)', (col) => col.notNull())
    .addColumn('title', 'varchar(255)', (col) => col.notNull())
    .addColumn('content', 'text', (col) => col.notNull())
    .addColumn('created_at', 'timestamp', (col) => col.notNull())
    .execute();
}

export async function down(db: Kysely<any>): Promise<void> {
  await db.schema.dropTable('posts').execute();
}

Running Migrations

bash
# Run all pending migrations
bun run migrate

# Rollback last migration
bun run migrate:rollback

Testing

bash
# Run tests
bun test

# Run tests with coverage
bun test --coverage

# Run specific test file
bun test src/lib/cache/hybrid-cache.test.ts

Deployment

See the complete Deployment Guide.

Railway

bash
# Install Railway CLI
npm i -g @railway/cli

# Login
railway login

# Deploy
railway up

Fly.io

bash
# Install Fly CLI
curl -L https://fly.io/install.sh | sh

# Login
fly auth login

# Deploy
fly deploy

Docker

dockerfile
FROM oven/bun:1

WORKDIR /app

COPY package.json bun.lockb ./
RUN bun install --production

COPY . .

EXPOSE 3000

CMD ["bun", "run", "start"]

Performance

Benchmarks (on flowfull-node):

  • Requests/sec: 50,000+
  • Latency (p50): <5ms
  • Latency (p99): <20ms
  • Cache Hit Rate: 95%+

Best Practices

  1. Use TypeScript - Full type safety
  2. Enable HybridCache - 95%+ cache hit rate
  3. Use VALIDATION_MODE=STRICT in production
  4. Implement rate limiting on sensitive endpoints
  5. Log security events (failed auth, token usage)
  6. Use environment validation with Zod
  7. Run migrations before deployment
  8. Monitor cache performance with Redis

Resources

Support


Official starter kit maintained by the Pubflow team

Released under the MIT License.