MantisBase is designed as a lightweight C++ library that can be embedded directly into your desktop, mobile, or embedded application. This guide explains how to integrate MantisBase into your project and configure it.
Why Embed MantisBase?
- Add full-featured local storage and REST API support to your Qt, Slint, or CLI app
- Serve data to local UI components through HTTP or direct C++ API calls
- Retain full control of the application lifecycle and logic
- No separate server deployment required
Dependencies
On Linux, MantisBase depends on ZSTD and libpq for PostgreSQL support:
sudo apt-get install -y libzstd-dev
sudo apt install libpq-dev
Integration
As a Static or Shared Library
Add MantisBase as a submodule or include it in your CMake project:
add_subdirectory(mantisbase)
target_link_libraries(your_app PRIVATE mantisbase)
Basic Usage
Using Command-Line Arguments
The simplest way to embed MantisBase is using command-line arguments:
int main(
int argc,
char* argv[])
{
return app.run();
}
static MantisBase & create(int argc, char **argv)
Create class instance given cmd args passed in.
Definition mantisbase.cpp:56
int main(const int argc, char *argv[])
MantisApp standalone entrypoint.
Definition main.cpp:16
The main application for mantisbase.
This allows your application to accept standard MantisBase CLI arguments like --port, --host, --database, etc.
Using JSON Configuration
For more control when embedding, use JSON configuration:
{
config["dev"] = true;
config["serve"] = {
{"port", 8080},
{"host", "127.0.0.1"},
{"poolSize", 5}
};
config["dataDir"] = "./data";
config["publicDir"] = "./public";
config["scriptsDir"] = "./scripts";
return app.run();
}
nlohmann::json json
Shorten JSON namespace.
Definition context_store.h:18
Minimal Configuration
You can also create an instance with default settings:
Configuration Options
The JSON configuration supports the following options:
{
"database": "SQLITE", // or "PSQL"
"connection": "connection_string", // For PSQL: "dbname=db user=user password=pass"
"dataDir": "./data", // Directory for SQLite DB and files
"publicDir": "./public", // Static file serving directory
"scriptsDir": "./scripts", // JavaScript scripts directory
"dev": true, // Enable development mode
"serve": {
"port": 7070, // HTTP server port
"host": "127.0.0.1", // HTTP server host
"poolSize": 2 // Database connection pool size
}
}
All options are optional and will use sensible defaults if omitted.
Adding Custom Routes
You can add custom API endpoints using the router:
{
auto& router = app.router();
res.
sendJSON(200, {{
"message",
"Custom endpoint"}});
});
mb::json stats = {{
"users", 100}, {
"posts", 500}};
std::string userId = auth["id"];
res.
sendJSON(200, {{
"user_id", userId}});
return app.run();
}
A wrapper class around httplib::Request offering a consistent API and allowing for easy wrapper metho...
Definition http.h:42
T & getOr(const std::string &key, T default_value)
Get value from context store or return default.
Definition http.h:288
Wrapper around httplib::Response for consistent API.
Definition http.h:318
void sendJSON(int statusCode=200, const json &data=json::object()) const
Send JSON response.
Definition http_response.cpp:145
Middleware functions for request processing.
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireAdminAuth()
Require admin authentication.
Definition middlewares.cpp:299
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireEntityAuth(const std::string &entity_name)
Require entity-specific authentication.
Definition middlewares.cpp:381
Accessing Database
You can access the database directly for custom operations:
#include <soci/soci.h>
{
auto sql = app.db().session();
soci::row row;
*sql << "SELECT * FROM users WHERE id = :id",
soci::use("user123"),
soci::into(row);
if (sql->got_data()) {
}
return app.run();
}
Working with Entities
You can interact with entities programmatically:
{
auto users = app.entity("users");
{"name", "John Doe"},
{"email", "john@example.com"}
};
auto created = users.create(newUser);
auto allUsers = users.list();
if (auto user = users.read("user123"); user.has_value()) {
}
mb::json updates = {{
"name",
"Jane Doe"}};
auto updated = users.update("user123", updates);
users.remove("user123");
return app.run();
}
Project Structure
A typical embedded project structure:
your-app/
├── main.cpp
├── CMakeLists.txt
├── data/ # SQLite database and files (created automatically)
├── public/ # Static assets (optional)
├── scripts/ # JavaScript extensions (optional)
└── mantisbase/ # MantisBase submodule
Using as a Submodule
Add MantisBase as a git submodule:
git submodule add https://github.com/allankoechke/mantisbase.git
git submodule update --init --recursive
Then include it in your CMakeLists.txt:
add_subdirectory(mantisbase)
target_link_libraries(your_app PRIVATE mantisbase)
Testing Embedded APIs
Once your app is running, test the APIs:
# Test entity endpoints
curl http://localhost:7070/api/v1/entities/users
# Test custom endpoints
curl http://localhost:7070/api/v1/custom
# Test with authentication
curl -H "Authorization: Bearer <token>" \
http://localhost:7070/api/v1/entities/posts
Notes
- MantisBase APIs respect all access rules and authentication even in embedded mode
- The
run() method is blocking - use a separate thread if you need non-blocking behavior
- All entity endpoints follow the pattern
/api/v1/entities/<entity_name>
- Authentication endpoints are at
/api/v1/auth/*
- Schema management endpoints are at
/api/v1/schemas/* (admin only)
Complete Example
{
config["dev"] = true;
config["serve"] = {{"port", 8080}};
auto& router = app.router();
res.
sendJSON(200, {{
"message",
"Hello from embedded MantisBase!"}});
});
return app.run();
}
Summary
By embedding MantisBase, you gain powerful backend features including database storage, authentication, and REST APIs without requiring a separate server deployment. The library integrates seamlessly into your C++ application with minimal configuration.