Programmatic API
Use Better-T-Stack programmatically in your Node.js applications
Overview
You can call Better-T-Stack directly from TypeScript/JavaScript without shelling out to the CLI.
The programmatic API is exported from create-better-t-stack and is designed for automation tools, internal generators, and scripted workflows.
Because it runs in silent mode by default, it also benefits from the same agent-safe behavior as create-json, including structured addon and database setup options.
Installation
npm i create-better-t-stackQuick Start
import { create } from "create-better-t-stack";
const result = await create("my-app", {
frontend: ["tanstack-router"],
backend: "hono",
database: "sqlite",
orm: "drizzle",
auth: "better-auth",
packageManager: "bun",
install: false,
dryRun: true,
});
result.match({
ok: (data) => {
console.log(`Project created at: ${data.projectDirectory}`);
console.log(`Reproducible command: ${data.reproducibleCommand}`);
},
err: (error) => {
console.error(`Failed: ${error.message}`);
},
});API Reference
create(projectName?, options?)
Create a new project.
function create(
projectName?: string,
options?: Partial<CreateInput>,
): Promise<Result<InitResult, CreateError>>;Notes:
- Uses the same option model as the CLI
createcommand (frontend,backend,database,orm,api,auth,addons, etc.). - Supports structured
addonOptionsanddbSetupOptions. - Supports
dryRunfor validation-only automation. - Runs in silent mode (no interactive prompts / no CLI UI output).
- Returns a
Result(ok/err) instead of exiting the process.
add(options?)
Add addons to an existing Better-T-Stack project.
function add(options?: {
addons?: Addons[];
addonOptions?: AddonOptions;
install?: boolean;
packageManager?: PackageManager;
projectDir?: string;
dryRun?: boolean;
}): Promise<AddResult | undefined>;Example:
import { add } from "create-better-t-stack";
const result = await add({
projectDir: "./my-app",
addons: ["biome", "mcp"],
addonOptions: {
mcp: {
scope: "project",
servers: ["context7"],
agents: ["cursor"],
},
},
install: true,
});
if (result?.success) {
console.log(`Added: ${result.addedAddons.join(", ")}`);
} else {
console.error(result?.error ?? "Failed to add addons");
}createVirtual(options)
Generate a project in memory without writing to disk.
import { createVirtual } from "create-better-t-stack";
const result = await createVirtual({
frontend: ["tanstack-router"],
backend: "hono",
database: "sqlite",
orm: "drizzle",
addonOptions: {
wxt: {
template: "react",
},
},
});This is useful for previews, tests, and web-based builders.
sponsors()
Show sponsors (same behavior as CLI command).
docs()
Open docs URL (same behavior as CLI command).
builder()
Open the web stack builder (same behavior as CLI command).
Result Types
InitResult (from create on ok)
type InitResult = {
success: boolean;
projectConfig: ProjectConfig;
reproducibleCommand: string;
timeScaffolded: string;
elapsedTimeMs: number;
projectDirectory: string;
relativePath: string;
error?: string;
};AddResult (from add)
type AddResult = {
success: boolean;
addedAddons: Addons[];
projectDir: string;
dryRun?: boolean;
plannedFileCount?: number;
error?: string;
};CreateError
create() can return these error types in Result.err(...):
UserCancelledErrorCLIErrorProjectCreationError
Error Handling Pattern
import { create } from "create-better-t-stack";
const result = await create("existing-dir", {
directoryConflict: "error",
});
if (result.isErr()) {
console.error(result.error.message);
process.exit(1);
}
console.log(result.value.projectDirectory);Mapping CLI to Programmatic
CLI:
create-better-t-stack my-app \
--frontend tanstack-router \
--backend hono \
--database postgres \
--orm drizzle \
--auth better-authProgrammatic:
const result = await create("my-app", {
frontend: ["tanstack-router"],
backend: "hono",
database: "postgres",
orm: "drizzle",
auth: "better-auth",
addonOptions: {
wxt: { template: "react" },
},
dbSetupOptions: {
mode: "manual",
},
});For the CLI-side JSON equivalents, see Agent Workflows.