01 · Philosophy
Built with the constraints, not around them
Kivu does not emulate a persistent application server. It treats a short-lived process as the platform contract and moves avoidable work into local build commands.
Small cold starts
Services load lazily. Config, routes and templates can be cached before deployment.
Explicit flow
Routes point to controller actions; context owns request-scoped state and rendering.
Secure defaults
Escaped templates, CSRF middleware, signed sessions and request-size limits are built in.
Shared-host portable
The deployable app is files and Perl modules — no daemon or container is required.
02 · Lifecycle
One request, one clean exit
- 01Apache invokes
public/index.cgiThe front controller captures CGI input and starts the application.
- 02Kivu builds the request context
Configuration, request limits, sessions and application services are wired.
- 03The router invokes a controller
A named route resolves to a focused
controller#action. - 04The response is finalized
Cookies and headers are emitted, the body is written, and the process exits.
03 · Frontend
Tailwind CSS and HTMX, progressively applied
Text::Xslate renders complete, accessible HTML. Tailwind supplies responsive utility styling; HTMX boosts navigation and swaps focused fragments. Forms and links still work without JavaScript.
<a class="rounded-xl bg-gold px-4 py-2 text-navy"
href="/docs">Read docs</a>
<form method="post"
hx-post="/login"
hx-target="this"
hx-swap="outerHTML">
...
</form>
The browser Tailwind build keeps this starter free of a Node build requirement. Production applications can replace it with compiled Tailwind CSS without changing template classes.
04 · Start here
Prepare a local application
cpanm --installdeps .
perl script/kivu migrate
perl script/kivu seed
perl script/smoke_test.pl
05 · CLI reference
The script/kivu commands
config:cacheWrite the merged configuration cache when it does not already exist.
routes:cacheCompile route declarations for fast production loading.
views:cachePrecompile Text::Xslate templates.
cache:clearRemove config, route and compiled-view caches.
clear:allRemove every generated cache and log file.
migrateApply pending migrations from database/migrations/.
migrate:statusShow applied and pending database migrations.
rollback [n]Revert the latest migration, or the latest n migrations.
seed [user] [pass] [email]Create the starter user; defaults to demo / demo1234 / demo@example.test.
user:superadmin <user> <email> <pass>Create a superadmin account, or promote an existing username and reset its email/password.
session:cleanupDelete expired records for the file-session driver.
secretGenerate a session secret and rotate the current value into session.previous_secret.
deploy <path>Replace a local target with the deployable project tree, then apply destination .deploy adaptations.
06 · Local workflow
Deploy to a local virtual host
The deploy command removes the destination contents before copying,
so stale files cannot survive from an earlier build. It excludes
.git, cpanfile and docs/, and
preserves a destination .deploy JSON file so host-specific
adaptations survive every redeploy.
perl script/kivu deploy ~/Sites/kivu
{
"shebang": "#!/usr/bin/perl",
"chmod": {
"script/kivu": "0755",
"public/index.cgi": "0755"
},
"files": {
"public/index.cgi": {
"shebang": "#!/usr/local/bin/perl"
}
},
"substitutions": [
{
"path": "kivu.json",
"find": "\"name\" : \"MyApp\"",
"replace": "\"name\" : \"LocalKivu\""
}
]
}
/, your home directory, or the source tree.
Top-level shebang rewrites public/index.cgi;
per-file files.*.shebang and literal/regex
substitutions cover other host tweaks.
Deploy always sets script/kivu and
public/index.cgi to mode 0755
(overridable via chmod or files.*.chmod).