@mariozechner/create-app
v1.0.11
Published
Project scaffolding for TypeScript applications and libraries
Maintainers
Readme
Create App
CLI for creating deployable web applications with Docker, Caddy, and modern tooling.
Why This Exists
Self-hosting web applications shouldn't require complex infrastructure. This CLI creates apps that deploy to a single server with automatic SSL and dev/prod parity - simple, reliable hosting on your own or rented hardware.
Perfect for:
- Personal projects - blogs, portfolios, side projects
- Small businesses - company websites, internal tools
- Prototypes - MVPs that need real deployment
- Learning - because it's fun to run your own infra stack
Not suitable for:
- High-scale applications (use Kubernetes/cloud platforms)
- Multi-region deployments (single server architecture)
- Complex microservices (better served by orchestration platforms)
Quick Start
Interactive Setup
# Create a new app (prompts for template and configuration)
npx @mariozechner/create-app my-app
cd my-app
# Start development server
./run.sh dev
# Deploy to your server (see Server section below)
./run.sh deployCLI Arguments (No Prompts)
# Create with all options specified
npx @mariozechner/create-app my-app \
--template spa-api \
--domain myapp.com \
--server myserver.hetzner.de \
--serverDir /home/username
# Quick static site
npx @mariozechner/create-app my-blog --template static --domain blog.example.com
# See all options
npx @mariozechner/create-app --helpTemplates
Available Templates
Static
- Description: Static file server with modern frontend tooling
- Features:
- Tailwind CSS 4 with live reload
- TypeScript support
- Automated testing setup
- Optimized production builds
- Use for: Landing pages, documentation sites, blogs, portfolios
SPA + API
- Description: Single Page Application with backend API
- Inherits: All features from the Static template
- Additional Features:
- Express.js backend API
- Frontend/backend code sharing
- API proxy in development
- Separate frontend/backend builds
- Use for: Web apps, internal tools, data-driven applications
Web Library
- Description: TypeScript library for the browser
- Features:
- ESM output with source maps
- TypeScript declarations
- Hot-reload development server with @mariozechner/hotserve
- Prettier formatting + Biome linting
- Publishing script included
- Use for: Browser libraries, web components, frontend utilities
Node Library
- Description: TypeScript library for Node.js with CLI support
- Features:
- ESM output with TypeScript declarations
- CLI executable support
- Prettier formatting + Biome linting
- Publishing script included
- Use for: Node.js libraries, CLI tools, backend utilities
Prerequisites
Server Setup
Your production server needs Docker, Caddy, and proper configuration. See SERVER.md for complete setup instructions.
DNS Configuration
Point your domain to the server:
A yourdomain.com -> server-ip
A *.yourdomain.com -> server-ip (for subdomains)Usage
CLI Options
| Option | Short | Description | Example |
|--------|-------|-------------|---------|
| --template | -t | Template to use | --template spa-api |
| --domain | | Domain for the app | --domain myapp.com |
| --server | | Production server hostname | --server myserver.com |
| --serverDir | | Server directory path | --serverDir /home/username |
| --frontendPort | | Frontend development port | --frontendPort 3000 |
| --apiPort | | API development port | --apiPort 8000 |
| --help | -h | Show help message | --help |
Available templates: static, spa-api, web-library, node-library
Template-Specific Instructions
After creating a project, check the generated README.md for detailed instructions specific to your template.
npx @mariozechner/create-app my-blog
cd my-blog
cat README.md # Template-specific instructionsDevelopment
Working on the CLI
To work on this CLI tool itself:
git clone https://github.com/badlogic/create-app
cd create-app
npm install
npx tsx src/cli.ts test-appTemplate System
The template system supports inheritance and file transformations, making it easy to create and maintain templates.
Template Structure
Each template is a directory in templates/ containing:
template.json- Template metadata and configuration- Template files and directories
- Special filename prefixes for transformations:
+filename- File will be merged with inherited file (JSON/YAML only)-filename- Marks a file/directory for deletion from inherited template- Regular files - Replace inherited files or create new ones
Creating a New Template
- Create a new directory in
templates/:
mkdir templates/my-template- Add
template.json:
{
"name": "My Template",
"description": "Description of what this template creates",
"prompts": [
{
"name": "domain",
"type": "text",
"message": "Domain (e.g. myapp.com)"
}
]
}- Add your template files with proper structure:
templates/my-template/
├── template.json
├── package.json
├── src/
│ └── index.ts
└── infra/
├── Caddyfile
└── docker-compose.ymlTemplate Inheritance
Templates can inherit from other templates using the inherits field:
{
"name": "Extended Template",
"description": "Builds on the static template",
"inherits": ["static"],
"prompts": [...]
}Inheritance rules:
- Files from parent templates are copied first
- Child template files override parent files with the same path
- Files prefixed with
+are merged with parent files (JSON/YAML only) - Files prefixed with
-delete the corresponding file from parent - Multiple inheritance is processed in order
Example: The spa-api template inherits from static and:
- Keeps all static template files (frontend build, testing, etc.)
- Adds
+package.jsonto merge additional dependencies - Adds
+docker-compose.ymlto extend Docker services - Adds new files like
src/backend/server.ts - Could use
-README.mdto remove the parent's README (if needed)
File Merging
Files prefixed with + are intelligently merged based on their type:
- JSON files (
+package.json): Deep merged with parent - YAML files (
+docker-compose.yml): Deep merged with special handling for arrays - Other files: Not supported for merging (warning shown)
Example +package.json in child template:
{
"scripts": {
"build:backend": "tsup"
},
"dependencies": {
"express": "^4.18.0"
}
}This will merge with the parent's package.json, adding new scripts and dependencies.
File Deletion
Files or directories prefixed with - mark items for deletion from the inherited template:
-README.md- Removes README.md from parent template-src/oldfeature/- Removes entire directory from parent template
This is useful when inheriting from a template but needing to remove specific files.
Variable Substitution
Template files can use variables that get replaced during project creation:
{{projectName}}- The project name{{domain}}- The domain from prompts{{server}}- The server hostname{{serverDir}}- The server directory- Any other prompt values
Best Practices
- Use inheritance to avoid duplication - build on existing templates
- Keep templates focused - each template should solve one use case well
- Document your template - include a README.md in the template
- Test thoroughly - ensure both dev and production modes work
- Follow conventions - match the structure and patterns of existing templates
Common Issues
Server setup required: Before deploying, your server needs Docker and Caddy configured. See SERVER.md for complete setup instructions.
Template-specific issues:
Check the README.md in your generated project for troubleshooting specific to your template type.
Publishing
The publish.sh script handles versioning, tagging, and publishing to npm:
# Patch release (1.0.0 -> 1.0.1)
./publish.sh
# Minor release (1.0.1 -> 1.1.0)
./publish.sh minor
# Major release (1.1.0 -> 2.0.0)
./publish.sh majorThe script will:
- Check for uncommitted changes
- Run checks (format, lint, type-check)
- Build the project
- Bump version in package.json
- Commit and tag the version
- Push to GitHub with tags
- Publish to npm
Contributing
Contributions are welcome! When adding new templates:
- Follow the template structure guidelines above
- Include comprehensive documentation
- Test both development and production workflows
- Consider if inheritance from existing templates makes sense
