Authoring

Creating Add-ons

Add-ons add files, dependencies, and code hooks to generated projects.

Use this guide when you want to build and maintain your own add-on outside the built-in catalog.

Quick Start

sh
# 1. Create base project
tanstack create my-addon-dev -y

# 2. Add your code
#    - src/integrations/my-feature/
#    - src/routes/demo/my-feature.tsx
#    - Update package.json

# 3. Extract add-on
tanstack add-on init

# 4. Edit .add-on/info.json

# 5. Compile
tanstack add-on compile

# Optional: continuously rebuild while authoring
tanstack add-on dev

# 6. Test locally
npx serve .add-on -l 9080
tanstack create test --add-ons http://localhost:9080/info.json

Structure

.add-on/
├── info.json        # Metadata (required)
├── package.json     # Dependencies (optional)
└── assets/          # Files to copy
    └── src/
        ├── integrations/my-feature/
        └── routes/demo/my-feature.tsx

Generated source of truth files in your project root:

  • .add-on/info.json - add-on metadata and integration config
  • .add-on/package.json - dependency/script additions merged into generated apps
  • .add-on/assets/** - template files copied into target apps

info.json

Required fields:

json
{
  "name": "My Feature",
  "version": "0.0.1",
  "description": "What it does",
  "type": "add-on",
  "phase": "add-on",
  "category": "tooling",
  "modes": ["file-router"]
}
FieldValues
versionSemantic version for your add-on metadata (e.g. 0.0.1)
typeadd-on, toolchain, deployment, example
phasesetup, add-on, example
categorytanstack, auth, database, orm, deploy, tooling, monitoring, api, i18n, cms, other

Optional fields:

json
{
  "dependsOn": ["tanstack-query"],
  "conflicts": ["other-feature"],
  "envVars": [{ "name": "API_KEY", "description": "...", "required": true }],
  "gitignorePatterns": ["*.cache"]
}

Hooks (Integrations)

Inject code into generated projects:

json
{
  "integrations": [
    {
      "type": "root-provider",
      "jsName": "MyProvider",
      "path": "src/integrations/my-feature/provider.tsx"
    }
  ]
}
TypeLocationUse
root-providerWraps app in __root.tsxContext providers
providerSame, but simplerBasic providers
vite-pluginvite.config.tsVite plugins
devtoolsAfter app in __root.tsxDevtools
header-userHeader componentUser menu, auth UI
layoutLayout wrapperDashboard layouts

Demo Routes

json
{
  "routes": [
    {
      "url": "/demo/my-feature",
      "name": "My Feature Demo",
      "path": "src/routes/demo/my-feature.tsx",
      "jsName": "MyFeatureDemo"
    }
  ]
}

Add-on Options

Let users configure the add-on:

json
{
  "options": {
    "database": {
      "type": "select",
      "label": "Database",
      "options": [
        { "value": "postgres", "label": "PostgreSQL" },
        { "value": "sqlite", "label": "SQLite" }
      ],
      "default": "postgres"
    }
  }
}

Access in EJS templates:

ejs
<% if (addOnOption['my-feature']?.database === 'postgres') { %>
// PostgreSQL code
<% } %>

EJS Templates

Files ending in .ejs are processed. Available variables:

VariableTypeDescription
projectNamestringProject name
typescriptbooleanTS enabled
tailwindbooleanTailwind enabled
addOnEnabledobject{ [id]: boolean }
addOnOptionobject{ [id]: options }

File patterns:

PatternResult
file.tsCopied as-is
file.ts.ejsEJS processed
_dot_gitignoreBecomes .gitignore
file.ts.appendAppended to existing

Distribution

Host on GitHub, npm, or any URL:

sh
tanstack create my-app --add-ons https://example.com/my-addon/info.json

Local Iteration Loop

Fastest way to iterate on a custom add-on:

sh
# in your add-on project
tanstack add-on compile
npx serve .add-on -l 9080

# in another terminal
tanstack create test-app --add-ons http://localhost:9080/info.json

If you are actively editing templates, run tanstack add-on dev to auto-refresh .add-on and add-on.json on file changes.

Publishing Tips

  • Keep add-on source in git (not just compiled output).
  • Re-run tanstack add-on compile after each metadata/template change.
  • Publish .add-on contents to a stable URL.
  • Prefer immutable/versioned URLs for production use.

Maintenance Checklist

When you update a custom add-on:

  1. Update templates or metadata in your source project.
  2. Re-run tanstack add-on compile.
  3. Test with a clean scaffold (tanstack create ... --add-ons <url>).
  4. Verify install/build/lint in the generated app.
  5. Publish updated .add-on assets.

Troubleshooting

  • Add-on not found: Verify URL points directly to info.json.
  • Template not applied: Ensure file is in .add-on/assets and ends with .ejs if templated.
  • Option not taking effect: Confirm option key matches addOnOption['<id>'] usage in template.
  • Integration code not injected: Check integrations[].type, jsName, and path in .add-on/info.json.