Repository navigation
API Pages
Caligrafy Quill 2.26.0. Generated from the source by
php qa/build-api-reference.php; the guides explain how to use these classes, this reference says exactly what each public method takes and returns. Back to the API reference.
Rendering pages: the controller base class, the page controller of Route::page, views and design styles.
| Class | What it is |
|---|---|
Caligrafy\Controller |
Parent Class that defines the properties and methods of a controller |
Caligrafy\PageController |
Route::page('/books/{id}', 'Books/show', ['data' => ['book' => 'get_book']]) renders a view through this controller: 1. access: 'signedIn' => true sends visitors to /login; 'level' => N also sends people below level N to |
Caligrafy\View |
Class View is the view renderer of the application |
Caligrafy\Designs |
A style is a DESIGN.md and the override stylesheet written from it, public/css/designs/<name>.css. |
Caligrafy\HttpCache |
A capability declared with cache (#[Capability(..., readOnly: true, public: true, cache: 30)]) answered over REST, or a page declared with Route::page(..., ['cache' => 30]), is sent with Cache-Control: public, ... |
Parent Class that defines the properties and methods of a controller
Its 17 public methods have a page of their own: Caligrafy\Controller.
namespace Caligrafy;
class PageController extends ControllerSource: framework/core/PageController.php:25
Class PageController Route::page('/books/{id}', 'Books/show', ['data' => ['book' => 'get_book']]) renders a view through this controller:
- access: 'signedIn' => true sends visitors to /login; 'level' => N also sends people below level N to /notAuthorized (Auth::guard on Context::$levelAttribute)
- data: each 'data' entry calls a read-only capability as the person who opens the page ($this->call(): the same rules as REST and MCP), with the query string and the route variables as inputs (the route variables win), or with the inputs it lists (['book' => ['get_book', ['id' => 3]]]). A refusal becomes the page's answer: a visitor is sent to sign in; otherwise 403 (error 1006) or 404 (error 1005), or the 'notFound' view (route variables, 'with', 'message', who opens it) with a 404 status
- the view gets the route variables, 'with' values, the data, 'authorized' and 'user' (id, username, level) - never the query string Pages never read models: capabilities do, so a page, REST and AI agents follow the same rules.
RESERVED = array('authorized', 'user')
->__construct()->render()PageController::admit()PageController::identity()PageController::signInAddress()PageController::routeVariables()
public function __construct()Nothing to connect for a page without data: the controller is set up when a capability is called
Source: framework/core/PageController.php:32
public function render($view, array $options = array())Parameters
-
$viewstring: the view, as for view(): 'Books/show' -
$optionsarray, defaultarray(): 'signedIn' (bool), 'level' (int), 'data' (array name => read-only capability or [capability, inputs]), 'with' (array of fixed view data), 'notFound' (a view for 404s); 2.20.0: 'visitorsOnly' (a path: signed-in people go there), 'comeBack' (bool: visitors come back here after signing in), 'query' (names of the query string the view gets, as strings, '' when absent); 2.26.0: 'cache' (seconds a visitor's copy may be shared, see HttpCache)
Source: framework/core/PageController.php:44
public static function admit(array $options, $label)The access options of Route::page and Route::action: 'signedIn', 'level', 'comeBack', 'visitorsOnly'
Parameters
-
$optionsarray $label
Returns bool: true when the person was sent elsewhere
Source: framework/core/PageController.php:107
public static function identity()Who opens the page: 'authorized' and 'user' (id, username, level), for every view the page controller renders
Source: framework/core/PageController.php:132
public static function signInAddress()The sign-in page, with this page and its query string to come back to (2.20.0, 'comeBack'): /login?return=/books/3%3Fpage%3D2. Route::auth goes back there after signing in.
Source: framework/core/PageController.php:145
public static function routeVariables()The variables of the route pattern only (/books/{id} -> id), not the query string
Source: framework/core/PageController.php:156
namespace Caligrafy;
class View extends \stdClassSource: framework/core/View.php:21
Class View is the view renderer of the application
public $viewNamepublic $viewData
public function __construct($viewName, $viewData = array())No doc comment.
Parameters
$viewName-
$viewData, defaultarray()
Source: framework/core/View.php:28
public static function display($path, array $data = array())Prints a Pug file (2.19.0). A view already compiled and up to date runs through Phug's Optimizer, which includes the compiled PHP without building Phug's compiler (3 classes instead of about 100); a view to compile, or a project that customized Phug at run time (its renderer already built), goes through Phug's renderer as before.
Parameters
$path-
$dataarray, defaultarray()
Source: framework/core/View.php:49
public static function debug()Phug's debug mode (line numbers of the Pug file in errors) only with APP_DEBUG=true: it makes every page about three times slower (2.19.0)
Source: framework/core/View.php:80
public static function cache()Compiled templates are kept between requests: a view is compiled to PHP once, then again only when it or a file it includes or extends changes. On by default; VIEW_CACHE=false compiles every view on every request. A project that sets Phug's cache_dir itself keeps its own. Returns the folder used, or null (no cache). Also sets Phug's debug mode from APP_DEBUG.
Source: framework/core/View.php:91
public static function cacheFolder()A folder of the system's temporary directory for this project and this system user only (compiled templates are PHP that runs): created private (0700), refused when someone else owns it or it cannot be written. Views compiled in debug mode are kept apart (the cache does not know the options a view was compiled with).
Source: framework/core/View.php:109
namespace Caligrafy;
class DesignsSource: framework/core/Designs.php:21
Class Designs A style is a DESIGN.md and the override stylesheet written from it, public/css/designs/<name>.css. DESIGN.md files are looked up in this order, the first one wins on a name clash:
application/design/<name>/ the project's own styles
framework/design/local/<name>/ styles added to Caligrafy itself
framework/design/vendor/<vendor>/<name>/ collections copied from elsewhere (awesome-design-md...), by vendor name
The layout loads that stylesheet after the Caligrafy stylesheets when DESIGN_STYLE names it; an empty DESIGN_STYLE, an unknown name or a style without its stylesheet keeps Caligrafy's own look.
VENDOR = 'framework/design/vendor'LOCAL = 'framework/design/local'APPLICATION = 'application/design'STYLESHEETS = 'public/css/designs'
Designs::name()Designs::setting()Designs::sources()Designs::all()Designs::available()Designs::source()Designs::find()Designs::stylesheet()Designs::stylesheetUrl()Designs::describe()Designs::status()Designs::cli()
public static function name($value)The style name of a value when it is a valid one (lowercase letters, digits, dot, dash, underscore), else ''
Parameters
$value
Source: framework/core/Designs.php:31
public static function setting()DESIGN_STYLE as loaded from .env (raw, trimmed): '' means Caligrafy's own look
Source: framework/core/Designs.php:40
public static function sources($root = '.')The folders that hold styles, first one wins: label => folder relative to the root
Parameters
-
$root, default'.'
Source: framework/core/Designs.php:49
public static function all($name, $root = '.')Every DESIGN.md of a name, in lookup order (the first one is used): label => path
Parameters
$name-
$root, default'.'
Source: framework/core/Designs.php:63
public static function available($root = '.')The styles available, name => path of the DESIGN.md that is used (application, then local, then vendors)
Parameters
-
$root, default'.'
Source: framework/core/Designs.php:78
public static function source($file, $root = '.')Where a DESIGN.md comes from: application, local or vendor/<vendor>
Parameters
$file-
$root, default'.'
Source: framework/core/Designs.php:94
public static function find($name, $root = '.')The DESIGN.md of a style, null when there is none
Parameters
$name-
$root, default'.'
Source: framework/core/Designs.php:105
public static function stylesheet($name, $root = '.')Path of the override stylesheet of a style (it may not exist yet)
Parameters
$name-
$root, default'.'
Source: framework/core/Designs.php:114
public static function stylesheetUrl($public, $root = '.')URL of the stylesheet of the selected style, versioned by its modification time, or '' for Caligrafy's own look
Parameters
$public-
$root, default'.'
Source: framework/core/Designs.php:122
public static function describe($file, $max = 110)One line describing a style: the description of its front matter, else its first paragraph
Parameters
$file-
$max, default110
Source: framework/core/Designs.php:133
public static function status($root = '.')The state of the selected style, for doctor and design status
Parameters
-
$root, default'.'
Returns array: [status OK|WARN, message, fix]
Source: framework/core/Designs.php:155
public static function cli(array $args, $root = '.', $envFile = '.env')php caligrafer.php design list | show <name> | use <name> | off | status
Parameters
-
$argsarray -
$root, default'.' -
$envFile, default'.env'
Returns int: exit code
Source: framework/core/Designs.php:183
namespace Caligrafy;
class HttpCacheSource: framework/core/HttpCache.php:23
Class HttpCache A capability declared with cache (#[Capability(..., readOnly: true, public: true, cache: 30)]) answered over REST, or a page declared with Route::page(..., ['cache' => 30]), is sent with Cache-Control: public, max-age=30 when the request is a GET or HEAD with no session cookie and no Authorization header: the production image's Apache cache (docker/production/cache.conf), a CDN or a proxy then answer the next visitors from memory, without PHP.
Never kept: an answer to a signed-in person or a token (it is not marked), an answer that sets a cookie (a session started while answering: a form's CSRF token) and any answer other than 200: guard() turns them into Cache-Control: private, no-store just before the headers are sent. Vary: Cookie, Authorization keeps the copy for visitors without them.
MAX = 86400
public static function publicFor($seconds)Marks the current answer public for $seconds when this request may share it
Parameters
$seconds
Returns bool: whether it was marked
Source: framework/core/HttpCache.php:33
public static function shareable()Whether this request may receive a shared answer: GET or HEAD, no session cookie, no Authorization header
Source: framework/core/HttpCache.php:52
public static function guard()Right before the headers go out: an answer that sets a cookie or is not a 200 is never kept
Source: framework/core/HttpCache.php:67
public static function reset()For tests: forget that the header callback is registered
Source: framework/core/HttpCache.php:86
Caligrafy: Describe it. Approve it. Ship it. Your idea turned into a complete app: every feature built once, for web pages, Vue apps, a REST API and AI agents, and online.
Why Caligrafy: the benefits, the measurements, and what it is not yet
-
Quickstart with Claude: describe it, approve it, ship it
or the Quickstart: the same three steps by hand, in 5 minutes
- How Caligrafy works: the ideas in 5 minutes
- Your first capability: build a feature, page included
-
Capabilities in depth
-
#[Capability]: every option - Scheduled jobs: capabilities on a timer
- Notifications: web push and email
- Background jobs: capabilities run later
- Migrations: database changes, in order
- The cache
-
Testing your app
- Dependency injection
- Validation rules
-
Web pages
- Views and page components
- Design styles: another look, one setting
- Declarative routes: every request, in one line
-
Route::page·Route::form·Route::auth·Route::webhook·Route::download·Route::redirect·Route::action·Route::snap· capability routes - How to export a list as CSV
- Controllers: moving one to a declared route · how to, step by step
- Forms and helpers
-
Vue apps
-
Mobile and tablet
-
REST API
-
AI agents
-
Snap Cards and the assistant
- Payments: Stripe and crypto
- Face detection and face login
- OpenAI: chat and images · Assistants
- Open models: Llama, Mistral...
- Chatbots with Watson
- Machine learning in the browser
- Metadata and social cards · search and analytics
-
Putting it online: the production image, the database at every start
-
API reference: every class and method
-
Routing ·
Route·AuthRoutes· pages ·Controller· capabilities -
Data ·
Model·Query· sign-in · jobs ·Notify· payments · AI -
Interfaces · Snap ·
Snap\Cards·Snap\Conversation· testing · tooling · helper functions
-
Routing ·
-
Caligrafer: every command
- Project · build · data · agents · jobs and tests · maintenance · deploy
- Installation, configuration and Caligrafer
- Routing · Request · Controllers · Views
- Vue: flow of information · routes · validations
- Security and upgrading
- Release notes: 2.26 · 2.25 · 2.24 · 2.23 · 2.22 · 2.21 · 2.20 · 2.19 · 2.18 · 2.17 · 2.16 · 2.15 · 2.14 · 2.13 · 2.12 · 2.11 · 2.10 · 2.9 · 2.8 · 2.7 · 2.6 · 2.5 · 2.4 · 2.3 · 2.1 · October 2026 · changelog
- Testing Caligrafy (contributors)