Programmatic API
Use Better-T-Stack programmatically in your Node.js applications
Overview
The Better-T-Stack CLI can be used programmatically in your Node.js applications, allowing you to create projects, add features, and manage configurations through JavaScript/TypeScript code instead of shell commands.
Installation
Install the package in your Node.js project:
npm install create-better-t-stack
# or
pnpm add create-better-t-stack
# or
bun add create-better-t-stack
Quick Start
Basic Project Creation
import { init } from "create-better-t-stack";
async function createProject() {
const result = await init("my-app", {
yes: true, // Use defaults, no prompts
frontend: ["tanstack-router"],
backend: "hono",
database: "sqlite",
orm: "drizzle",
auth: "better-auth",
packageManager: "bun",
install: false, // Don't install deps automatically
disableAnalytics: true, // Disable analytics
});
if (result.success) {
console.log(`✅ Project created at: ${result.projectDirectory}`);
console.log(`📝 Reproducible command: ${result.reproducibleCommand}`);
console.log(`⏱️ Time taken: ${result.elapsedTimeMs}ms`);
} else {
console.error(`❌ Failed: ${result.error}`);
}
}
createProject();
Directory Conflict Handling
import { init } from "create-better-t-stack";
const result = await init("existing-folder", {
yes: true,
directoryConflict: "increment", // Creates "existing-folder-1"
renderTitle: false, // Hide ASCII art
});
Disabling Analytics
You can disable analytics:
import { init } from "create-better-t-stack";
const result = await init("my-private-project", {
yes: true,
disableAnalytics: true, // No analytics data will be sent
frontend: ["tanstack-router"],
backend: "hono",
});
Note: Analytics help improve Better-T-Stack by providing insights into usage patterns. When disabled, no data is collected or transmitted.
API Reference
init(projectName?, options?)
Creates a new Better-T-Stack project.
Parameters:
projectName
(string, optional): Project name or directory pathoptions
(CreateInput, optional): Configuration options
Returns: Promise<InitResult>
Example:
const result = await init("my-project", {
frontend: ["next"],
backend: "hono",
database: "postgres",
orm: "drizzle"
});
sponsors()
Display Better-T-Stack sponsors (same as CLI).
Returns: Promise<void>
docs()
Open documentation in browser (same as CLI).
Returns: Promise<void>
builder()
Open web-based stack builder (same as CLI).
Returns: Promise<void>
Type Definitions
CreateInput
Configuration options for project creation:
interface CreateInput {
projectName?: string;
yes?: boolean; // Skip prompts, use defaults
yolo?: boolean; // Bypass validations (not recommended)
verbose?: boolean; // Show JSON result (CLI only, programmatic always returns result)
database?: Database; // "none" | "sqlite" | "postgres" | "mysql" | "mongodb"
orm?: ORM; // "none" | "drizzle" | "prisma" | "mongoose"
auth?: boolean; // Include authentication
frontend?: Frontend[]; // Array of frontend frameworks
addons?: Addons[]; // Array of addons
examples?: Examples[]; // Array of examples
git?: boolean; // Initialize git repo
packageManager?: PackageManager; // "npm" | "pnpm" | "bun"
install?: boolean; // Install dependencies
dbSetup?: DatabaseSetup; // Database hosting setup
backend?: Backend; // Backend framework
runtime?: Runtime; // Runtime environment
api?: API; // API type
webDeploy?: WebDeploy; // Web deployment setup
serverDeploy?: ServerDeploy; // Server deployment setup
directoryConflict?: DirectoryConflict; // "merge" | "overwrite" | "increment" | "error"
renderTitle?: boolean; // Show ASCII art title
disableAnalytics?: boolean; // Disable analytics and telemetry
}
InitResult
Result object returned by init()
:
interface InitResult {
success: boolean; // Whether operation succeeded
projectConfig: ProjectConfig; // Final project configuration
reproducibleCommand: string; // CLI command to recreate project
timeScaffolded: string; // ISO timestamp of creation
elapsedTimeMs: number; // Time taken in milliseconds
projectDirectory: string; // Absolute path to project
relativePath: string; // Relative path to project
error?: string; // Error message if failed
}
Configuration Options
Directory Conflict Resolution
Control how existing directories are handled:
// Merge with existing files (careful with conflicts)
directoryConflict: "merge"
// Completely overwrite existing directory
directoryConflict: "overwrite"
// Create new directory with incremented name (my-app-1)
directoryConflict: "increment"
// Throw error if directory exists
directoryConflict: "error"
Title Rendering
Control CLI output appearance:
// Hide ASCII art title (useful for automated scripts)
renderTitle: false
// Show ASCII art title (default)
renderTitle: true
YOLO Mode
Bypass validation checks (not recommended):
// Skip compatibility validations
yolo: true
Error Handling
The programmatic API uses different error handling than the CLI:
Directory Conflicts
Directory conflict errors return structured results instead of throwing:
const result = await init("existing-dir", {
directoryConflict: "error"
});
if (!result.success) {
console.log(result.error); // "Directory exists and is not empty..."
// Handle gracefully instead of process exit
}
Validation Errors
Validation errors still throw exceptions (maintains CLI compatibility):
try {
await init("test", {
database: "mongodb",
orm: "drizzle" // Invalid combination
});
} catch (error) {
console.error(error.message); // "MongoDB requires Mongoose or Prisma ORM"
}
Migration from CLI
CLI Command to Programmatic API
Convert CLI commands to programmatic calls:
# CLI Command
create-better-t-stack my-app \
--frontend tanstack-router \
--backend hono \
--database postgres \
--orm drizzle \
--auth better-auth \
--yes
// Programmatic Equivalent
const result = await init("my-app", {
frontend: ["tanstack-router"],
backend: "hono",
database: "postgres",
orm: "drizzle",
auth: "better-auth",
yes: true
});
Handling Prompts
CLI prompts become explicit options:
// Instead of interactive prompts, specify all options
const result = await init("my-app", {
yes: true, // Skip all prompts
frontend: ["tanstack-router"],
backend: "hono",
database: "postgres",
orm: "drizzle",
auth: "better-auth",
addons: ["biome", "turborepo"],
examples: ["todo"],
packageManager: "bun",
install: false,
git: true
});