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.

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,
});

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.).
  • 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[];
  install?: boolean;
  packageManager?: PackageManager;
  projectDir?: string;
}): Promise<AddResult | undefined>;

Example:

import { add } from "create-better-t-stack";

const result = await add({
  projectDir: "./my-app",
  addons: ["biome", "mcp"],
  install: true,
});

if (result?.success) {
  console.log(`Added: ${result.addedAddons.join(", ")}`);
} else {
  console.error(result?.error ?? "Failed to add addons");
}

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;
  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",
});

On this page