Introduction
Prism is a C++20 web framework for REST APIs, covering routing, middleware, authentication, logging and JSON. The HTTP transport is built on Boost.Asio and C++20 coroutines, providing modern asynchronous request handling.
This page covers installing, configuring and deploying it. For type-by-type signatures, see the API reference.
Prism is pre-1.0. Signatures still change between versions, so pin a release tag rather than tracking main.
The repository also contains Prism API, a blog backend built on the framework, with accounts, posts and comments plus JWT auth, rate limiting, CORS, PostgreSQL persistence and a small web UI. It exists so there is a complete, working app to read rather than only snippets.
Add Prism to your project
Prism is consumed from your CMakeLists.txt. There is nothing to clone or system-install first. CMake fetches and builds it during your own configure step.
include(FetchContent)
FetchContent_Declare(
Prism
GIT_REPOSITORY https://github.com/Segniko/Prism.git
GIT_TAG v0.1.0 # pin a tag, main moves
GIT_SUBMODULES ""
)
FetchContent_MakeAvailable(Prism)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE Prism::Prism)
The only things you need installed are a C++20 compiler, CMake 3.16+ and OpenSSL (for the auth features). nlohmann/json is fetched automatically.
OpenSSL: apt-get install libssl-dev (Linux), brew install openssl (macOS), or vcpkg install openssl (Windows). Don't need auth? Add -DENABLE_OPENSSL=OFF. Prism also ships a vcpkg.json and a conanfile.py.
Quick start
A complete first project is two files. Your main.cpp creates a Server, registers routes and calls start():
#include "Prism.hpp" // one header for the whole framework
using namespace Prism;
int main() {
Server server; // defaults: 0.0.0.0:8080, 4 threads
server.get("/", [](const HttpRequest&) -> boost::asio::awaitable {
co_return HttpResponse::text("Hello, Prism!");
});
server.get("/api/users/:id", [](const HttpRequest& req) -> boost::asio::awaitable {
Json out;
out["id"] = req.path_params.at("id");
co_return HttpResponse::json(out.dump());
});
server.start(); // blocks until stop()
}
Configure, build and run it with CMake. Your server is live on http://localhost:8080:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/my_app # http://localhost:8080
For what each type does, read the API reference. For a full app, clone the repo. The reference API builds as prism-api, and .env.example copied to .env configures it.
Usage examples
Drive the reference API with curl. Registering or logging in returns a JWT you pass back as a Bearer token.
# Register (returns a token)
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"alice","email":"alice@example.com","password":"a-strong-password"}'
# Create a post (authenticated)
curl -X POST http://localhost:8080/api/posts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"title":"My First Post","content":"Hello world"}'
# Read posts and a single post with its comments
curl http://localhost:8080/api/posts
curl http://localhost:8080/api/posts/1
Configuration
All settings come from environment variables (a .env file is loaded at startup, and real environment variables win). The important ones:
| Variable | Default | Notes |
|---|---|---|
| PORT / HOST | 8080 / 0.0.0.0 | Listen address |
| ENVIRONMENT | development | In production the server refuses to start without a real JWT_SECRET_KEY |
| JWT_SECRET_KEY | none | Token signing secret. Generate with openssl rand -hex 32 |
| DATABASE_URL | none | PostgreSQL connection string (enables the database when set) |
| ENABLE_DATABASE | auto | Defaults to true when DATABASE_URL is set |
| DB_SSLMODE | prefer | Use require for hosted databases |
| CORS_ORIGIN | * | Set to your frontend origin in production |
| RATE_LIMIT_MAX | 100 | Requests per window, per client IP |
| RATE_LIMIT_WINDOW_SECONDS | 60 | Rate-limit window length |
In production, set JWT_SECRET_KEY to a strong random value. The server refuses to start without it. Without DATABASE_URL, data is in-memory and lost on every restart.
Connecting to Supabase
- In the Supabase dashboard go to Project Settings → Database → Connection string and pick the Session pooler variant.
- Set it as DATABASE_URL (in .env locally, or in the Render dashboard in production).
- On first start, Prism creates the users, posts, comments and migrations tables and enables row-level security on them.
postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres
Reference API endpoints
These are the HTTP routes of the bundled prism-api demo, not of the framework itself. For the framework's C++ types see the API reference. Authenticated requests send the token in the Authorization: Bearer <token> header.
Project structure
Prism/
├── ConfigAPI/
│ ├── include/ # Public headers, the part you consume
│ ├── src/ # Implementations + main.cpp (the reference API)
│ ├── third_party/ # Vendored dependencies
│ └── examples/ # Example programs (-DBUILD_EXAMPLES=ON)
├── website/ # This documentation site (GitHub Pages)
├── public/ # Frontend served by the reference API
├── tests/ # GoogleTest suite (-DBUILD_TESTS=ON)
├── Dockerfile # Multi-stage image
├── render.yaml # Render deployment config
├── CMakeLists.txt # FetchContent-ready build
└── .env.example # Environment variable template
Deployment
Docker
A multi-stage Dockerfile builds the binary and packages a slim runtime image.
docker build -t prism-api .
docker run -p 8080:8080 \
-e JWT_SECRET_KEY=$(openssl rand -hex 32) \
-e DATABASE_URL=... prism-api
Render
- Push the repository to GitHub.
- Create a new Web Service on Render and connect the repo. render.yaml is detected automatically (Docker runtime, /health health check).
- Set the two secrets (marked sync: false): JWT_SECRET_KEY and DATABASE_URL.
- Deploy.
Health check
The /health endpoint reports service and database status, which suits load balancers and uptime monitors.
{
"status": "healthy",
"version": "0.1.0",
"environment": "production",
"database_enabled": true,
"database_healthy": true
}