We have seen how to extend MantisBase natively in C++, allowing you full configurability of the engine. But that comes at a cost. You need to compile your code either from source or link to the shared dev lib.
Extending MantisBase: the C++ Edition (Part 1 — Setup)
One of MantisBase’s biggest goals has always been embeddability in any C++ codebase. In the past, you had to compile MantisBase from source, and if you’ve tried, you know it can be daunting.
Extending MantisBase: The C++ Edition (Part 2)
In Part 1, we walked through setting up the MantisBase C++ development package and creating a basic CMake project.
What if you are not a C++ expert? Or even more, you don’t have the capacity to rebuild the whole engine?
There is an easier way: using the embedded scripting engine!
Which Scripting Language?
Anytime scripting is mentioned in any software, it’s either a hit or a miss. You may be required to learn a whole different syntax or even more, fight outdated documentation just to get the basics.
For MantisBase, we chose to go with the regular feel of ES5 syntax using the Duktape library, which allows embedding a JavaScript engine inside C/C++ codebases. Being lightweight, it was the perfect fit for static embedding.
The question that remains is, how do I start it?
Don’t worry, the Duktape scripting engine lifecycle is managed by MantisBase. Yours is to provide the scripts, and we execute them as needed. Just drop a main.mb.js in your scripts directory (next to the mantisbase binary, or wherever --scriptsDir points), and that’s your entry script. It’s loaded first, so register your routes and middleware there. Want to split things up? Pull in extra files with app.loadScript().
# Use default scripts dir
mantisbase serve
# Set a different scripts dir for mantisbase to search for `main.mb.js` entrypoint script
mantisbase --scriptsDir /some/dir serveWhat can you do from JS?
We ship a types file, mantisbase.d.ts, in the git root dir as well as with the binary zip file. It provides types for all shipped features. Copy it next to your scripts, and editors like VS Code and Cursor will give you autocompletion and inline docs. It’s types-only, so the server never executes it.
Currently, the scripting engine allows you to:
Register custom routes: use
app.router()withaddRoute, or theget,post,put,patchanddeleteshorthands. You can also set up redirects without writing a handler.Chain middleware: attach your own middleware to a route, or reuse the built-in ones from the global
middlewaresobject, likerequireAdminAuth(),requireEntityAuth(entity)andrequireExprEval(expr).Handle requests and responses: read the body, headers, query and path params, then reply with
res.json(),res.html(),res.text(),res.send(),res.empty(), or stream a file withres.setFileContent().Share data between middleware and handlers: use
req.set()andreq.get()on the per-request context store.Query the database: run SQL with
:namedbinds viaapp.db().query(), or lease a session for transactions withbegin(),commit()androllback().Work with auth: create and verify JWTs, and refresh or revoke sessions through
app.auth().Manage settings and files: read and write app config with
app.settings(), and resolve entity upload paths withapp.files().Push realtime events: broadcast changes to subscribers with
app.router().broadcastChange()andapp.rt().Log properly: use
app.logs()for structured logging, orconsole.log()for quick output.Use helper utilities: the
utilsobject gives you ID generators, environment variable access, filename sanitizing and password hashing and verification.React to lifecycle events: define
onServerStart(),onServerShutdown(),onRecordCreated()oronRecordUpdated()and MantisBase calls them when the time comes.
Here’s what a complete endpoint looks like:
// main.mb.js
app.router().get("/hello/:name", function (req, res) {
res.json(200, { message: "Hello, " + req.getPathParam("name") + "!" });
}, middlewares.requireAdminAuth());
That’s a protected endpoint with no rebuild and no linking, just a script.
Limitations, so far
Scripting is great, but keep these in mind:
It’s ES5, not modern JS. Duktape is built for small footprints, not the latest syntax. There are no arrow functions,
let/const, template literals,async/awaitor Promises. If you’re used to Node-style code, you’ll be writingfunctionandvaragain. (The types file uses TypeScript syntax, but that’s only for your editor’s hints. Your actual scripts must stay ES5.)No Node.js or browser APIs. There’s no
fs, nofetch, nonpmecosystem and no ES modules. You can split code across files withapp.loadScript(), but that’s all.You only get what we expose. If it isn’t in the types file, you can’t call it from JS. For anything deeper, head back to native C++.
db.query()has a quirky return shape. It gives younullfor no rows, a single object for exactly one row, and an array for anything more. Always check which one you got before looping over the result.Middleware must return a boolean. Return
trueto continue, orfalseto abort the route. When you abort, remember to set the response yourself; otherwise, the client gets nothing useful.Record hooks are limited. You can listen for
onRecordCreatedandonRecordUpdated, but there’s no delete hook yet.Some APIs speak JSON strings.
app.settings()andapp.auth()take and return JSON-encoded strings, so you’ll be callingJSON.parse()andJSON.stringify()yourself.Logging is lean.
consoleonly haslog,infoandtrace. For warnings and errors, useapp.logs().No heavy lifting. Duktape is a lightweight interpreter, not a JIT. It’s perfect for glue logic, validation and custom endpoints, but CPU-heavy work belongs in C++.
It’s a build-time option. Scripting only works when MantisBase is built with
MB_SCRIPTING_ENABLED=ON. Check that flag first if you compile from source.
So, which route should I pick?
Need raw speed, full control or a custom build? Go native C++. Want a new endpoint or a bit of logic in minutes, without touching the build system? Reach for a script. And the two aren’t exclusive: you can mix both in the same project.
For the full guide, check our docs.
You can watch the full video on YouTube as we look at getting started with scripting in MantisBase.
Useful links
Homepage: https://mantisbase.com
Documentation: https://docs.mantisbase.com




