CLI

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-stack

Quick 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 create command (frontend, backend, database, orm, api, auth, addons, etc.).
  • Supports structured addonOptions and dbSetupOptions.
  • Supports dryRun for 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(...):

  • UserCancelledError
  • CLIError
  • ProjectCreationError

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-auth

Programmatic:

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.

On this page