🚀 Quick Start
Get up and running in minutes with a single command.
bunx @noundryfx/ndts-cli init
For a complete step-by-step guide including CRM sample application, visit the Getting Started page.
Prerequisites
- Bun v1.3+ - JavaScript runtime (bun.com)
- Docker (optional) - For database, Redis, and other services
🏗️ Architecture
API Architecture Patterns
Choose the pattern that fits your needs:
DAPI (Direct API) - Default
Frontend → API Routes → Database
- ✓ Direct database access via Drizzle ORM
- ✓ All business logic in routes
- ✓ Perfect for new applications
- ✓ Fast development
Use when: Building a new app from scratch
BFF (Backend for Frontend)
Frontend → BFF → Services → Backend API
- ✓ Wraps existing backend APIs
- ✓ Forwards bearer tokens
- ✓ Transforms data for frontend
- ✓ Perfect for enterprise
Use when: Integrating with C#, Java, Python, etc. backends
Project Structure
your-app/
├── packages/
│ ├── server/ # Hono API server
│ │ ├── src/
│ │ │ ├── config/ # Environment, database, cache
│ │ │ ├── middleware/ # Auth, logging, errors
│ │ │ ├── routes/ # API endpoints
│ │ │ ├── schema/ # Database schema (Drizzle)
│ │ │ └── index.ts # Server entry point
│ │ └── package.json
│ │
│ └── client/ # HonoX with Hono JSX
│ ├── app/
│ │ ├── routes/ # File-based routing (.tsx)
│ │ │ ├── index.tsx # Home page
│ │ │ ├── login.tsx # Login page
│ │ │ ├── dashboard.tsx # Dashboard
│ │ │ └── records/ # CRUD routes
│ │ ├── components/ # Reusable components
│ │ ├── server.ts # HonoX entry point
│ │ ├── global.tsx # Global layout (jsxRenderer)
│ │ └── style.css # Tailwind v4 + Basecoat UI
│ ├── public/static/js/ # Client-side utilities
│ ├── vite.config.ts # HonoX Vite config
│ └── package.json
├── scripts/ # Service management
├── docker-compose.dev.yml # Dev services
├── docker-compose.yml # Production
├── .env.example
├── package.json # Monorepo scripts
└── README.md
💻 Client Development
HonoX with Hono JSX - Server-Side Rendering without React
The client uses HonoX for file-based routing and Hono JSX for server-side rendering - lightweight, fast, and type-safe.
Technology Stack
- • HonoX - Full-stack framework with file-based routing
- • Hono JSX - Server-side JSX rendering (NO React!)
- • Vite - Build tool with customRender for Tailwind
- • Tailwind CSS v4 - Modern utility-first CSS
- • Basecoat UI - shadcn/ui-inspired components
- • Inter Font - Professional typography
File-Based Routing
HonoX automatically generates routes from .tsx files in app/routes/:
Global Layout:
import { jsxRenderer } from 'hono/jsx-renderer'
export default jsxRenderer(({ children, title }) => {
return (
<html>
<head>
<title>{title}title>
<link href="/app/style.css" rel="stylesheet" />
head>
<body>{children}body>
html>
)
})
Route Component:
export default function Login() {
return (
<div class="container mx-auto p-8">
<div class="card max-w-md mx-auto">
<form id="login-form">
<input class="input" />
<button class="btn">Loginbutton>
form>
div>
div>
)
}
Route Examples:
app/routes/index.tsx→ /app/routes/about.tsx→ /aboutapp/routes/records/index.tsx→ /recordsapp/routes/records/[id].tsx→ /records/:id
Creating Components
Build reusable components with Hono JSX:
type ButtonProps = {
children: any
variant?: 'primary' | 'secondary'
}
export function Button({ children, variant = 'primary' }: ButtonProps) {
const buttonClass = variant === 'primary'
? 'btn btn-primary'
: 'btn btn-secondary'
return <button class={buttonClass}>{children}button>
}
Tailwind CSS v4 + Basecoat UI
Use Tailwind utilities and Basecoat components:
Tailwind Classes
Utility-first CSS with all Tailwind v4 utilities available
Basecoat Components
.card, .btn, .input, .badge and more
Inter Font
Professional typography included by default
customRender
Vite plugin for Tailwind compilation
🎨 UI Components
Pre-built TypeScript Components
Add production-ready components to your project with a single command. No React required!
Adding Components
Use the ndts CLI to add components to your project:
# Interactive component selection
ndts add
# Add specific components
ndts add input multiselect datatable
# Add all components
ndts add --all
# Filter by category
ndts add --all --category noundry
Available Components
Input
Flexible input field with icon support
ndts add input
MultiSelect
Multi-select dropdown with API support
ndts add multiselect
DataTable
Premium table with advanced pagination, sorting & search
ndts add datatable
DatePicker
Date picker with calendar interface
ndts add datepicker
Modal & SlideOver
Overlay and panel components
ndts add modal
More...
NavigationMenu, DateRangePicker, Pacer
ndts add --all
Using Components
Components are added to your project and can be imported:
Import Component:
import { Input } from './components/ui/Input'
const emailInput = Input.create({
name: 'email',
type: 'email',
placeholder: 'Enter email',
icon: 'envelope',
iconPosition: 'left'
})
document.body.appendChild(emailInput)
DataTable Example:
const table = DataTable.create({
columns: [
{ key: 'id', label: 'ID', sortable: true },
{ key: 'name', label: 'Name' }
],
apiEndpoint: '/api/users',
pagination: true,
searchable: true
})
🔗 URL State Binding
NEW FEATURE: Shareable, Bookmarkable Component States!
All form and data components now support bidirectional URL state synchronization. Enable with bindToUrl: true to make your components shareable and bookmarkable.
What You Get:
- Shareable URLs - Copy URL to share exact component state
- Bookmarkable - Save specific configurations
- Browser Back/Forward - Works automatically
- Deep Linking - Direct links to specific states
- No Page Reloads - Uses History API
Supported Components:
Form inputs sync values to URL
Selections stored in URL
Pagination, search, sort in URL
Open state + data passing
Enable URL Binding:
const searchInput = Input.create({
name: 'query',
bindToUrl: true // ← Enable URL sync
})
// URL becomes: ?query=laptop
Modal with Data Passing:
const modal = new FullScreenModal({
id: 'user',
bindToUrl: true,
onUrlData: (data) => { /* use data */ }
})
modal.open({ userId: 123 })
// URL: ?user=open&user-data={"userId":123}
Example URLs:
?search=laptop- Input value?date=2025-01-15- Date picker?tags=["react","typescript"]- Multi-select?users-page=2&users-search=john- DataTable state
📖 Full Component Documentation
View detailed documentation, API references, and interactive examples for all components. See the DataTable live demo with premium pagination!
🔧 Server Development
Technology Stack
- • Hono - Ultra-fast web framework (60x faster than Express)
- • Drizzle ORM - Type-safe database ORM
- • Bun - JavaScript runtime (3x faster than Node.js)
- • JWT - Authentication tokens
- • bcrypt - Password hashing
- • Zod - Schema validation
Creating API Routes
import { Hono } from 'hono';
import { auth } from '../middleware/auth';
import { db } from '../config/database';
import { users } from '../schema/schema';
import { eq } from 'drizzle-orm';
import { z } from 'zod';
const app = new Hono();
// Validation schema
const registerSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
name: z.string().min(1)
});
// Register endpoint
app.post('/register', async (c) => {
const body = await c.req.json();
const data = registerSchema.parse(body);
const [user] = await db.insert(users)
.values(data)
.returning();
return c.json(user, 201);
});
export default app;
Database Migrations
bun run db:generate # Generate migration from schema
bun run db:migrate # Run migrations
bun run db:studio # Open Drizzle Studio (GUI)
🔌 Service Integrations
⚡ Redis Caching
In-memory caching with automatic fallback to memory cache.
Port: 6379
Connection: redis://localhost:6379
import { cache } from '../config/cache';
// Set cache
await cache.set('user:123', userData, 3600); // TTL: 1 hour
// Get cache
const user = await cache.get('user:123');
// Delete cache
await cache.del('user:123');
📬 BullMQ Queues
Background job processing for async tasks.
Requires: Redis
Use for: Email sending, report generation, data processing
import { Queue, Worker } from 'bullmq';
// Create queue
const emailQueue = new Queue('emails');
// Add job
await emailQueue.add('send', {
to: 'user@example.com',
subject: 'Welcome!'
});
// Process jobs
const worker = new Worker('emails', async (job) => {
await sendEmail(job.data);
});
🗂️ S3 Blob Storage
S3-compatible storage for files and assets (works with AWS S3, MinIO, Cloudflare R2).
MinIO (dev): Port 9000 (API), Port 9001 (Console)
Credentials: minioadmin / minioadmin
import { s3Client } from '../config/storage';
import { PutObjectCommand } from '@aws-sdk/client-s3';
// Upload file
await s3Client.send(new PutObjectCommand({
Bucket: 'uploads',
Key: 'avatar.jpg',
Body: fileBuffer,
ContentType: 'image/jpeg'
}));
📝 Pino Logging
Structured JSON logging for production-ready applications.
import { logger } from '../config/logger';
logger.info('User registered', { userId: 123 });
logger.warn('Rate limit approaching');
logger.error('Database connection failed', { error });
logger.debug('Cache hit', { key: 'user:123' });
📊 OpenTelemetry
Distributed tracing and observability with Jaeger UI.
Jaeger UI: http://localhost:16686
OTLP Endpoint: Port 4318
Automatic instrumentation for HTTP requests, database queries, and cache operations.
📧 SMTP Email
Email sending with Resend, SendGrid, or custom SMTP.
Resend
Modern, developer-friendly
SendGrid
Enterprise email service
MailHog (dev)
Port 8025 (UI), Port 1025 (SMTP)
🔐 Authentication
Multiple authentication options to fit your needs.
Custom JWT (Default)
- • Built-in JWT + bcrypt
- • Full control over auth flow
- • Simple and straightforward
Better Auth
- • Modern auth library
- • Many OAuth providers
- • Type-safe
Auth.js
- • NextAuth.js compatible
- • Popular OAuth providers
- • Session management
Auth0
- • Enterprise authentication
- • Social login ready
- • MFA support
🐳 Docker Services
Automatic Service Startup
When you run bun run dev, Docker services automatically start:
- ✓ Checks if Docker is running
- ✓ Starts only required services (PostgreSQL, MySQL, Redis, MinIO, Jaeger, MailHog)
- ✓ Waits for services to be ready
- ✓ Displays connection URLs and credentials
- ✓ Starts your application
- ✓ Gracefully handles Docker not being available
Service Management Commands
bun run services:start # Start all services
bun run services:stop # Stop all services
bun run services:restart # Restart services
bun run services:ps # Show service status
bun run services:logs # View service logs
Available Services
| Service | When Started | Ports | Credentials |
|---|---|---|---|
| PostgreSQL | database: postgresql | 5432 | postgres / postgres |
| MySQL | database: mysql | 3306 | root / mysql |
| Redis | cache or queues enabled | 6379 | No password |
| MinIO | blobStorage: true | 9000, 9001 | minioadmin / minioadmin |
| Jaeger | telemetry: true | 16686, 4318 | No auth |
| MailHog | emailProvider: smtp | 1025, 8025 | No auth |
🚀 Deployment
Deploy your application to any of these platforms:
Fly.io
fly launch
fly secrets set JWT_SECRET="..."
fly deploy
Railway
railway init
railway add postgresql
railway up
Vercel
vercel
vercel env add JWT_SECRET
vercel --prod
Docker Self-Hosted
docker-compose up -d
Production Checklist
- ☐ Change JWT_SECRET to a strong random value
- ☐ Use PostgreSQL or MySQL instead of SQLite
- ☐ Set NODE_ENV=production
- ☐ Configure CORS for your domain
- ☐ Set up SSL/TLS
- ☐ Configure rate limiting
- ☐ Set up monitoring and logging
- ☐ Configure database backups
⌨️ Commands Reference
CLI Commands
ndts init [options]
Initialize a new project
-y, --yes - Skip prompts, use defaults
--no-git - Skip git initialization
--no-install - Skip dependency installation
ndts --version
Display the current version of ndts CLI
Development Commands
bun run dev # Start both server + client
bun run dev:server # Start only API server
bun run dev:client # Start only frontend
bun run build # Build for production
bun run start # Start production build
Database Commands
bun run db:generate # Generate migration from schema
bun run db:migrate # Run migrations
bun run db:studio # Open Drizzle Studio (GUI)
Service Commands
bun run services:start # Start Docker services
bun run services:stop # Stop Docker services
bun run services:restart # Restart services
bun run services:ps # Show service status
bun run services:logs # View service logs