duck template

Fast, customizable Rust-powered project scaffolding — because smart devs don’t start from scratch.

Features

  • Template-based scaffolding using JSON
  • Variants for different project layouts (api, web, cli, etc.)
  • Local or remote configs (URL or file path)
  • Unified flag parsing with dynamic injection into templates
  • Blazing fast — written in Rust
  • Modular commands: init, create, and create-variant

Installation

cargo install duck-template
cargo install duck-template

Quick Start

Initialize a New Project

duck-template init --name my-app
duck-template init --name my-app

This will:

  • Create a directory my-app/
  • Inject the project name into template files
  • Use your local duck-template.json

Create From a Variant

duck-template create --variant api --config ./duck-template.json
duck-template create --variant api --config ./duck-template.json

With a remote config:

duck-template create --variant api --config https://example.com/template.json
duck-template create --variant api --config https://example.com/template.json

With extra arguments:

duck-template create \
  --variant cli \
  --config ./template.json \
  --outdir ./output \
  --args author=Ahmed,year=2025
duck-template create \
  --variant cli \
  --config ./template.json \
  --outdir ./output \
  --args author=Ahmed,year=2025

Create a New Variant

duck-template create-variant \
  --source ./template-source \
  --name cli \
  --description "Command-line app setup" \
  --config ./duck-template.json
duck-template create-variant \
  --source ./template-source \
  --name cli \
  --description "Command-line app setup" \
  --config ./duck-template.json

This will:

  • Package the folder into a new variant
  • Append it to the config (if valid and writable)

Configuration Format

Templates are defined in a duck-template.json file:

{
  "$schema": "https://zpgqhogoevbgpxustvmo.supabase.co/storage/v1/object/public/json/duck-template-schema.json",
  "name": "my-template",
  "version": "1.0.0",
  "description": "Reusable project setup",
  "outdir": "./output",
  "args": {
    "author": "Anonymous",
    "license": "MIT"
  },
  "variants": [
    {
      "name": "api",
      "description": "Express API starter",
      "files": [
        { "path": "src/index.ts", "content": "console.log('API ready');" },
        { "path": "tsconfig.json", "template": "tsconfig-template.json" }
      ]
    }
  ]
}
{
  "$schema": "https://zpgqhogoevbgpxustvmo.supabase.co/storage/v1/object/public/json/duck-template-schema.json",
  "name": "my-template",
  "version": "1.0.0",
  "description": "Reusable project setup",
  "outdir": "./output",
  "args": {
    "author": "Anonymous",
    "license": "MIT"
  },
  "variants": [
    {
      "name": "api",
      "description": "Express API starter",
      "files": [
        { "path": "src/index.ts", "content": "console.log('API ready');" },
        { "path": "tsconfig.json", "template": "tsconfig-template.json" }
      ]
    }
  ]
}

Command Reference

init — Create a New Project Directory

duck-template init --name my-app
duck-template init --name my-app
FlagDescription
-n, --nameProject name (used for folder name and inside templates).

create — Generate Files from a Variant

duck-template create --variant api --config ./config.json
duck-template create --variant api --config ./config.json
FlagDescription
-v, --variantName of the variant to generate
-d, --outdirOutput directory (defaults to ./)
-c, --configLocal or remote JSON config
-a, --argsKey=value overrides for template variables (author=Ahmed)

create-variant — Package a Folder into a Variant

duck-template create-variant \
  --source ./starter \
  --name basic \
  --description "Basic setup" \
  --config ./duck-template.json
duck-template create-variant \
  --source ./starter \
  --name basic \
  --description "Basic setup" \
  --config ./duck-template.json
FlagDescription
-s, --sourceSource directory or file
-n, --nameUnique name for the variant
-d, --descriptionShort description of the variant
-c, --configOptional path to an existing config to update

Output Example

Given:

duck-template init --name wiseman
duck-template init --name wiseman

With config:

{
  "name": "wiseman",
  "outdir": "./output",
  "variants": [
    {
      "name": "wiseman",
      "files": [
        { "path": "src/main.ts", "content": "console.log('{{name}} is wise');" }
      ]
    }
  ]
}
{
  "name": "wiseman",
  "outdir": "./output",
  "variants": [
    {
      "name": "wiseman",
      "files": [
        { "path": "src/main.ts", "content": "console.log('{{name}} is wise');" }
      ]
    }
  ]
}

Result:

output/
└── src/
    └── main.ts   // console.log("wiseman is wise");

Help & Version

duck-template --help
duck-template --version
duck-template --help
duck-template --version

Also works with subcommands:

duck-template init --help
duck-template create-variant --help
duck-template init --help
duck-template create-variant --help

Contributions

Pull requests, issues, and suggestions are welcome! Fork, tweak, and share your own templates.


🦆 duck-templatesmart scaffolding for smart developers.