
Code Generation Template
- 485 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
code-generation-template is an agent skill that guides developers through template engines, AST manipulation, scaffolding, and boilerplate generation so AI assistants produce consistent, reusable code instead of one-off
About
code-generation-template is a Claude Code skill from aj-geddes/useful-ai-prompts that documents code generation techniques including template engines, AST-based transforms, project scaffolding, and automated boilerplate workflows. The skill bundles reference guides, quick-start steps, and best practices for when agents generate modules, CRUD layers, API stubs, or full project skeletons from repeatable patterns. Developers reach for code-generation-template when repetitive structure work slows feature delivery or when prompts produce inconsistent file layouts across runs. It pairs naturally with scaffolding tasks in TypeScript, Python, or polyglot repos where pattern reuse beats hand-writing every file. The README positions it for generating code, scaffolding projects, creating boilerplate, and operating template engines during active build work.
- Supports scaffolding new projects and components
- Automates repetitive boilerplate and CRUD operations
- Generates API clients from OpenAPI specs and TypeScript types from JSON Schema
- Includes AST-based generation and multiple template engines
- Provides 8 distinct code-generation use cases with ready-to-use patterns
Code Generation Template by the numbers
- 485 all-time installs (skills.sh)
- Ranked #1,801 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill code-generation-templateAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 485 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
How do you scaffold code with reusable templates?
Generate consistent, high-quality code from reusable templates and patterns instead of writing everything from scratch.
Who is it for?
Developers who want AI agents to emit consistent scaffolding and boilerplate from documented template and AST patterns.
Skip if: Teams that only need a single hand-written function fix with no scaffolding, templates, or repeatable generation workflow.
When should I use this skill?
The user asks to scaffold a project, generate boilerplate, use a template engine, or apply AST-based code generation.
What you get
Scaffolded project files, boilerplate modules, AST-generated snippets, and template-driven code structures ready for review.
- scaffolded files
- boilerplate modules
- template-driven code snippets
Files
Code Generation & Templates
Table of Contents
Overview
Comprehensive guide to code generation techniques including template engines, AST manipulation, code scaffolding, and automated boilerplate generation for increased productivity and consistency.
When to Use
- Scaffolding new projects or components
- Generating repetitive boilerplate code
- Creating CRUD operations automatically
- Generating API clients from OpenAPI specs
- Building code from templates
- Creating database models from schemas
- Generating TypeScript types from JSON Schema
- Building custom CLI generators
Quick Start
Minimal working example:
// templates/component.hbs
import React from 'react';
export interface {{pascalCase name}}Props {
{{#each props}}
{{this.name}}{{#if this.optional}}?{{/if}}: {{this.type}};
{{/each}}
}
export const {{pascalCase name}}: React.FC<{{pascalCase name}}Props> = ({
{{#each props}}{{this.name}},{{/each}}
}) => {
return (
<div className="{{kebabCase name}}">
{/* Component implementation */}
</div>
);
};Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Template Engines | Template Engines |
| AST-Based Code Generation | AST-Based Code Generation |
| Project Scaffolding | Project Scaffolding |
| OpenAPI Client Generation | OpenAPI Client Generation |
| Database Model Generation | Database Model Generation |
| GraphQL Code Generation | GraphQL Code Generation |
| Plop.js Generator | Plop.js Generator |
Best Practices
✅ DO
- Use templates for repetitive code patterns
- Generate TypeScript types from schemas
- Include tests in generated code
- Follow project conventions in templates
- Add comments to explain generated code
- Version control your templates
- Make templates configurable
- Generate documentation alongside code
- Validate inputs before generating
- Use consistent naming conventions
- Keep templates simple and maintainable
- Provide CLI for easy generation
❌ DON'T
- Over-generate (avoid unnecessary complexity)
- Generate code that's hard to maintain
- Forget to validate generated code
- Hardcode values in templates
- Generate code without documentation
- Create generators for one-off use cases
- Mix business logic in templates
- Generate code without formatting
- Skip error handling in generators
- Create overly complex templates
AST-Based Code Generation
AST-Based Code Generation
Using Babel/TypeScript AST
// ast-generator.ts
import * as ts from "typescript";
export class TypeScriptGenerator {
// Generate interface
generateInterface(
name: string,
properties: Array<{ name: string; type: string; optional?: boolean }>,
) {
const members = properties.map((prop) =>
ts.factory.createPropertySignature(
undefined,
ts.factory.createIdentifier(prop.name),
prop.optional
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
: undefined,
ts.factory.createTypeReferenceNode(prop.type),
),
);
const interfaceDecl = ts.factory.createInterfaceDeclaration(
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
ts.factory.createIdentifier(name),
undefined,
undefined,
members,
);
return this.printNode(interfaceDecl);
}
// Generate class
generateClass(
name: string,
properties: Array<{ name: string; type: string }>,
) {
const propertyDecls = properties.map((prop) =>
ts.factory.createPropertyDeclaration(
[ts.factory.createToken(ts.SyntaxKind.PrivateKeyword)],
ts.factory.createIdentifier(prop.name),
undefined,
ts.factory.createTypeReferenceNode(prop.type),
undefined,
),
);
const constructor = ts.factory.createConstructorDeclaration(
undefined,
properties.map((prop) =>
ts.factory.createParameterDeclaration(
undefined,
undefined,
ts.factory.createIdentifier(prop.name),
undefined,
ts.factory.createTypeReferenceNode(prop.type),
),
),
ts.factory.createBlock(
properties.map((prop) =>
ts.factory.createExpressionStatement(
ts.factory.createBinaryExpression(
ts.factory.createPropertyAccessExpression(
ts.factory.createThis(),
prop.name,
),
ts.SyntaxKind.EqualsToken,
ts.factory.createIdentifier(prop.name),
),
),
),
true,
),
);
const classDecl = ts.factory.createClassDeclaration(
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
ts.factory.createIdentifier(name),
undefined,
undefined,
[...propertyDecls, constructor],
);
return this.printNode(classDecl);
}
private printNode(node: ts.Node): string {
const sourceFile = ts.createSourceFile(
"temp.ts",
"",
ts.ScriptTarget.Latest,
false,
ts.ScriptKind.TS,
);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
}
}
// Usage
const generator = new TypeScriptGenerator();
const interfaceCode = generator.generateInterface("User", [
{ name: "id", type: "string" },
{ name: "email", type: "string" },
{ name: "name", type: "string", optional: true },
]);
const classCode = generator.generateClass("UserService", [
{ name: "repository", type: "UserRepository" },
{ name: "logger", type: "Logger" },
]);Database Model Generation
Database Model Generation
// prisma-schema-generator.ts
export class PrismaSchemaGenerator {
generateModel(table: DatabaseTable): string {
return `model ${pascalCase(table.name)} {
${table.columns.map((col) => this.generateField(col)).join("\n")}
${this.generateRelations(table.relations)}
${this.generateIndexes(table.indexes)}
}
`;
}
private generateField(column: Column): string {
const optional = !column.required ? "?" : "";
const unique = column.unique ? " @unique" : "";
const defaultValue = column.default ? ` @default(${column.default})` : "";
return ` ${column.name} ${this.mapType(column.type)}${optional}${unique}${defaultValue}`;
}
private mapType(sqlType: string): string {
const typeMap: Record<string, string> = {
varchar: "String",
text: "String",
integer: "Int",
bigint: "BigInt",
boolean: "Boolean",
timestamp: "DateTime",
date: "DateTime",
json: "Json",
};
return typeMap[sqlType.toLowerCase()] || "String";
}
private generateRelations(relations: Relation[]): string {
return relations
.map((rel) => {
if (rel.type === "hasMany") {
return ` ${rel.name} ${rel.model}[]`;
} else if (rel.type === "belongsTo") {
return ` ${rel.name} ${rel.model} @relation(fields: [${rel.foreignKey}], references: [id])`;
}
return "";
})
.join("\n");
}
}GraphQL Code Generation
GraphQL Code Generation
// graphql-codegen.config.ts
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "http://localhost:4000/graphql",
documents: ["src/**/*.tsx", "src/**/*.ts"],
generates: {
"./src/generated/graphql.ts": {
plugins: [
"typescript",
"typescript-operations",
"typescript-react-apollo",
],
config: {
withHooks: true,
withComponent: false,
withHOC: false,
},
},
"./src/generated/introspection.json": {
plugins: ["introspection"],
},
},
};
export default config;OpenAPI Client Generation
OpenAPI Client Generation
// openapi-client-generator.ts
import SwaggerParser from "@apidevtools/swagger-parser";
import { compile } from "json-schema-to-typescript";
export class OpenAPIClientGenerator {
async generate(specPath: string, outputDir: string) {
const api = await SwaggerParser.parse(specPath);
// Generate TypeScript types from schemas
if (api.components?.schemas) {
for (const [name, schema] of Object.entries(api.components.schemas)) {
const ts = await compile(schema as any, name, {
bannerComment: "",
});
await fs.writeFile(path.join(outputDir, "types", `${name}.ts`), ts);
}
}
// Generate API client methods
for (const [path, pathItem] of Object.entries(api.paths)) {
for (const [method, operation] of Object.entries(pathItem)) {
if (["get", "post", "put", "delete", "patch"].includes(method)) {
const clientMethod = this.generateClientMethod(
method,
path,
operation as any,
);
// Write to file...
}
}
}
}
private generateClientMethod(
method: string,
path: string,
operation: any,
): string {
const functionName =
operation.operationId || this.pathToFunctionName(method, path);
const parameters = operation.parameters || [];
return `
async ${functionName}(${this.generateParameters(parameters)}): Promise<${this.getResponseType(operation)}> {
const response = await this.request('${method.toUpperCase()}', '${path}', {
${this.generateRequestOptions(parameters)}
});
return response.json();
}
`;
}
private generateParameters(parameters: any[]): string {
return parameters
.map(
(p) =>
`${p.name}${p.required ? "" : "?"}: ${this.schemaToType(p.schema)}`,
)
.join(", ");
}
private getResponseType(operation: any): string {
const successResponse =
operation.responses["200"] || operation.responses["201"];
if (!successResponse) return "any";
const schema = successResponse.content?.["application/json"]?.schema;
return schema ? this.schemaToType(schema) : "any";
}
private schemaToType(schema: any): string {
if (schema.$ref) {
return schema.$ref.split("/").pop();
}
if (schema.type === "string") return "string";
if (schema.type === "number" || schema.type === "integer") return "number";
if (schema.type === "boolean") return "boolean";
if (schema.type === "array") return `${this.schemaToType(schema.items)}[]`;
return "any";
}
private pathToFunctionName(method: string, path: string): string {
const cleanPath = path
.replace(/\{.*?\}/g, "By")
.replace(/[^a-zA-Z0-9]/g, "");
return `${method}${cleanPath}`;
}
}Plop.js Generator
Plop.js Generator
// plopfile.ts
import { NodePlopAPI } from "plop";
export default function (plop: NodePlopAPI) {
// Component generator
plop.setGenerator("component", {
description: "React component",
prompts: [
{
type: "input",
name: "name",
message: "Component name:",
},
{
type: "list",
name: "type",
message: "Component type:",
choices: ["functional", "class"],
},
],
actions: [
{
type: "add",
path: "src/components/{{pascalCase name}}/{{pascalCase name}}.tsx",
templateFile: "templates/component.hbs",
},
{
type: "add",
path: "src/components/{{pascalCase name}}/{{pascalCase name}}.test.tsx",
templateFile: "templates/component.test.hbs",
},
{
type: "add",
path: "src/components/{{pascalCase name}}/index.ts",
template:
"export { {{pascalCase name}} } from './{{pascalCase name}}';\n",
},
],
});
// API generator
plop.setGenerator("api", {
description: "API endpoint with full stack",
prompts: [
{
type: "input",
name: "name",
message: "Resource name (e.g., user, post):",
},
],
actions: [
{
type: "add",
path: "src/models/{{kebabCase name}}.model.ts",
templateFile: "templates/model.hbs",
},
{
type: "add",
path: "src/services/{{kebabCase name}}.service.ts",
templateFile: "templates/service.hbs",
},
{
type: "add",
path: "src/controllers/{{kebabCase name}}.controller.ts",
templateFile: "templates/controller.hbs",
},
{
type: "add",
path: "src/routes/{{kebabCase name}}.routes.ts",
templateFile: "templates/routes.hbs",
},
],
});
}Project Scaffolding
Project Scaffolding
Simple CLI Generator
// cli/generate.ts
#!/usr/bin/env node
import { Command } from 'commander';
import inquirer from 'inquirer';
import fs from 'fs-extra';
import path from 'path';
const program = new Command();
program
.name('generate')
.description('Code generator CLI')
.version('1.0.0');
program
.command('component <name>')
.description('Generate a React component')
.option('-d, --dir <directory>', 'Output directory', 'src/components')
.action(async (name, options) => {
const answers = await inquirer.prompt([
{
type: 'list',
name: 'type',
message: 'Component type?',
choices: ['functional', 'class']
},
{
type: 'confirm',
name: 'typescript',
message: 'Use TypeScript?',
default: true
},
{
type: 'confirm',
name: 'test',
message: 'Generate test file?',
default: true
}
]);
await generateComponent(name, options.dir, answers);
});
program
.command('api <resource>')
.description('Generate API endpoint with controller, service, and model')
.action(async (resource) => {
await generateApiResource(resource);
});
program.parse();
async function generateComponent(name: string, dir: string, options: any) {
const componentName = pascalCase(name);
const ext = options.typescript ? 'tsx' : 'jsx';
const template = options.type === 'functional'
? getFunctionalComponentTemplate(componentName, options.typescript)
: getClassComponentTemplate(componentName, options.typescript);
const componentPath = path.join(dir, `${componentName}.${ext}`);
await fs.ensureDir(dir);
await fs.writeFile(componentPath, template);
console.log(`✓ Created ${componentPath}`);
if (options.test) {
const testTemplate = getTestTemplate(componentName, options.typescript);
const testPath = path.join(dir, `${componentName}.test.${ext}`);
await fs.writeFile(testPath, testTemplate);
console.log(`✓ Created ${testPath}`);
}
}
function getFunctionalComponentTemplate(name: string, ts: boolean): string {
if (ts) {
return `import React from 'react';
export interface ${name}Props {
// Add props here
}
export const ${name}: React.FC<${name}Props> = (props) => {
return (
<div className="${kebabCase(name)}">
<h1>${name}</h1>
</div>
);
};
`;
}
return `import React from 'react';
export const ${name} = (props) => {
return (
<div className="${kebabCase(name)}">
<h1>${name}</h1>
</div>
);
};
`;
}
async function generateApiResource(resource: string) {
const name = pascalCase(resource);
// Generate model
const modelCode = `export interface ${name} {
id: string;
createdAt: Date;
updatedAt: Date;
// Add fields here
}
`;
await fs.writeFile(`src/models/${kebabCase(resource)}.model.ts`, modelCode);
// Generate service
const serviceCode = `import { ${name} } from '../models/${kebabCase(resource)}.model';
export class ${name}Service {
async findAll(): Promise<${name}[]> {
// Implement
return [];
}
async findById(id: string): Promise<${name} | null> {
// Implement
return null;
}
async create(data: Partial<${name}>): Promise<${name}> {
// Implement
throw new Error('Not implemented');
}
async update(id: string, data: Partial<${name}>): Promise<${name}> {
// Implement
throw new Error('Not implemented');
}
async delete(id: string): Promise<void> {
// Implement
}
}
`;
await fs.writeFile(`src/services/${kebabCase(resource)}.service.ts`, serviceCode);
// Generate controller
const controllerCode = `import { Router } from 'express';
import { ${name}Service } from '../services/${kebabCase(resource)}.service';
const router = Router();
const service = new ${name}Service();
router.get('/', async (req, res) => {
const items = await service.findAll();
res.json(items);
});
router.get('/:id', async (req, res) => {
const item = await service.findById(req.params.id);
if (!item) return res.status(404).json({ error: 'Not found' });
res.json(item);
});
router.post('/', async (req, res) => {
const item = await service.create(req.body);
res.status(201).json(item);
});
router.put('/:id', async (req, res) => {
const item = await service.update(req.params.id, req.body);
res.json(item);
});
router.delete('/:id', async (req, res) => {
await service.delete(req.params.id);
res.status(204).send();
});
export default router;
`;
await fs.writeFile(`src/controllers/${kebabCase(resource)}.controller.ts`, controllerCode);
console.log(`✓ Generated API resource: ${name}`);
}Template Engines
Template Engines
Handlebars Templates
// templates/component.hbs
import React from 'react';
export interface {{pascalCase name}}Props {
{{#each props}}
{{this.name}}{{#if this.optional}}?{{/if}}: {{this.type}};
{{/each}}
}
export const {{pascalCase name}}: React.FC<{{pascalCase name}}Props> = ({
{{#each props}}{{this.name}},{{/each}}
}) => {
return (
<div className="{{kebabCase name}}">
{/* Component implementation */}
</div>
);
};// generator.ts
import Handlebars from "handlebars";
import fs from "fs";
// Register helpers
Handlebars.registerHelper("pascalCase", (str: string) =>
str.replace(
/(\w)(\w*)/g,
(_, first, rest) => first.toUpperCase() + rest.toLowerCase(),
),
);
Handlebars.registerHelper("kebabCase", (str: string) =>
str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
);
// Load template
const templateSource = fs.readFileSync("templates/component.hbs", "utf8");
const template = Handlebars.compile(templateSource);
// Generate code
const code = template({
name: "userProfile",
props: [
{ name: "userId", type: "string", optional: false },
{ name: "onUpdate", type: "() => void", optional: true },
],
});
fs.writeFileSync("src/components/UserProfile.tsx", code);EJS Templates
// templates/api-endpoint.ejs
import { Router } from 'express';
import { <%= modelName %>Service } from '../services/<%= kebabCase(modelName) %>.service';
const router = Router();
const service = new <%= modelName %>Service();
// GET /<%= pluralize(kebabCase(modelName)) %>
router.get('/', async (req, res) => {
try {
const items = await service.findAll();
res.json(items);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// GET /<%= pluralize(kebabCase(modelName)) %>/:id
router.get('/:id', async (req, res) => {
try {
const item = await service.findById(req.params.id);
if (!item) {
return res.status(404).json({ error: 'Not found' });
}
res.json(item);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// POST /<%= pluralize(kebabCase(modelName)) %>
router.post('/', async (req, res) => {
try {
const item = await service.create(req.body);
res.status(201).json(item);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
export default router;// Using EJS
import ejs from "ejs";
const code = await ejs.renderFile("templates/api-endpoint.ejs", {
modelName: "User",
kebabCase: (str: string) =>
str
.replace(/([A-Z])/g, "-$1")
.toLowerCase()
.slice(1),
pluralize: (str: string) => str + "s",
});#!/bin/bash
# validate-api.sh - Validate API specification
# Usage: ./validate-api.sh <openapi_spec>
set -euo pipefail
SPEC_FILE="${{1:?Usage: $0 <openapi_spec>}}"
echo "Validating API spec: $SPEC_FILE"
# TODO: Add API validation
# - Validate OpenAPI/Swagger syntax
# - Check endpoint naming conventions
# - Verify response schemas
# - Check for required headers
# - Validate authentication definitions
echo "API validation complete."
# API Endpoint Scaffold
# TODO: Customize for your API framework
openapi: "3.0.3"
info:
title: "API Service"
version: "1.0.0"
paths:
/api/v1/resource:
get:
summary: "List resources"
# TODO: Define parameters and responses
responses:
"200":
description: "Success"
post:
summary: "Create resource"
# TODO: Define request body and responses
responses:
"201":
description: "Created"
Related skills
How it compares
Pick code-generation-template when the goal is repeatable scaffolding and pattern-driven generation rather than optimizing or reviewing existing production code.
FAQ
What does code-generation-template cover?
code-generation-template covers template engines, AST manipulation, code scaffolding, and automated boilerplate generation. The skill includes overview, quick start, reference guides, and best practices for agent-assisted code output.
When should developers use code-generation-template?
Developers should use code-generation-template when generating code, scaffolding projects, creating boilerplate, or working with template engines. The skill is invoked during active implementation when repetitive structure must stay consistent.