DCBase Documentation

Last updated on 2020-02-15

Contents

    1. Introduction

    The DCBase.org website is currently managed through a git repository hosted at GitLab.com and served through a custom PHP middleware layer (backend) written in PHP creatively named DCBase. Content is produced primarily using a combination of Twig templates and Markdown or other Lightweight Markup Languages. This document consists of the primary end user documentation for that backend system.

    The problems when it came to deciding how the site should be managed were twofold, easy management without direct server access and low maintenance overhead. Which roughly translates to doing a lot with very little actual backend logic. It should be noted that in this case end user is generally equivalent to people with some level of software development experience.

    To allow the system to solve both of those problems the immediately obvious answer would have been to use a Static Site Generator which the current system resembles a great deal. However, whether you use an SSG or not is a very binary choice as using one generally excludes all possibility of any dynamic content on the server side (that is easily integrated). While using an existing system created for managing primarily dynamic content, with generally a lower barrier to entry, would have placed needless restrictions on the content structure.

    So instead what this system does is go to the halfway point between static and dynamic. In short it is the modern equivalent of Server Side Includes. In practice this means that its primary functionality is to act as a sort of frontend for Twig and the file system of the server it's on. This is why arguably the most advanced piece of functionality it has is actually packaged as a Twig extension separate from the thin layer of code that maps requests to file system paths.

    The majority of the code of the backend, Twig excluded, is actually about hiding the aged procedural ways that PHP handles many aspects of the HTTP protocol. Of course all of this is technically work that has been done elsewhere, however, the problem with most of those existing solutions is that they do too much at a level that is completely unnecessary for a simple system like this. Because all a system like this really needs is enough to not make it look like it was created in the late 20th century.

    2. The Git repository

    The repository containing the website code is publicly available here, we ask that you read the LICENSE and README files prior to contributing or using any content in the repository.

    2.1 Issues and Merge Requests

    Anyone, with a GitLab.com account, may create an issue for the project through GitLab.com issue tracker and these issues will be reviewed by a project member and appropriate action will be taken after discussion.

    In order to submit merge requests (also known as pull request) you must fork the project on GitLab.com under your account namespace in order to create a branch and an accompanying merge request. Alternatively if you have at least developer access level on the parent project you may work with merge requests directly on the parent project using branches.

    2.2 Requesting write (developer) access

    If you are directly affiliated with the Direct Connect Network Foundation as a member, and have successfully paid your membership fee for the year, you have the right to request direct write access to the organizations git repositories. When making a request for repository access state your GitLab.com user name and the email on file with the organization, to verify your member status, and a reason for your request.

    You may also directly request access through the GitLab.com interface using the "Request Access" button on the project page, however, when making a request like this it is important to know that your request being accepted depends on whether your reason and membership status can be verified.

    People who are not members of the organization, and affiliate projects who do not have member representation, may submit a request for access through GitLab.com as above. However, in such cases the request being accepted depends on previous contributions, including but not limited to the number of previously accepted merge requests or other contributions such as patches, issues or other types of content submissions or other involvement with Direct Connect or the organization.

    Long term established members of the organization, or members of multiple of its projects, may have their GitLab.com project membership moved to the group level for easier management.

    2.3 Content submissions

    Content submissions are preferred in the form of merge requests or patches within issues, unless you have write access to the project repository in which case you may make commits directly or use merge requests where appropriate. Before submitting any content, make sure you have read and understood the entirety of this documentation. This is to save both your and our time.

    Most normal content submissions should only involve content within the virtual document root (see the section on content directories) although any form of content and code submissions are welcome and will be reviewed by the relevant people.

    2.4 Automatic Deployment of changes

    Changes are currently automatically deployed to the organization's public facing web server. This is achieved through the use of Git webhooks, as commonly implemented by GitLab and GitHub, which the backend provides a trivial implementation for that simply saves the payload to a file. The server then monitors this file and does a hard reset followed by git pull on the public copy of this site whenever it detects a change.

    Because all changes are generally immediately deployed the non-content files contained in the project repository are generally locked to a single person who will manage their updates to avoid unintentionally breaking the public site in such a way that does not get resolved in a timely fashion.

    2.5 Affiliate project's and their websites

    Affiliate projects can have their own repositories that are served through the main installation of the DCBase backend under a subdomain such as projectname.dcbase.org. The content in these repositories is generally subject to the same rules and restrictions as the content in the main repository, with the notable exception that for these repositories the repository root itself is the projects virtual document root.

    The setup of the subdomain and the link between the repository and the deployment server requires a manual set up process. However, after it is done, from the point of view of the affiliate project the link requires no maintenance at all.

    To request a subdomain and a repository to be set up or a repository to be linked to the system one should contact a memeber of the organization's current board via email through dcnf (at) dcbase.org. The hosting location of the actual repository is not mandated, however, it has to be able to support either GitLab or GitHub style webhooks system in order for automatic deployment of changes to be possible. Asking a repository to be created, along with the required subdomain, under the DCNF group on GitLab.com is always the easiest option but it is not a requirement.

    Affiliate projects will have access to extend the default base style used on this site, however, they can also opt to create their own custom Twig based template for their sub-site. Affiliate projects will not be able to deploy custom PHP code through this repository.

    For more information on Direct Connect Network Foundation and affiliate projects, please head over to the main site here.

    3. Directory structure

    In this section we will go over the various directories in the git tree and their roles and associated best practices for content where relevant.

    3.1 System directories

    These are covered here for the sake of completeness, and have little relevance to maintaining the content on the site on day to day basis. They include the cache, config, public and vendor directories.

    The cache directory contains various temporary and preprocessed files including but not limited to parsed markdown blocks and files that have been pulled from the template or markdown files and git related metadata for display on the pages.

    The config directory, as its name suggests, contains various configuration files for the site. Most notable of these are the mapping of known file extensions and several global constants. These config files are written in PHP and make use of the special relationship between PHP's include and return statements to avoid global variables. In simple terms if an included file includes a return statement in global scope that file acts somewhat similar to a function body and the result is passed through the include statement to the parent file and can be assigned to a variable not unlike a value from a normal function call. The config files are annotated with PHP comments, should one need to edit them.

    The public directory is the actual document root as far as the front facing web server is concerned, however, it should only contain the index.php file that acts as the entry point for the site and backend. Any other files placed in this directory will not be tracked through git or processed by the backend. It should be noted that since symbolic links are not processed by the backend and they should be placed to the public directory on the hosting server if they are needed for specific hosted content outside of this system.

    The vendor directory has the same role as in PHP projects using Composer, however, Composer is not used in this instance so that the git repository may function as a complete self contained backup of all dependencies required to run a copy of the site at any point in time. This directory contains all the custom PHP classes for the backend, under the DCBase namespace, as well as verbatim copies of Twig and other dependencies.

    3.2 Content directories

    These cover the directories containing the actual files (templates) representing pages on the site as well as their dependencies such as JavaScript and CSS. They include the content and template directories including any sub directories.

    The template directory contains the base page template (bootstrap_base.html.twig) which pages on the site can, and most should, inherit from to achieve a consistent look across pages. It should be noted that certain aspects of pages covered in the following sections will rely on use of this base template. For example, if one wants to serve a page without inheriting from the base template one has to either inherit from a modified version of the base template or include the full HTML document structure in the pages main template file (the latter should be considered bad practice).

    Along with the base template, this directory also contains Twig macro definitions and various stock templates such as error, redirect and directory indexing templates as well as the wrapper used for serving plain markdown files.

    The content directory is what is best described as a the virtual document root of the website, anything placed here acts as if served by the backed as if it was located in the document root of the site. While the structure of the content in this directory is generally free form, for the sake of keeping things organized, several sub directories have been created. Notably anything placed in the files sub directory of this directory is by default not under version control unless explicitly versioned through gitignore. Additionally plain HTML files will not be served the default file format is considered to be Twig template file (generally with the extension .html.twig, more details are in the following section about content creation).

    We will cover the virtual document root and its use more in the next section as we move to go over the topics of page creation and editing.

    4. Content creation

    Content on the site is created mainly as Twig templates inheriting the base template that gives you the basic blocks and all necessary boilerplate HTML in the final resulting page. While covering the entirety of Twig syntax in this document is far outside the scope of it the syntax should be easy to pick up for anyone with previous experience with either programming or templating systems used by various software making use of the MVC paradigm or its variants.

    4.1 Twig syntax primer

    Here we will quickly cover the basics of Twig syntax, however, this is not intended as a replacement of reading the Twig documentation.

    • Template variables or function calls intended to produce output on the page will be surrounded by {{ and }}.
    • Block level tags, control flow and assignment statements (if, else, for, etc.) will be surrounded by {% and %}.
    • Comments will be surrounded by {# and #}.
    • Tag tokens can be printed as string literals, for example {{ '{{' }} prints the content of the literal as is on the page. This is particularly relevant when passing markdown content through Twig (see below).
    • Minus sign (-) following or preceding the above tokens inside the tag can be used for fine grained whitespace control.
    • Single new line immediately following a tag will be removed from the final output.
    • Block level tags and control flow statements will end with an end tag, for example {% endblock %} or {% endif %}
    • The {{ parent() )} statement will pull in content of the block it's used in from the parent template, without it the content is replaced.
    • Associative arrays and objects are accessed using the dot notation.
    • Any file paths referenced in Twig templates are relative from Twig's template directories (the virtual document root and the template directory specifically).
    • String concatenation is done with the tilde (~) character.

    4.2 Getting started

    For an easy starting point it is recommended to have a look at the basic empty boilerplate document in the virtual document root, under the docs/boilerplate directory, named blank_page.twig. This file is additionally annotated with Twig comments and contains superfluous blocks and template directives for all available sections of the base template.

    If you want the resulting page to be served with the .html extension it should end in .html.twig. If you want to primarily use markdown in your page the extension should be either .md or .md.twig (variants with .markdown are also accepted). For an example of such page please consult meeting.md.twig. Note that in order to allow for mixed Twig and markdown syntax, such as using any of the provided global template variables or macros, the extension used has to be a variant ending in .twig. The inline use of markdown within a regular Twig template file will be covered in a later section about the TextFormat extension provided by the backend.

    4.3 Naming pages and page lookup rules

    When considering how to name a page as well as structuring the content in the virtual document root it is important to know that the backend employs a simplistic fuzzy search based on the Request URI. For example if file foobar.html.twig exists in the virtual document root it will be accessible either as /foobar.html or /foobar (if directory /foobar does not exist). This is done to avoid creation of directories with just a single index file for the sake of the URL.

    If Request URI does not contain a file name, the lookup appends /index to the query string when looking for the file, if the requested file name extension is .html .twig will be appended to it. This means raw HTML files are not served by the backend. As a general recommendation the names should be conservatively web safe and in particular spaces should be avoided in directory and file names.

    Some of these naming rules and guidelines are also covered briefly at the header of the blank page boilerplate file, if you use the boilerplate file as a basis for your pages these notes should not be left in the final page template.

    4.4 Support for directory indexes

    If a directory exists but no suitable index file can be found with any extension directory index will be generated using the stock template directory_index. Directory indexes generated by the backend have the ability to additionally display a markdown or text README file from root of the directory being indexed. The lookup for the README is recursive and the closest reachable readme will be displayed. When markdown is used it is important to use the correct extension for the file (see above).

    4.5 Referencing local pages from Twig templates

    This is related to the use of the make_url function, as it is documented below, it should always be used for URL's relative to the address the site is hosted under (ie. local links). While from the current description of the function it may seem trivial, however, this function exists so that local links can have special processing attached to them if necessary. In other words the use of this function is for the sake of future proofing internal links.

    This requirement also affects pages written in pure markdown, and as such markdown documents containing local links should always use the .md.twig extension (or another equivalent variant) as outlined above (see also: "Twig TextFormat extension" for info about quirks related to mixing Twig and Markdown syntax).

    5. Twig Environment

    In this section we will cover the custom functions exposed to Twig templates by the backend as well as expanded syntax and predefined macros and global variables.

    5.1 Custom functions and filters

    The backend exposes a handful of custom Twig functions and filters for templates to use. On more about Twig functions see the documentation and Twig's list of built in functions.

    Unlike functions filters are applied to template variables using the pipe (|) character, so for example {{ timestamp | date_relative(now) }} would apply the below relative_date filter to template variable timestamp with now as the optional argument. Multiple filters may be applied to a single variable by repeating the syntax. On more advanced use of filters see the Twig documentation and Twig's list of built-in filters.

    date_relative([now = null])

    Filter that returns relative date representation from a time stamp and a fixed point in time (the argument now, which by default is the current time). The time can be either a unix time stamp or a standardized string representation compatible with strtotime. Example result: "3 weeks ago" or "5 minutes to go".

    git_info(files[, author_info = true])

    Function that returns an associative array of git file information such as the last time the file was changed, the commit it was changed in as well as by default information about author of the commit, including email. If multiple files are provided as an array the information about most recent of these files is returned. The intended use scenario is {% set git_info = git_info([_self, ...]) %} where _self represents the file the call is made from. If the template file includes any external files then those should be provided in the array as paths relative to the virtual document root or template directory.

    load_json(file)

    Function that loads a JSON file as an associative array and returns it. This should be used in conjunction with the set template template directory in the same way as the previous git_info function in order to be useful. If the file can not be found or accessed this function returns an empty value. Internally the PHP function json_decode is used.

    pathinfo(option)

    Filter that exposes the PHP function pathinfo for use within templates. The option argument should be the name of one of the options supported by the underlying PHP function as a string or a combination of the options as an integer. The other semantics of this filter are identical to the original PHP function.

    make_url(resource[, params])

    Function that turns relative URI into an absolute one, and appends a query string (params) if given. Generally the preferred way get the URL for local links over hard coding relative or absolute URL's or using string concatenation. The best practice is to pass all links through make_url unless you are referencing the current page or the domain root in which case use of the globals covered below is preferred.

    is_debug, page_time([format = true]), page_memory([format = true])

    This set of functions is for very coarse and unscientific performance profiling and fun statistics.

    • is_debug: returns true depending on whether the global constant DEBUG is defined or not, roughly equivalent to calling the built in Twig function constant like this constant('DEBUG').
    • page_time: returns page execution time up to the function call either formatted as a string or as a float.
    • page_memory: returns page memory usage up to the function call either formatted as a string or as bytes.

    5.2 Global template variables

    In addition to the global template variables defined by Twig the following variables are always set for all templates.

    • content_encoding: the encoding of the current page, usually the literal "utf-8".
    • base_url: the URL the backend is served under, including protocol and port, no trailing slash.
    • page_url: the full URL for the current page that corresponds to the template file.

    Adittionally a few global variables are set from templates using the set template directive.

    • theme: information about the template as an associative array, see theme.json in the template directory.
    • content_owner: translates to the literal "Direct Connect Network Foundation" (set by bootstrap_base)
    • hide_menu: should be set to true if a template wants to not have the top level menu present on the resulting page.
    • page_subtitle: should be a short, preferably one word, title describing the page may be used in the top level menu. must be set by each template inheriting the base template.
    • git_info: should be set to cache the result of the git_info template function. must be set by each template inheriting the base template, may be set by other templates and must not be set by template files not under version control (including files matching .gitignore rules).

    5.3 Predefined macros

    The backend comes with a set of predefined macros, they are defined in the macros.twig file in the template directory and imported under the name util by the base template accessing these macros is done using the dot notation, ie. {{ util.format_bytes(size) }}. The main goal of these macros is to reduce repetitive markup or do some basic tasks such as in the previous example formatting template variable with a byte size as a human readable.

    The macros include menu helpers that make the base templates menu markup generally more readable as well as sanitize_url wrapper for make_url to address inconsistent escaping issues caused by URL's that predate this system. The rest of the macros in this file are mostly trivial and self explanatory, looking at the file itself is advisable before using any of these macros. The use of the aforementioned sanitize_url macro should be avoided in the future (see caveat above).

    6. TextFormat Extension (Twig)

    Twig understandably does not provide support for any lightweight markup languages (LML) out the box. So to address this for our use case of Twig the backend comes with a simple Twig extension that allows extending the core set of Twig tags and filters with ones for third party markup parsers written in PHP.

    The extension adds both block level tags, for inline content, as well as include style tags for all supported parsers. Both the block level and include style tags support caching of the parsed content using flat files, with an optional hint to disable caching on demand.

    Twig filters are also registered, however, caching is not supported for these filters so their use is not recommended outside short trivial string literals or variables containing such content.

    Note that throughout the rest of this section markdown is used as a general example, but everything below applies for every supported lightweight markup language. In all of the following examples the tag name (ie. markdown) corresponds to the parser being used and can be replaced with the lowercased name of any supported parser.

    6.1 Block style tags

    The syntax for block style tags for including formatted content inline inside a Twig template file is outlined below. Here the extension specific additional literal token nocache controls whether the parsed content of the block is cached on the file system or not (caching always happens by default).

    Optionally, in place of the nocache token, the tag can include a depends on declaration which allows for fine grained control of when the cache corresponding to this tag will be invalidated, which by default happens only when the file containing the tag has changed. Including the depends on declaration ammends this condition to include the file or files that are referenced by it.

    {% markdown[ nocache|depends on 'path/to/another/file.ext'] %}
    Markdown formatted content here.
    {% endmarkdown %}

    6.2 Include style tags

    The syntax for including a file from within a Twig template file is shown below. Note that this tag is an extension of the standard Twig include tag so its arguments can also optionally include the same arguments as the standard tag (below represented collectively as twig_opts...). For details on the nocache and depends on arguments of this tag see the previous section on the block style tag as these behave identically for both variants.

    However, pay attention to the order in relation to any arguments inherited from the Twig include tag as the extension specific arguments must precede these other arguments, also, any twig specific arguments will be silently ignored if the included file is not processed by Twig (see below).

    {% markdown 'path/to/file.md'[ nocache|depends on 'path/to/another/file.ext' twig_opts...] %}

    If the file name above ends in .twig, such as .md.twig in the case of markdown, as outlined in earlier sections the file contents are first processed by Twig before being passed on to the respective parser implementation. Using the nocache hint for files that get processed by Twig before being rendered by this extension is usually advised so that incorrect cached information isn't displayed to the user if request specific dynamic Twig variables are used.

    6.3 The pitfalls of mixed syntax scenarios

    When external markup, parsed by the third party parsers, and Twig syntax is mixed within a block, or a file ending in .twig, it should be noted that sometimes the syntax overlaps with Twig reserved patterns and in such cases outputting these parts as string literals using Twig syntax is required. In the case of the below example, using markdown extra (as implemented by the underlying parser Parsedown), the recommended syntax to avoid conflicts with Twig in the case of the anchor syntax for headings is as follows.

    # Markdown heading {{ '{#anchor}' }} 

    Note that, either a single space, as above, or an additional newline must follow the Twig output syntax, in this case, as otherwise there might not be a new line break to end the heading (see Twig syntax rules outlined in an earlier section) in the output to be parsed as markdown by the extension.

    6.4 The metafile tag and frontmatter

    Using LML's with the backend in this fashion is all well and good, however, in order to customise the Twig template including or wrapping such markup in any way one would have to create a wrapper template file to do so. In order to decrease the cases where individually customised wrappers are required for trivial changes, to the base template, the TextFormat extension registers an additional Twig tag metafile with syntax that is nearly identical to the include style tags presented above except that this tag does not accept any parameters apart from the name of the file.

    {% metafile 'path/to/file.md' %}

    Placing the above tag into a Twig template will extract what is commonly known as "frontmatter" from the referenced file and and inject all the attributes from this data into the Twig template context, which is equivalent to using the Twig set directive to set the values inside a template file. The frontmatter has to be specified at the top of the file using one of the below syntaxes in order to be recognized.

    HTML style comments (useful for files without .twig extension)
    <!-- metadata: ... -->
    
    Twig style comments
    {# metadata: ... #}

    The data placed in between these tags should be a well formed JSON object, with named key and value pairs (ie. you can consider it to be an associative array or a map object).

    By using the metafile tag it is possible for the backend using the TextFormat extension to use a generic view for serving all files using a particular LML's while still retaining the ability to allow some customization by using the frontmatter syntax from the file included in the view.

    6.5 Adding new parsers

    In order to add support for additional parsers for this extension one must implement the simple ParserInterface interface which is declared under the DCBase\Twig\TextFormat\Parser namespace. It is recommended that all implementations also be placed in this namespace.

    Requirements for parsers to use are only that it can format and produce document fragments. This is because a parser only capable of handling or parsing full documents can not be reliably used to parse the kind of content suitable for embedding into the HTML output of the final pages. Obviously the parser also has to be either implemented in or callable from PHP, however, for parser implementations that execute system commands both security and speed, of the call outside of PHP, should be a primary concern.

    As of right now the background provides a single parser for including and parsing markdown using the implementation of markdown by Emanuil Rusev, Parsedown and its accompanying extension ParsedownExtra. The original classes are slightly augmented by a trivial extension to its table syntax using a trait defined under the namespace DCBase\Parsedown aliases for the original Parsedown classes importing this trait are also provided. This extra complexity is to provide better support for tables styled by Bootstrap, that the default style on this site uses, by expanding Parsedowns attribute syntaxt to the column definition portion of the table markup.

    Appendix A: Code and Classes

    This section contains a brief overview of the more technical aspects of the backend, including some epanded rationale on why the system exists in the form it is in.

    A1. DCBase Classes

    This section contains a brief overview of the primary classes defined in the DCBase namespace, with short descriptions of their role and purpose.

    The classes and other code included in the TextFormat extension and the accompanying Parsedown class extension are sadly outside the scope of this section. This is due to the fact that in order to understand the structure of both of these components one has to have some level of knowledge about the internals of each of the related projects and covering that in detail would require a lot more than what can reasonably be covered and maintained as part of this document. The TextFormat extension to Twig in particular can essentially be considered its own subproject, albeit a very central one in terms of easy content production, for the main DCBase system.

    ClassLoader
    This class provides the SPL autoloader implementation for the backend, it is mostly conformant with PSR-4 autoloader specification by PHP-FIG. This component is something that has been inspired by existing autoloaders from other projects and has transformed through several iterations since its initial conception.
    ConFigLoader
    This class handles loading PHP config files from within the config directory, it does so relying on the unique property of PHP's include statement when the included file contains a return statement. This is done to avoid creating variables in the global scope as much as possible.
    DirectoryList
    This class generates the template parameters array for the automatic directory indexing support of the backend from a file path, it was initially created for a different project, also using Twig, and then ported forward to this one.
    ErrorReporting
    Set of functions, wrapped in a static class, whose purpose is to format PHP errors and exceptions into a more readable format either as HTML or text (CLI).
    FrontController
    The entry point for the application, the FrontController::run method is basically the equivalent of the main() method from many programming languages. Also implements the PHP error handlers that use the ErrorReporting functions and the end points for Git Webhooks.
    GitUtil
    Collection of functions, wrapped in a static class, that interface with Git like the logic behind the webhooks implementation and the actual final implementations for the git_info template function exposed by the backend to Twig.
    WebRequest
    This class, along with its response counterpart is responsible for abstracting away the age old super globals and the procedural ways PHP deals with HTTP protocol in general. Notably this class, particularly its public interface, has been inspired by work originally done by Nils Aderman for the phpBB project, further details in the header of the file.
    WebResponse
    This is the response counterpart for the above WebRequest class. Its role is to act both as a base class and a container for factory methods of several typed response classes, among them most notably File, Text and Twig responses.
    Common\StrUtil
    This static class contains a partial set of wrappers for PHP's multibyte string functions, for better UTF-8 support, as well as what could be called serviceable implementations for a few missing ones.
    Common\Util
    Procedural style functions that really have no better place to reside in, includes for example a set of wholly unscientific functions for coarse measuring of execution time and memory usage of the PHP script. As well as function for formatting dates as string relative to a point in time (implementation for date_relative template function).
    Response\FileResponse
    This typed response represents any real file on the servers file system, served as is, includes support for NGINX specific X-Accel-Redirect server side header. Also contains theoretical support for partial downloads, however, this has only been partially tested due to git being unsuitable for large binary files to begin with. Support for HTTP caching headers.
    Response\TextResponse
    This typed response represents any text based file or generated string response, supports HTTP cache headers, for actual files, and variable mime-types.
    Response\TwigResponse
    This typed response represents anything passed through Twig, creating and managing the twig environment, also contains several auxiliary methods for building up the template parameter array. Contains implementations or wrappers to implementations for most custom template functions.
    Response\JsonResponse
    This typed response represents, usually dynamically generated, JSON response. Includes support for JSON with padding for the scenarios where it is still necessary. Does not support any HTTP cache mechanisms. Suited for API responses.
    Response\XmlResponse
    This typed response represents, usually dynamically generated, XML response supports both SimpleXml and DOMDocument out of the box, along with strings and files, however, ill-suited for static files due to lack of support for caching. Likewise suited for API responses.

    A2. DCBase: Code, Usage and Design

    The nucleus of the system is really formed around the WebRequest and WebResponse pair of classes, obviously including the various typed responses. That and the custom Twig environment.

    Generally speaking the code is using a basic Front Controller pattern, as the name of the entry point class would suggets, where every control path of its main method FrontController::run(WebRequest $request) should end in return statement that calls the send() method of an instance of WebResponse which matches the parameters of $request.

    As for the WebResponse instances, their public interface aims to be such that most of the time all that is required is a call to one of the static factory methods of the abstract parent class corresponding to the expected return type, with the correct parameters, chained directly to a send call. The best code usage examples, would actually probably be the myriad of factories defined as part of WebResponse. Particularly the ones for errors and redirects.

    Additionally, the system aims deliberately to be as stateless as possible, excluding data that is the same for every visiting user when it comes to what happens on the server side the default style add some limited state through the use of cookies. Which ironically is in part to comply with the largely useless EU directive about browser cookies.

    Drawing some parallels to the ever popular MVC pattern the Model doesn't really exist, View would correspond to the Twig template which most content pages inherit from and the only controller would be the aforementioned front controller, because there really is only one action the backend does and that is map a file (or a set of files) to a request URI. The closest thing to a model, that being the actual content of the page, would be then be the Twig template file inheriting the base template. The generic views for PDF's, page source, and markdown make the comparison a little more obvious.

    In this system the Twig templates itself are used as a both a content authoring format and tool as well as the way to present the content. Resulting in no hard boundaries existing between content and presentation but rather creating a soft boundary, through template inheritance, that the user can choose to ignore respect this boundary or not.