Forge your next project with lightning-fast scaffolding. A pluggable CLI that transforms blank directories into production-ready codebases in seconds.
- Interactive CLI: Guided project creation with sensible defaults
- Plugin System: Extensible architecture for custom templates
- Configuration File: Register custom plugin directories via
.lbscaffold - Dry Run Mode: Preview what will be generated before committing
- Force Overwrite: Safely regenerate existing projects
- Built-in Templates: TypeScript libraries and more included
npm install -g @libria/scaffoldOr use with npx:
npx lb-scaffold createCreate a new project interactively:
lb-scaffold createYou'll be prompted for:
- Template choice (e.g.,
ts-lib) - Project name
- Additional template-specific options
- Whether to initialize git and install dependencies
Pass all options up-front for CI/CD or scripting:
lb-scaffold create -t ts-lib -n my-awesome-lib --dry-run| Option | Description | Default |
|---|---|---|
-t, --template <name> |
Template to use | (prompted) |
-n, --name <project-name> |
Name of the new project folder | (prompted, required) |
--dry-run |
Show what would be generated without writing files | false |
--force |
Overwrite existing project folder if it exists | false |
-i, --interactive |
Run in interactive mode | true |
Create a TypeScript library:
lb-scaffold create -t ts-lib -n my-utilsPreview generation without files:
lb-scaffold create -t ts-lib -n my-utils --dry-runForce overwrite an existing project:
lb-scaffold create -t ts-lib -n my-utils --forceA modern TypeScript library template with:
- ESLint + Prettier configuration
- Vitest for testing
- tsdown for fast builds
- TypeScript path aliases
- Package.json with proper exports
- Comprehensive README and LICENSE
A complete Angular application template using the official Angular CLI. Supports:
- Angular versions: Latest, 20, 19, 18, 17, 16
- Stylesheet formats: SCSS, CSS, Sass, Less
- Optional routing module
- Optional Server-Side Rendering (SSR)
- Git initialization (optional)
- Dependency installation (optional)
lb-scaffold create -t angular -n my-angular-appInteractive prompts:
- Angular version selection
- Stylesheet format (SCSS recommended)
- Add routing module?
- Enable SSR?
- Skip git initialization?
- Skip npm install?
A production-ready NestJS backend application using the official NestJS CLI. Includes:
- TypeScript with strict mode (optional)
- Package manager choice: npm, Yarn, or pnpm
- Controller, Service, and Module structure
- Unit test setup with Jest
- E2E test configuration
- Git initialization (optional)
- Dependency installation (optional)
lb-scaffold create -t nestjs -n my-nest-apiInteractive prompts:
- Package manager selection (npm, Yarn, pnpm)
- Enable strict TypeScript mode?
- Skip git initialization?
- Skip package installation?
The scaffold CLI supports a configuration file (.lbscaffold) that allows you to register custom plugin directories. This enables you to use your own templates alongside the built-in ones.
The CLI searches for .lbscaffold starting from the current directory and walking up the directory tree. This allows you to have project-specific or workspace-level configurations.
Initialize a new config file:
lb-scaffold config initThis creates a .lbscaffold file with a default plugin path:
{
"plugins": ["./plugins/**"]
}Add a custom plugin directory:
lb-scaffold config add ./my-templates/**Remove a plugin directory:
lb-scaffold config remove ./my-templates/**List all configured plugin patterns:
lb-scaffold config listShow the full config file:
lb-scaffold config showThe .lbscaffold config file is a JSON file with the following structure:
{
"plugins": [
"./plugins/**",
"./custom-templates/**",
"/absolute/path/to/plugins/**"
]
}The plugins array contains glob patterns pointing to directories containing template plugins. Paths can be:
- Relative: Resolved relative to the config file location
- Absolute: Used as-is
When a user plugin has the same name as a built-in plugin, the user plugin takes precedence. This allows you to customize or replace built-in templates.
-
Create a config file:
lb-scaffold config init
-
Add your custom templates directory:
lb-scaffold config add ./my-company-templates/** -
Create a template plugin in that directory (see Creating Custom Template Plugins)
-
Your template will now appear in the template selection:
lb-scaffold create
The scaffold CLI uses a plugin system powered by @libria/plugin-loader. Each template is a self-contained plugin.
templates/
└── my-template/
├── plugin.json # Plugin metadata
├── index.ts # Plugin entry point
├── types.ts # TypeScript types
├── my-template.ts # Implementation
└── files/ # Template files
├── package.json
├── tsconfig.json
└── src/
{
"name": "my-template",
"version": "1.0.0",
"type": "scaffold-template",
"main": "./index.ts",
"description": "My custom template"
}import { ScaffoldTemplatePluginOptions } from "@libria/scaffold";
export type MyTemplateOptions = ScaffoldTemplatePluginOptions & {
packageName: string;
description: string;
framework: 'react' | 'vue' | 'svelte';
};import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs-extra';
import { input, confirm } from '@inquirer/prompts';
import { definePlugin } from '@libria/plugin-loader';
import { SCAFFOLD_TEMPLATE_PLUGIN_TYPE, ScaffoldTemplatePlugin } from '@libria/scaffold';
import { MyTemplateOptions } from './types';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const FILES_DIR = path.resolve(__dirname, 'files');
export default definePlugin<ScaffoldTemplatePlugin>(
SCAFFOLD_TEMPLATE_PLUGIN_TYPE,
'my-template',
{
argument: 'my-template',
async execute(options: ScaffoldTemplatePluginOptions): Promise<void> {
// Collect user input
const userOptions = await getInitialOptions(options);
// Generate the project
await generateProject(userOptions);
// Post-processing
await postProcess(userOptions);
}
}
);
async function getInitialOptions(
options: ScaffoldTemplatePluginOptions
): Promise<MyTemplateOptions> {
const packageName = await input({
message: 'Package name:',
default: options.name,
});
const description = await input({
message: 'Description:',
});
const framework = await input({
message: 'Framework (react/vue/svelte):',
default: 'react',
});
return { packageName, description, framework, ...options };
}
async function generateProject(options: MyTemplateOptions): Promise<void> {
const { name, dryRun, force } = options;
const targetDir = path.resolve(process.cwd(), name);
// Handle existing directory
if (await fs.pathExists(targetDir)) {
if (!force) {
console.error(`Directory '${name}' already exists. Use --force to overwrite.`);
process.exit(1);
}
if (!dryRun) {
await fs.remove(targetDir);
}
}
// Create and copy files
if (!dryRun) {
await fs.ensureDir(targetDir);
await fs.copy(FILES_DIR, targetDir);
// Replace placeholders
await replacePlaceholders(targetDir, options);
}
console.log(`Project '${name}' created successfully!`);
}
async function replacePlaceholders(
targetDir: string,
options: MyTemplateOptions
): Promise<void> {
// Replace {PACKAGE_NAME}, {DESCRIPTION}, etc. in files
}
async function postProcess(options: MyTemplateOptions): Promise<void> {
// Git init, npm install, etc.
}export { default } from './my-template';
export * from './types';Use placeholders that will be replaced:
package.json:
{
"name": "{PACKAGE_NAME}",
"description": "{DESCRIPTION}",
"version": "1.0.0"
}npm run build:templatesThis compiles your template plugins to the dist/templates directory.
# Install dependencies
npm install
# Build the project
npm run build
# Build templates
npm run build:templates
# Run tests
npm test
# Lint and format
npm run cleanMIT - see LICENSE file for details