Template
Generate files from Eta templates.
npm install @seedcli/templateThe standalone package exports named functions. Inside a Seed command, the same helpers are available on seed.template.*.
The template module uses Eta as its template engine — a TypeScript-native engine that's 3x faster than EJS with compatible syntax.
Generate a Single File
import { resolve } from 'node:path'
await seed.template.generate({
template: resolve('templates/component.ts.eta'),
target: resolve('src/components/Button.tsx'),
props: {
name: 'Button',
hasStyles: true,
},
})The template file at templates/component.ts.eta:
import React from 'react'
<% if (hasStyles) { %>
import styles from './<%= name %>.module.css'
<% } %>
export function <%= name %>() {
return <div<% if (hasStyles) { %> className={styles.root}<% } %>>
<%= name %>
</div>
}Generate Options
| Option | Type | Description |
|---|---|---|
template | string | Template file path (required) |
target | string | Absolute output file path (required) |
props | Record<string, unknown> | Template variables |
directory | string | Currently ignored by generate() |
overwrite | boolean | Overwrite existing files (default: false) |
Render to a File
Render a template string directly to a file:
await seed.template.render({
source: '<%= name %> v<%= version %>',
target: 'VERSION.txt',
props: { name: 'My App', version: '1.0.0' },
})Render Options
| Option | Type | Description |
|---|---|---|
source | string | Template string (required) |
target | string | Output file path (required) |
props | Record<string, unknown> | Template variables |
render() writes target directly and overwrites an existing file.
Render to String
Render a template and return the result without writing a file:
const result = await seed.template.renderString(
'Hello, <%= name %>!',
{ name: 'World' }
)
// => 'Hello, World!'Render a File to String
const result = await seed.template.renderFile(
'templates/readme.md.eta',
{ projectName: 'my-app', version: '1.0.0' }
)Scaffold a Directory
Copy and process an entire template directory:
await seed.template.directory({
source: 'templates/project',
target: 'my-new-project',
props: {
name: 'my-new-project',
author: 'John Doe',
useTypeScript: true,
},
ignore: ['node_modules/**', '.git/**'],
rename: {
'_package.json': 'package.json',
'_gitignore': '.gitignore',
},
})Directory Options
| Option | Type | Description |
|---|---|---|
source | string | Source template directory (required) |
target | string | Output directory (required) |
props | Record<string, unknown> | Template variables |
overwrite | boolean | Overwrite existing files |
ignore | string[] | Glob patterns to skip |
rename | Record<string, string> | Rename files during copy |
Files with .eta extension are processed as templates (extension is stripped). Other files are copied as-is.
Template Syntax
Eta uses a syntax similar to EJS:
| Syntax | Description |
|---|---|
<%= name %> | Output value (not escaped; this package sets autoEscape: false) |
<%~ html %> | Output raw value |
<% if (cond) { %> ... <% } %> | JavaScript logic |
<% for (const item of items) { %> ... <% } %> | Loops |
<%/* comment */%> | Comments (not output) |
Template variables are available both directly (name) and via it.name.
<% for (const field of fields) { %>
<%= field.name %>: <%= field.type %>;
<% } %>