The @atlas/create-atlas-app package is a scaffolding tool that generates new Atlas services with all the necessary boilerplate, configuration, and best practices built-in.
# Interactive mode
pnpm create-atlas-app
# With app name
pnpm create-atlas-app my-serviceThe scaffolding tool:
- β Prompts for service configuration (name, description, port, database)
- β Generates complete service structure with all files
- β Creates Dockerfile and docker-compose.yml
- β Sets up TypeScript configuration
- β Adds example routes and tests
- β Configures database (optional)
- β Generates comprehensive README
- β Follows Atlas best practices
package.json- Dependencies and scriptstsconfig.json- TypeScript configurationtsconfig.test.json- Test TypeScript configurationvitest.config.ts- Vitest test configuration.env.example- Environment variable templateREADME.md- Service documentation
Dockerfile- Multi-stage Docker builddocker-compose.yml- Local development setup with PostgreSQL (if database included)
src/index.ts- Server entry pointsrc/app.ts- App configuration and route registrationsrc/env.ts- Environment variable validation with Zodsrc/generate-openapi.ts- OpenAPI specification generator
src/lib/create-app.ts- App factory with middleware setupsrc/lib/types.ts- TypeScript type definitionssrc/lib/constants.ts- Constants and error messages
src/middlewares/pino-logger.ts- Structured logging with Pino
src/routes/health.ts- Health check endpointsrc/routes/example/example.routes.ts- Example route definitionssrc/routes/example/example.handlers.ts- Example route handlerssrc/routes/example/example.index.ts- Example route registration
drizzle.config.ts- Drizzle ORM configurationsrc/db/index.ts- Database connectionsrc/db/schema.ts- Database schema with example tablesrc/db/migrate.ts- Migration runnersrc/db/seed.ts- Database seedersrc/db/migrations/- Migration files directory
test/{service-name}.spec.ts- Example test file
$ pnpm create-atlas-app
π Create Atlas App
? What is the name of your app? βΊ notifications-service
? App description: βΊ API service for sending notifications
? Default port: βΊ 3003
? Include PostgreSQL database setup? βΊ No
π¦ Creating app: notifications-service
β Files generated
β App created successfully!$ pnpm create-atlas-app
π Create Atlas App
? What is the name of your app? βΊ rides-service
? App description: βΊ API service for managing bicycle rides
? Default port: βΊ 3001
? Include PostgreSQL database setup? βΊ Yes
? Database name: βΊ rides_db
π¦ Creating app: rides-service
β Files generated
β App created successfully!$ pnpm create-atlas-app analytics-service
π Create Atlas App
? App description: βΊ API service for analytics and reporting
? Default port: βΊ 3004
? Include PostgreSQL database setup? βΊ Yes
? Database name: βΊ analytics_db
π¦ Creating app: analytics-service
β Files generated
β App created successfully!pnpm install# Start the service
pnpm --filter @atlas/your-service dev
# Or start all services
pnpm dev# Generate initial migration
pnpm --filter @atlas/your-service db:generate
# Run migrations
pnpm --filter @atlas/your-service db:migrate
# (Optional) Seed the database
pnpm --filter @atlas/your-service db:seedpnpm --filter @atlas/your-service testpnpm --filter @atlas/your-service generate-openapiEach generated service includes these scripts:
# Development
pnpm dev # Start dev server with hot reload
pnpm build # Build for production
pnpm start # Start production server
# Database (if included)
pnpm db:generate # Generate migrations from schema changes
pnpm db:migrate # Run migrations
pnpm db:studio # Open Drizzle Studio
pnpm db:seed # Seed database with sample data
# Testing & Quality
pnpm test # Run tests
pnpm test:watch # Run tests in watch mode
pnpm check-types # Type check without building
pnpm lint # Lint code
pnpm format # Format code
# OpenAPI
pnpm generate-openapi # Generate OpenAPI specificationAfter generating a service, you can customize:
- Create a new directory in
src/routes/ - Add route definitions, handlers, and index file
- Register in
src/app.ts
See docs/CREATE_NEW_SERVICE.md for detailed examples.
- Edit
src/db/schema.ts - Generate migration:
pnpm db:generate - Run migration:
pnpm db:migrate
- Update
src/env.tswith new Zod schema - Update
.env.example - Use in code:
import env from "./env.js"
- Create file in
src/middlewares/ - Register in
src/lib/create-app.ts
The generated service follows these patterns:
// src/lib/create-app.ts
export default function createApp() {
const app = new OpenAPIHono<AppBindings>({
strict: false,
defaultHook,
});
app.use(cors());
app.use(serveEmojiFavicon("π"));
app.use(createPinoLogger());
app.notFound(notFound);
app.onError(onError);
return app;
}// routes/example/example.routes.ts - Route definitions
export const list = createRoute({
path: "/examples",
method: "get",
responses: { ... },
});
// routes/example/example.handlers.ts - Business logic
export const list: AppRouteHandler<routes.ListRoute> = async (c) => {
return c.json([...]);
};
// routes/example/example.index.ts - Registration
const router = createRouter()
.openapi(routes.list, handlers.list);// src/env.ts
const EnvSchema = z.object({
NODE_ENV: z.string().default("development"),
PORT: z.coerce.number().default(3000),
// ...
});
export default EnvSchema.parse(process.env);// src/db/schema.ts
export const examples = pgTable("examples", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
});
export type Example = typeof examples.$inferSelect;
export type InsertExample = typeof examples.$inferInsert;The generated service includes:
- β Type Safety - TypeScript strict mode, Zod validation
- β OpenAPI Documentation - Auto-generated from route definitions
- β Structured Logging - Pino logger with context
- β Environment Validation - Zod schemas for env vars
- β Health Checks - Health endpoint with database check
- β Error Handling - Centralized error handling
- β Testing - Vitest setup with example tests
- β Docker - Multi-stage builds for optimization
- β Database Migrations - Drizzle Kit for schema management
- β Code Quality - Biome for linting and formatting
The generated service is automatically integrated with:
- β Turborepo - Build caching and task orchestration
- β pnpm Workspaces - Dependency management
- β
CI/CD - GitHub Actions with
--affectedflag - β Docker - Multi-stage builds using Turbo prune
- β Biome - Shared linting and formatting config
No additional configuration needed!
The tool checks if an app with the same name already exists. Choose a different name or remove the existing app.
App names must:
- Be lowercase
- Use hyphens for spaces (kebab-case)
- Contain only letters, numbers, and hyphens
- Not start or end with a hyphen
Examples:
- β
rides-service - β
user-auth - β
analytics-v2 - β
RidesService(uppercase) - β
rides_service(underscore) - β
-rides-service(starts with hyphen)
Make sure to run pnpm install from the monorepo root to install all dependencies.
Change the port in the service's .env file or when starting:
PORT=3005 pnpm --filter @atlas/your-service devTo customize the generated files:
- Edit files in
packages/create-atlas-app/src/generators/ - Update templates as needed
- Rebuild:
pnpm --filter @atlas/create-atlas-app build - Test by generating a new service
Create a new generator file:
// packages/create-atlas-app/src/generators/my-generator.ts
import type { AppConfig } from "../create-app.js";
export function generateMyFile(config: AppConfig): string {
return `// Generated file for ${config.displayName}`;
}Use in generators/index.ts:
import { generateMyFile } from "./my-generator.js";
export async function generateFiles(appPath: string, config: AppConfig) {
// ...
await fs.writeFile(
path.join(appPath, "my-file.ts"),
generateMyFile(config)
);
}- Creating a New Service - Detailed guide
- Documentation Summary - Complete documentation index
- Main README - Project overview