Backend Template
The backend template creates a production-oriented Vix backend application. Use it when you want more than a simple main.cpp.
It is designed for real backend services that need:
- API routes
- health checks
- middleware
- static files
- templates
- configuration
- storage
- database migrations
- production diagnostics
- deployment metadata
- a structure that can grow without becoming messy
Create a backend project with:
vix new api --template backendWhat this template is for
Use the backend template when you want to build:
- REST APIs
- JSON APIs
- backend services
- admin backends
- realtime backends
- WebSocket-ready services
- production services behind Nginx and systemd
- services with health checks and diagnostics
- APIs that may later need database, auth, logs, migrations, static files, or background logic
This template is not only a demo.
It gives you a serious starting structure for a backend application.
Design used by this template
The backend template uses a layered backend architecture inspired by Clean Architecture.
The important idea is simple:
main.cpp
-> app bootstrap
-> middleware
-> routes
-> controllers
-> application logic
-> domain logic
-> infrastructureThe generated project starts small, but the folders already prepare the application to grow.
This design separates responsibilities:
| Layer | Role |
|---|---|
app/ | Starts and wires the application. |
presentation/ | Handles HTTP routes, controllers, middleware, and request/response concerns. |
application/ | Contains use cases and application workflows. |
domain/ | Contains business rules and core models. |
infrastructure/ | Contains database, file system, external services, repositories, clients, and technical adapters. |
support/ | Contains shared helpers used by the backend. |
The goal is not to make the project complicated.
The goal is to prevent a backend from becoming one giant main.cpp.
Quick start
Create the project:
vix new api --template backendEnter the project:
cd apiCreate your local configuration:
cp .env.example .envStart development mode:
vix devOpen:
http://127.0.0.1:8080
http://127.0.0.1:8080/status.htmlCheck the API:
curl http://127.0.0.1:8080/api
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/healthGenerated structure
A backend project generated with:
vix new api --template backendhas this structure:
api/
├── include/
│ └── api/
│ ├── app/
│ │ └── AppBootstrap.hpp
│ ├── support/
│ │ └── HttpResponses.hpp
│ └── presentation/
│ ├── controllers/
│ ├── middleware/
│ └── routes/
├── src/
│ ├── main.cpp
│ └── api/
│ ├── app/
│ │ └── AppBootstrap.cpp
│ ├── application/
│ ├── domain/
│ ├── infrastructure/
│ ├── presentation/
│ │ ├── controllers/
│ │ │ ├── HomeController.hpp
│ │ │ ├── HomeController.cpp
│ │ │ ├── HealthController.hpp
│ │ │ └── HealthController.cpp
│ │ ├── middleware/
│ │ │ ├── MiddlewareRegistry.hpp
│ │ │ └── MiddlewareRegistry.cpp
│ │ └── routes/
│ │ ├── RouteRegistry.hpp
│ │ └── RouteRegistry.cpp
│ └── support/
│ └── HttpResponses.cpp
├── public/
│ ├── index.html
│ ├── app.css
│ ├── app.js
│ ├── status.html
│ ├── status.css
│ └── status.js
├── views/
├── storage/
├── migrations/
├── tests/
├── .env.example
├── .env
├── vix.app
├── vix.json
└── README.mdWhy this design exists
A backend usually starts simple.
At the beginning, you may only need:
GET /api
GET /healthBut later, a real backend often needs:
- authentication
- users
- roles
- orders
- billing
- file uploads
- WebSocket events
- database access
- migrations
- background jobs
- logs
- health checks
- deployment checks
- static status pages
- reverse proxy configuration
If everything stays inside main.cpp, the project becomes hard to maintain.
The backend template avoids that problem by separating the project early, but without forcing you to fill every folder immediately.
You can start with the generated files and add logic progressively.
Request flow
The generated backend follows this flow:
main.cpp
-> AppBootstrap
-> load .env
-> create vix::App
-> configure templates
-> mount public files
-> register middleware
-> register routes
-> start serverThen an HTTP request follows this flow:
client request
-> middleware stack
-> route registry
-> controller
-> response helper
-> response sent to clientThis flow gives you a clear place for each responsibility.
main.cpp
main.cpp is intentionally small.
It only starts the application:
#include <api/app/AppBootstrap.hpp>
int main()
{
api::app::AppBootstrap bootstrap;
return bootstrap.run();
}Do not put all routes, middleware, database code, and business logic in main.cpp.
main.cpp should stay focused on startup.
The app/ folder owns the application startup sequence.
Generated files:
include/api/app/AppBootstrap.hpp
src/api/app/AppBootstrap.cppAppBootstrap is responsible for:
- loading
.env - creating
vix::App - reading configuration
- configuring templates
- mounting static files
- enabling static compression when configured
- registering middleware
- registering routes
- starting the server
The generated bootstrap reads values such as:
templates.path
public.path
public.mount
public.index
public.cache_control
public.spa_fallback
public.compressionThen it configures:
app.templates(viewsPath);
app.static_dir(publicPath, publicMount, publicIndex, ...);Finally, it starts the application:
app.run(cfg);This is why the port and runtime settings belong in .env, not in the source code.
presentation/
The presentation/ layer is the HTTP layer.
It contains the code that talks to the outside world through HTTP.
Generated folders:
presentation/controllers/
presentation/routes/
presentation/middleware/Use this layer for:
- HTTP routes
- request parsing
- response formatting
- middleware registration
- authentication middleware
- CORS
- rate limiting
- API controllers
- status endpoints
Do not put core business rules here.
Controllers should call application services when the project grows.
presentation/routes/
Routes are centralized in:
src/api/presentation/routes/RouteRegistry.cppThe generated RouteRegistry registers controller routes:
controllers::HomeController::register_routes(app);
controllers::HealthController::register_routes(app);This means AppBootstrap does not need to know every controller.
When you add a new controller, register it here.
Example:
controllers::UserController::register_routes(app);
controllers::OrderController::register_routes(app);This keeps route wiring clear.
presentation/controllers/
Controllers own HTTP route handlers.
Generated controllers:
HomeController
HealthControllerHomeController registers:
GET /apiHealthController registers:
GET /health
GET /api/healthA controller should handle HTTP concerns:
- reading route parameters
- reading query parameters
- validating request shape
- calling application services
- sending JSON responses
Example role:
UserController
-> receives HTTP request
-> validates input
-> calls CreateUserUseCase
-> returns JSON responseA controller should not contain heavy business logic.
presentation/middleware/
Middleware is centralized in:
src/api/presentation/middleware/MiddlewareRegistry.cppThe generated middleware registry installs:
- security headers
- request logging
- an
X-API: truemarker header for/apiroutes
The generated file also documents the recommended production order:
CORS -> rate limit -> request logging -> security headers -> body limits -> auth -> routesThis order matters.
For example:
- CORS should run early because browsers need it.
- Rate limiting should run before expensive logic.
- Request logging should observe the request.
- Security headers should apply to responses.
- Body limits should protect memory.
- Auth should run before protected routes.
- Routes should run after middleware is ready.
When your app grows, add middleware here instead of scattering it across main.cpp.
support/
The support/ folder contains shared backend helpers.
Generated files:
include/api/support/HttpResponses.hpp
src/api/support/HttpResponses.cppThe generated helpers include:
json_error(...)
json_ok(...)
json_message(...)Use this folder for small reusable helpers that are not business logic.
Examples:
- JSON response helpers
- pagination helpers
- HTTP error helpers
- request parsing helpers
- shared constants
Do not put database repositories here.
Do not put business rules here.
Use application/, domain/, and infrastructure/ for that.
application/
The application/ folder is empty at the beginning.
It is where you put use cases.
A use case is an application action.
Examples:
CreateUser
LoginUser
PlaceOrder
SendMessage
UploadFile
GenerateReportWhen the project grows, the controller should not do everything.
Instead, the controller should call a use case.
Example flow:
POST /api/users
-> UserController
-> CreateUserUseCase
-> UserRepository
-> returns result
-> JSON responseUse application/ for orchestration.
It coordinates domain logic and infrastructure.
domain/
The domain/ folder is empty at the beginning.
It is where you put business rules.
Examples:
User
Order
Invoice
Payment
Role
Permission
Message
ConversationUse this folder for logic that should not depend on HTTP, database, Vix, or external services.
Good domain code should be easy to test.
Example:
domain/User.hpp
domain/Order.hpp
domain/PermissionPolicy.hppThe domain layer answers questions like:
Can this user perform this action?
Is this order valid?
Can this invoice be paid?
Is this message allowed?infrastructure/
The infrastructure/ folder is empty at the beginning.
It is where you put technical adapters.
Examples:
MySqlUserRepository
SqliteOrderRepository
FileStorage
EmailClient
RedisCache
PaymentGatewayClient
WebSocketMessageStoreUse this folder for things that talk to the outside world:
- database
- file system
- Redis
- HTTP clients
- payment APIs
- email providers
- storage services
- external APIs
The application layer can depend on interfaces, while infrastructure provides concrete implementations.
public/
The backend template includes public/ on purpose.
This does not mean the backend is a frontend framework.
Static files are useful in a production backend.
Generated files include:
public/index.html
public/app.css
public/app.js
public/status.html
public/status.css
public/status.jsUse public/ for:
- a simple landing page
- a backend status page
- a WebSocket test page
- a local diagnostics UI
- static assets
- deployment check pages
- a small admin/status interface
This is useful especially when the backend has WebSocket or realtime features.
For example, a backend may expose:
/status.htmlto test:
- HTTP is running
- static files are served
- health endpoint responds
- WebSocket connection can be tested later
The generated AppBootstrap mounts public/ at /.
That means:
public/index.html -> http://127.0.0.1:8080/
public/status.html -> http://127.0.0.1:8080/status.htmlviews/
The views/ folder is for server-side templates.
The backend template configures:
app.templates(viewsPath);The folder can stay empty if your backend only returns JSON.
Use views/ when you want the backend to render HTML pages.
Examples:
- admin page
- status dashboard
- email preview page
- simple internal tool
- server-rendered documentation page
If your project is mainly server-rendered HTML, use the web template instead:
vix new site --template webstorage/
The storage/ folder is for runtime storage.
Examples:
storage/api.db
storage/uploads/
storage/cache/
storage/logs/
storage/tmp/The generated .env.example can point SQLite to:
DATABASE_SQLITE_PATH=storage/api.dbUse storage/ for local files that belong to the running service.
Do not put source code here.
migrations/
The migrations/ folder is for database migrations.
A migration is a database change saved as a file.
Examples:
001_create_users.sql
002_create_orders.sql
003_add_user_roles.sqlThe backend template includes migration settings in .env:
VIX_ORM_DIR=migrationsUse this folder when your backend starts using a database.
tests/
The tests/ folder contains backend tests.
The generated backend includes a basic test executable.
Run tests with:
vix testsUse tests for:
- domain rules
- use cases
- helpers
- controllers
- regression checks
- safety before deployment
As the backend grows, add tests close to the logic you care about.
.env.example
.env.example documents the expected configuration.
It is safe to commit.
It contains values such as:
APP_NAME=api
APP_ENV=development
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
PUBLIC_PATH=public
PUBLIC_MOUNT=/
PUBLIC_INDEX=index.html
PUBLIC_CACHE_CONTROL=public, max-age=3600
PUBLIC_SPA_FALLBACK=false
PUBLIC_COMPRESSION=false
DATABASE_ENGINE=sqlite
DATABASE_SQLITE_PATH=storage/api.db
WEBSOCKET_ENABLED=false
WEBSOCKET_HOST=0.0.0.0
WEBSOCKET_PORT=9090When someone clones the project, they should run:
cp .env.example .env.env
.env contains local runtime values.
Use .env for:
- local port
- local database path
- local logging level
- local WebSocket settings
- secrets
- machine-specific values
Do not hardcode these values in C++ source code.
vix.app
vix.app is the build manifest.
It describes the backend executable target.
The generated backend manifest includes source files such as:
src/main.cpp
src/api/app/AppBootstrap.cpp
src/api/support/HttpResponses.cpp
src/api/presentation/routes/RouteRegistry.cpp
src/api/presentation/middleware/MiddlewareRegistry.cpp
src/api/presentation/controllers/HomeController.cpp
src/api/presentation/controllers/HealthController.cppIt also includes resources:
resources = [
".env=.env",
"public=public",
"views=views",
"storage=storage",
]That means these runtime folders are copied or made available next to the built executable.
The build flow is:
vix.app
-> Vix generates internal CMake
-> vix build compiles the backend
-> vix run starts the backendDo not edit the generated CMake project manually.
Edit vix.app.
vix.json
vix.json is the project metadata and orchestration file.
The backend template uses it for:
- project name
- version
- template type
- tasks
- production service settings
- proxy settings
- health checks
- deployment settings
- logs
- database defaults
- required environment variables
Common tasks include:
vix task dev
vix task build
vix task test
vix task checkThe generated vix.json also prepares production-oriented sections such as:
production.service
production.ports
production.websocket
production.proxy
production.health
production.deploy
production.logs
production.env
production.databaseThis gives Vix enough metadata to help with production workflows.
Configuration model
The backend template uses two kinds of configuration.
.env -> runtime values
vix.json -> project orchestrationUse .env for values that change per environment:
SERVER_PORT
DATABASE_SQLITE_PATH
WEBSOCKET_PORT
VIX_LOG_LEVELUse vix.json for project-level metadata:
tasks
production service name
proxy configuration
health check URLs
deployment workflow
required env variablesDo not duplicate everything everywhere.
The simple rule is:
.env = how the app runs here
vix.json = how Vix manages the projectGenerated routes
The backend starts with these routes:
GET /api
GET /health
GET /api/healthThe / route is served from:
public/index.htmlThat means:
GET / -> static HTML page
GET /api -> JSON backend route
GET /health -> health checkThis separation is useful:
/can show a simple status or landing page./apiproves the API layer works./healthis for local checks, monitoring, service checks, and deployment scripts.
Middleware stack
The generated middleware registry installs:
security headers
request logging
X-API marker for /api routesRecommended production order:
CORS
-> rate limit
-> request logging
-> security headers
-> body limits
-> auth
-> routesAs your backend grows, add middleware in MiddlewareRegistry.
Examples:
CORS
rate limiting
auth
request body size limits
compression
sessions
API version headersWebSocket-ready configuration
The backend template includes WebSocket configuration in .env.example and vix.json.
Example:
WEBSOCKET_ENABLED=false
WEBSOCKET_HOST=0.0.0.0
WEBSOCKET_PORT=9090
WEBSOCKET_MAX_MESSAGE_SIZE=65536
WEBSOCKET_IDLE_TIMEOUT=60
WEBSOCKET_ENABLE_DEFLATE=true
WEBSOCKET_PING_INTERVAL=30
WEBSOCKET_AUTO_PING_PONG=trueThis does not mean every backend starts a WebSocket server automatically.
It means the backend is prepared for realtime features.
When you add WebSocket later, you already have:
- the port convention
- environment variables
- production metadata
- proxy metadata
- a place for static status or test pages
This is why public/status.html is useful.
A backend can serve a small page that helps verify HTTP and later WebSocket behavior.
How to add a new route
Example: add a users controller.
Create:
include/api/presentation/controllers/UserController.hpp
src/api/presentation/controllers/UserController.cppRegister the controller in:
src/api/presentation/routes/RouteRegistry.cppExample:
controllers::UserController::register_routes(app);Add the new .cpp file to vix.app:
sources = [
"src/main.cpp",
"src/api/app/AppBootstrap.cpp",
"src/api/support/HttpResponses.cpp",
"src/api/presentation/routes/RouteRegistry.cpp",
"src/api/presentation/middleware/MiddlewareRegistry.cpp",
"src/api/presentation/controllers/HomeController.cpp",
"src/api/presentation/controllers/HealthController.cpp",
"src/api/presentation/controllers/UserController.cpp",
]Then run:
vix build
vix runHow to add business logic
Do not put business logic directly in the controller forever.
Start simple, then move logic into application/.
Example:
src/api/application/CreateUserUseCase.hpp
src/api/application/CreateUserUseCase.cppThe controller should become:
HTTP request
-> UserController
-> CreateUserUseCase
-> result
-> JSON responseThis keeps controllers thin.
How to add domain logic
Put business rules in domain/.
Example:
src/api/domain/User.hpp
src/api/domain/UserPolicy.hppUse this layer for logic like:
validate user role
check if order can be cancelled
check if invoice can be paid
validate message policyDomain logic should not know about HTTP.
How to add database code
Put database code in infrastructure/.
Example:
src/api/infrastructure/database/SqliteConnection.hpp
src/api/infrastructure/repositories/UserRepository.hpp
src/api/infrastructure/repositories/SqliteUserRepository.cppUse migrations/ for database schema changes.
Example:
migrations/001_create_users.sqlHow to add static files
Put static files in:
public/Examples:
public/status.html
public/admin.html
public/app.css
public/app.js
public/ws-test.htmlThen open:
http://127.0.0.1:8080/status.htmlUse this for simple backend pages, not for large frontend applications.
For large frontend applications, use the Vue template:
vix new dashboard --template vueHow to add templates
Put HTML templates in:
views/Use templates when your backend should render HTML.
For a project mainly focused on server-rendered pages, prefer:
vix new site --template webBuild and run
Start development mode:
vix devBuild:
vix buildRun:
vix runRun tests:
vix testsCheck the project:
vix check --tests --runProduction direction
The backend template is production-oriented, but it is still a starter.
Before production, you will usually add:
- real logging policy
- real error handling
- CORS policy
- rate limiting
- authentication
- database migrations
- service user
- Nginx proxy
- TLS termination
- health checks
- deployment scripts
- monitoring
- backups
The template gives you the structure where these pieces belong.
When not to use this template
Do not use the backend template when you only want a tiny experiment.
Use the application template instead:
vix new hello --appDo not use the backend template when you mainly want server-rendered HTML pages.
Use the web template instead:
vix new site --template webDo not use the backend template when you want a Vue frontend and a Vix backend together.
Use the Vue template instead:
vix new dashboard --template vueCommon mistakes
Putting everything in main.cpp
Avoid growing main.cpp.
Keep it small.
Use:
AppBootstrap
RouteRegistry
MiddlewareRegistry
controllersPutting business logic in controllers forever
A controller can start simple.
But when logic grows, move it to:
application/
domain/Putting database code in controllers
Database code belongs in:
infrastructure/Controllers should not directly become database scripts.
Forgetting to update vix.app
When you add new .cpp files, add them to:
sources = [
]in vix.app.
Confusing static files with frontend apps
public/ is useful for status pages, simple assets, diagnostics, and small HTML pages.
For a full frontend app, use the Vue template.
Hardcoding runtime values
Avoid hardcoding ports, paths, or secrets.
Use .env.
What you should remember
The backend template uses a layered backend architecture inspired by Clean Architecture.
The main flow is:
main.cpp
-> AppBootstrap
-> MiddlewareRegistry
-> RouteRegistry
-> Controllers
-> Application
-> Domain
-> InfrastructureUse each folder for its role:
| Folder | Role |
|---|---|
app/ | Startup and wiring. |
presentation/ | HTTP layer. |
application/ | Use cases and workflows. |
domain/ | Business rules. |
infrastructure/ | Database and external systems. |
support/ | Shared backend helpers. |
public/ | Static backend assets and status pages. |
views/ | Server-rendered templates. |
storage/ | Runtime local storage. |
migrations/ | Database migrations. |
tests/ | Tests. |
Create a backend:
vix new api --template backend
cd api
cp .env.example .env
vix devCheck it:
curl http://127.0.0.1:8080/api
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/healthNext steps
Continue with: