Backend Integration
The Vue template keeps the backend as a normal Vix C++ application. The frontend lives in frontend/, but the backend is still built from the project root, described by vix.app, and run through the Vix CLI.
The integration between both sides happens through HTTP. Vue calls API routes, usually under /api, and the Vix backend returns JSON responses. This keeps the frontend and backend close in one project without mixing their source files or build systems.
Vue frontend
-> fetch("/api/...")
-> Vix backend route
-> JSON responseBackend role
The backend side of a Vue template project is responsible for application logic, API routes, data access, authentication, validation, server configuration, and anything that should not run inside the browser.
The generated frontend should not import backend files. The backend should not import Vue components. They live in the same project, but they communicate through API routes.
frontend/src/ Vue components and browser code
src/ C++ backend source
include/ backend headers
vix.app backend build manifest
vix.json shared project workflowThis boundary is the main reason the template stays understandable as it grows.
Backend layout
The generated backend is intentionally small.
dashboard/
include/
app/
ModuleRegistry.hpp
src/
main.cpp
app/
ModuleRegistry.cpp
vix.app
vix.jsonThe exact backend can grow over time, but the starting point is simple: one Vix application target, one entry point, and a place for future module registration.
Backend entry point
The backend entry point lives in:
src/main.cppA small Vue template backend usually creates a Vix app, registers API routes, and starts the server.
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/api/hello", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
"ok", true,
"message", "Hello from Vix"
});
});
app.run(8080);
}The generated frontend calls this route with a relative path.
const response = await fetch("/api/hello");
const data = await response.json();During development, Vite receives that /api/hello request and forwards it to the Vix backend through the proxy.
API route prefix
The generated project uses /api as the backend boundary.
/apiThis makes the project easier to reason about. Browser page routes and frontend assets belong to the Vue side. Backend data routes belong under /api.
GET /api/hello
GET /api/projects
POST /api/login
GET /api/meKeeping API routes grouped under /api also makes the Vite proxy simple.
server: {
proxy: {
"/api": "http://localhost:8080"
}
}Vite proxy
The frontend development server forwards API requests to the backend.
browser
-> Vite dev server
-> Vue app
-> /api request
-> Vix backend on localhost:8080This lets frontend code stay clean.
fetch("/api/hello");Avoid hard-coding the local backend URL inside Vue components.
fetch("http://localhost:8080/api/hello");The proxy already knows where the backend runs during development. Relative /api paths make the frontend easier to move between local development and production.
vix.app
The backend target is described by the root vix.app.
vix.appA generated Vue project can start with a small backend manifest.
name = "dashboard"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
"src/app/ModuleRegistry.cpp",
]
include_dirs = [
"include",
"src",
]
packages = [
"vix",
]
links = [
"vix::vix",
]This manifest describes only the C++ backend. Vue files under frontend/ do not belong in sources, because they are handled by Vite.
Adding backend source files
When the backend grows, add C++ files under src/ and headers under include/.
include/
api/
ProjectsController.hpp
src/
api/
ProjectsController.cppThen add the new .cpp file to vix.app.
sources = [
"src/main.cpp",
"src/app/ModuleRegistry.cpp",
"src/api/ProjectsController.cpp",
]This is still a Vix application. A .cpp file must be listed in the manifest before it is compiled into the backend target.
Adding an API controller
A cleaner backend can move routes out of main.cpp and into controllers.
include/api/ProjectsController.hpp
src/api/ProjectsController.cppThe controller can expose a route registration function.
#pragma once
namespace vix
{
class App;
}
namespace api
{
class ProjectsController
{
public:
static void register_routes(vix::App &app);
};
}The implementation owns the routes.
#include <api/ProjectsController.hpp>
#include <vix.hpp>
namespace api
{
void ProjectsController::register_routes(vix::App &app)
{
app.get("/api/projects", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
"ok", true,
"projects", vix::json::Array{}
});
});
}
}Then main.cpp can stay focused on application setup.
#include <api/ProjectsController.hpp>
#include <vix.hpp>
int main()
{
vix::App app;
api::ProjectsController::register_routes(app);
app.run(8080);
}This is a good step when the backend starts to have more than one or two routes.
ModuleRegistry
The generated Vue template can include a backend module registry.
include/app/ModuleRegistry.hpp
src/app/ModuleRegistry.cppThe registry gives the backend one place to connect internal modules later. A small project may not need modules immediately, but the integration point prevents main.cpp from becoming a long file as the backend grows.
main.cpp
-> app::ModuleRegistry
-> backend modulesA simple registry can expose one function.
#pragma once
namespace vix
{
class App;
}
namespace app
{
class ModuleRegistry
{
public:
static void register_all(vix::App &app);
};
}The default implementation can be empty.
#include <app/ModuleRegistry.hpp>
namespace app
{
void ModuleRegistry::register_all(vix::App &app)
{
(void)app;
}
}Then main.cpp can call the registry once.
#include <app/ModuleRegistry.hpp>
#include <vix.hpp>
int main()
{
vix::App app;
app::ModuleRegistry::register_all(app);
app.run(8080);
}Using app modules later
When the backend becomes larger, features can move into app modules.
vix modules init
vix modules add auth
vix modules add projectsA module-based backend can keep feature routes and implementation inside modules/.
modules/
auth/
include/auth/
src/
tests/
vix.module
CMakeLists.txt
projects/
include/projects/
src/
tests/
vix.module
CMakeLists.txtThe root vix.app can declare which modules are active.
[module.auth]
enabled = true
path = "modules/auth"
kind = "backend"
depends = []
[module.projects]
enabled = true
path = "modules/projects"
kind = "backend"
depends = [
"auth",
]The Vue frontend still calls the backend through /api. The internal backend organization can change without changing the frontend boundary.
Returning JSON
The Vue frontend expects API responses it can parse.
const response = await fetch("/api/projects");
const data = await response.json();The backend should return JSON for API routes.
res.json({
"ok", true,
"message", "Hello from Vix"
});Keep response shapes consistent. For example, a project can use a simple convention:
{
"ok": true,
"data": {}
}and for errors:
{
"ok": false,
"error": "not_found",
"message": "Resource not found"
}The exact shape is a project decision. What matters is that the frontend and backend agree on it.
Backend configuration
The Vue template backend can start small, but real projects usually need runtime configuration.
A simple backend can run on the default port:
app.run(8080);A more structured backend can load configuration from .env.
vix::config::Config cfg{".env"};
vix::App app;
app.run(cfg);When the backend uses .env, keep .env.example in the repository to document expected variables, and keep real local values in .env.
.env.example documented variables
.env local runtime valuesFrontend calls should stay relative
The frontend should call backend routes through relative /api paths.
fetch("/api/projects");This works during development because Vite proxies /api to the backend. It also works better in production when the frontend and backend are served under the same domain or behind the same reverse proxy.
Hard-coded local URLs are harder to move.
fetch("http://localhost:8080/api/projects");A hard-coded development URL can break when the app is opened from another device, deployed behind a domain, served through HTTPS, or routed through a proxy.
Backend development commands
Backend commands run from the project root.
vix build
vix run
vix tests
vix check --tests --runThe frontend commands run inside frontend/.
npm install --prefix frontend
npm run dev --prefix frontend
npm run build --prefix frontendDuring normal development, use the project workflow.
npm install --prefix frontend
vix devFor manual debugging, run backend and frontend in separate terminals.
vix runnpm run dev --prefix frontendBuilding for production
Build the backend with Vix.
vix buildBuild the frontend with Vite.
npm run build --prefix frontendThe frontend output is written to:
frontend/dist/A production deployment can decide how to serve that directory. One common approach is to let the backend carry it as a runtime resource.
resources = [
"frontend/dist=public",
]Then the built frontend is copied beside the backend executable as public/.
bin/
dashboard
public/
index.html
assets/That deployment shape is optional. During development, Vite serves the frontend directly.
Checking the integration
A practical integration check validates both sides.
vix check --tests
vix tests --fail-fastThen build the frontend.
npm run build --prefix frontendFinally, confirm that the frontend uses relative API routes and that the backend exposes matching /api routes.
Vue calls /api/...
Vite proxies /api to the backend
Vix backend registers matching /api routes
backend returns JSON
frontend handles success and failure responsesCommon mistakes
The most common mistake is mixing the two build systems. Vue files do not belong in vix.app, and C++ files do not belong in the Vite build.
Another mistake is adding a backend .cpp file but forgetting to list it in vix.app. The backend may compile without the new route, or linking may fail because the implementation was never added to the target.
A third mistake is hard-coding http://localhost:8080 inside Vue components. Use relative /api paths and let the Vite proxy handle development routing.
A fourth mistake is putting too much backend logic directly in main.cpp. That is fine for the first route, but controllers or modules are better once the backend grows.
Recommended rule
Keep the integration simple. Vue owns the browser UI. Vix owns the backend API. Use /api as the boundary, keep frontend calls relative, list backend .cpp files in vix.app, and move backend features into controllers or modules when they become larger than a starter route.
Next step
Continue with the API proxy page to see how Vite forwards frontend requests to the Vix backend during development.