{"id":14966028,"url":"https://github.com/scmorrison/uzu","last_synced_at":"2025-10-25T13:31:07.830Z","repository":{"id":77431189,"uuid":"96057247","full_name":"scmorrison/uzu","owner":"scmorrison","description":"Uzu is a static site generator with built-in web server, file modification watcher, live reload, i18n, themes, multi-page support, inject external data via local Raku module, and external pre/post command execution.","archived":false,"fork":false,"pushed_at":"2020-09-13T12:36:10.000Z","size":389,"stargazers_count":36,"open_issues_count":3,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-31T07:21:26.739Z","etag":null,"topics":["raku","static-site-generator"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scmorrison.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-03T00:49:52.000Z","updated_at":"2024-08-23T15:43:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"b565874a-956b-47a4-9b60-eb80f675d4a9","html_url":"https://github.com/scmorrison/uzu","commit_stats":{"total_commits":358,"total_committers":2,"mean_commits":179.0,"dds":"0.0027932960893854997","last_synced_commit":"40139f63a5b7da6ccd4ef64b2fd8a11d9fc53889"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scmorrison%2Fuzu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scmorrison%2Fuzu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scmorrison%2Fuzu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scmorrison%2Fuzu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scmorrison","download_url":"https://codeload.github.com/scmorrison/uzu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238147586,"owners_count":19424288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["raku","static-site-generator"],"created_at":"2024-09-24T13:35:43.351Z","updated_at":"2025-10-25T13:31:07.389Z","avatar_url":"https://github.com/scmorrison.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"Uzu (渦) [![build status](https://travis-ci.org/scmorrison/uzu.svg?branch=master)](https://travis-ci.org/scmorrison/uzu)\n===\n\nUzu is a static site generator with built-in web server, file modification watcher, live reload, i18n, themes, multi-page support, inject external data via local Raku module, and external pre/post command execution.\n\n**Note:** Uzu 0.3.6 and higher requires at least raku 2020.06.\n\n- [Features](#features)\n- [Getting started](#getting-started)\n  * [Uzu Demo Site](#uzu-demo-site)\n- [Usage](#usage)\n- [Config](#config)\n  * [Config variables](#config-variables)\n- [Project folder structure (Template6)](#project-folder-structure-template6)\n- [Project folder structure (Mustache)](#project-folder-structure-mustache)\n- [Public and Assets directories](#public-and-assets-directories)\n- [i18n YAML and Templating](#i18n-yaml-and-templating)\n  * [Nested i18n variable files](#nested-i18n-variable-files)\n  * [i18n output paths](#i18n-output-paths)\n- [Template Features](#template-features)\n  * [Template6](#template6)\n    + [Examples](#examples-template6)\n  * [Mustache](#mustache)\n    + [Examples](#examples-mustache)\n  * [Theme layouts](#theme-layouts)\n  * [Partials](#partials)\n  * [Global variables](#global-variables)\n  * [Extended variables](#extended-variables)\n  * [Page variables](#page-variables)\n  * [Template variables](#template-variables)\n  * [Layout variables](#layout-variables)\n  * [Related / linked pages](#related--linked-pages)\n- [Page render conditions](#page-render-conditions)\n- [Installation](#installation)\n- [Todo](#todo)\n- [Requirements](#requirements)\n- [Troubleshooting](#troubleshooting)\n- [Authors](#authors)\n- [Contributors](#contributors)\n- [License](#license)\n- [See also](#see-also)\n\nFeatures\n========\n* **Easy to use**: Based on existing static site generator conventions\n* **Built-in development webserver**: Test your modifications (http://localhost:3000) as you work\n* **Auto Re-render**: `uzu watch` monitors the `theme/[your-theme]/`, `pages/`, `partials/`, and `i18n/` folders for modifications and auto-renders to build\n* **Live reload**: `uzu watch` automatically reloads the browser when a re-render occurs\n* **Templating**: Supports [Template6](#template6) and [Mustache](#mustache) template engines.\n* **i18n support**: Use YAML to define each language in the `i18n/` folder (e.g. `i18n/en.yml`)\n* **Page / layout support**: Generate individual pages wrapped in the same theme layout\n* **Extended variables**: Inject dynamically generated data into project via external `Raku` module.\n* **Pre/Post commands**: Trigger external commands to execute before or after build. \n* **YAML variables**: Create page-specific and partial-specific variables as a [YAML block](#page-variables) at the top of any page or partial template.\n* **Trigger rebuild manually**: Press `r enter` to initiate a full rebuild. This is useful for when you add new files or modify files that are not actively monitored by `uzu`, e.g. images, css, fonts, or any non `.tt`, `.mustache`, or `.yml` files\n* **Actively developed**: More features coming soon (e.g. more tests, AWS, Github Pages, SSH support...)\n\n**Note**: Uzu is a work in progress. It is functional and does a bunch of cool stuff, but it isn't perfect. Please post any [issues](https://github.com/scmorrison/uzu/issues) you find.\n\nGetting started\n===============\n\nAfter [installing](#installation) uzu, run the following command from an empty directory:\n\n```\nuzu init\n```\n\nEnter your site name, default language, and template engine when prompted.\n\n## Uzu Demo Site\n\n@uzluisf has created an excellent [Uzu Demo Site](https://github.com/uzluisf/uzu-demo-site) that shows how a fully working Uzu project is organized / functions.\n\nUsage\n=====\n\n```\nUsage:\n  uzu init          - Initialize new project\n  uzu webserver     - Start local web server\n  uzu build         - Render all templates to build\n  uzu clear         - Delete build directory and all of its contents\n  uzu watch         - Start web server and re-render\n                      build on template modification\n  uzu version       - Print uzu version and exit\n\nOptional arguments:\n  \n  --config=         - Specify a custom config file\n                      Default is `config`\n\n  e.g. uzu --config=path/to/config.yml init \n\n  --no-livereload   - Disable livereload when\n                      running uzu watch.\n\n  --clear           - Delete build directory before \n                      render when running with build.\n\n  --page-filter     - Restrict build to pages starting\n                      from this directory\n\n  --theme           - Limit build / watch to single theme\n\n  e.g. uzu --theme=default build \n```\n\nConfig\n======\n\nEach project has its own `config.yml` which uses the following format:\n\n```yaml\n---\n# \n# Core variables\n#\n\n# Name of the project\nname: uzu-starter\n\n# Languages to use, determines which\n# i18n/*.yml file to use for string variables\n#\n# The first language in the list is considered\n# the default language. The defualt language\n# will render to non-suffixed files (e.g index.html).\n# All other languages will render with the\n# language as a file suffix (e.g index-fr.html,\n# index-ja.html). This will be overridable in\n# future releases.\n\nlanguage:\n  - en\n  - ja\n  - fr\n\n# i18n scheme (default: suffix)\ni18n_scheme: 'directory' # Render non-default languages to /[lang]/[page name].[extension]\n\n# Template engine\n# - Template6: tt\n# - Mustache: mustache\ntemplate_engine: mustache\n\n# Stored theme directories under themes/[theme-name]\n#\n# Themes can be specified with either the single theme\n# variable:\ntheme: default\n\n# .. or multiple themes:\nthemes:\n  - default              # Specify a theme directory using the default options\n  - summer2017:          \n      build_dir: web2017 # Override build director\n      port: 4333         # Port to start watch on for this theme.\n      exclude_pages:     # List of page template names to ignore for this theme\n        - index\n\n# Optional parameters (also, comments like this are ok)\n\n# Use a custom dev server port, default is 3000\nport: 4040\n\n# Specify a custom project root path\n# default is .\nproject_root: path/to/project/folder\n\n# List of page template names to ignore for all themes\nexclude_pages:\n  - about\n  - blog/fiji-scratch\n\n# List of directories and files to exclude from build/\nexclude:\n  - node_modules\n  - packages.json\n  - yarn.lock\n\n# Pre / post build commands\npre_command: \"webpack\"\npost_command: \"echo 'post-build command'\"\n\n# Omit .html extension from generated HTML files\nomit_html_ext: true\n```\n\n### Config variables\n\nConfig variables are defined in `config.yml`:\n\n* `name`: Project name\n* `language`: List of languages to render for site. First item is default language. When rendering, the `language` variable is set to the current rendering language and can be referenced in templates. For example, if `uzu` is rendering an `en` version of a page, then the `language` variable will be set to `en`.\n\n* `i18n_scheme`: By default `uzu` will generate files with the language suffix appended for non-default language output. (e.g. `fr`: `index-fr`). This behaviour can be set to 'directory' witch will render non-default languages to `/[lang]/[page name].[extension]` (e.g. `fr`: `/fr/index.html`).\n* `theme`: The theme to apply to the layout (themes/themename). `default` refers to the folder named `default` in the themes folder.\n* `themes`: Alternatively, using the `themes` yaml hash supports multiple themes. Themes will be rendered at the same time into their target build directories. By default the theme build directory is `build/[theme-name]`. This can be overridden with the `build_dir` variable. Relative and absolute paths are supported:\n  * `build_dir`: \n     ```yaml\n     themes:\n       - summer2017:\n           build_dir: web2017\n     ```\n  * `port`: A dev web server will spawn for rach theme specified in the `themes` yaml dict. The default port for the first theme is `3000`, this port number is incremented by one for every subsequent theme listed in the `themes` dict. This variable will override that behavior.\n     ```yaml\n     themes:\n       - summer2017:\n           port: 4444\n     ```\n  * `exclude_pages`: List page templates that should not be rendered for the associated theme. \n     ```yaml\n     themes:\n       - summer2017:\n           exclude_pages:\n             - about\n             - blog/fiji\n             - sitemap.xml\n     ```\n* `exclude`: List of directories and files to exclude from `build/`\n   ```yaml\n   exclude:\n     - node_modules\n     - packages.json\n     - yarn.lock\n   ```\n* `pre_command`: Run command prior to build step\n* `post_command`: Run command after to build step\n* `host`: Host IP for the dev server. Defaults to `127.0.0.1`.\n* `port`: Host TCP port for dev server. Defaults to `3000`.\n* `project_root`: Project root folder. Defaults to `.`.\n* `omit_html_ext`: Omit `.html` from generated HTML files.\n\n### Accessing config variables in templates\n\nConfig variables can be accessed from inside templates directly (e.g. `port`, `theme`, etc.)\n\n### Accessing non-core variables in templates\n\nNon-core variables are any additional variables found in config.yml and can be accessed in templates using `site.variablename` (e.g. `site.url`, `site.author`).\n\nProject folder structure (Template6)\n========================\n```\n├── config.yml                    # Uzu config file\n├── pages                         # Each page becomes a .html file\n│   ├── about.tt\n│   ├── index.tt\n│   └── blog                      # Pages can be nested in sub-folders. Their URI\n│       └── vacation.tt           # will follow the same path (e.g. /blog/vacation.html)\n│\n├── partials                      # Partials can be included in pages\n│   ├── footer.tt                 # and theme layouts\n│   ├── head.tt\n│   ├── home.tt\n│   ├── jumbotron.tt\n│   ├── navigation.tt\n│   └── profiles.tt\n├── public                        # Static files / assets independant of theme (copied to /)\n├── i18n                          # Language translation files\n│   └── blog\n│       └── vacation              # i18n variables can be defined for specific pages\n│           └── en.yml\n│   ├── en.yml\n│   ├── fr.yml\n│   ├── ja.yml\n└── themes                        # Project themes\n    └── default\n        ├── assets                # Theme specific static files / assets (copied to /)\n        │   ├── css\n        │   ├── favicon.ico\n        │   ├── fonts\n        │   ├── img\n        │   ├── js\n        ├── partials              # Theme specific partials. These will override any top-level\n        │   ├── footer.tt         # partials with the same file name.\n        └── layout.tt             # Theme layout file\n```\n\nProject folder structure (Mustache)\n========================\n```\n├── config.yml                    # Uzu config file\n├── pages                         # Each page becomes a .html file\n│   ├── about.mustache\n│   ├── index.mustache\n│   └── blog                      # Pages can be nested in sub-folders. Their URI\n│       └── vacation.mustache     # will follow the same path (e.g. /blog/vacation.html)\n│\n├── partials                      # Partials can be included in pages\n│   ├── footer.mustache           # and theme layouts\n│   ├── head.mustache\n│   ├── home.mustache\n│   ├── jumbotron.mustache\n│   ├── navigation.mustache\n│   └── profiles.mustache\n├── public                        # Static files / assets independant of theme (copied to /)\n├── i18n                          # Language translation files\n│   └── blog\n│       └── vacation              # i18n variables can be defined for specific pages\n│           └── en.yml\n│   ├── en.yml\n│   ├── fr.yml\n│   ├── ja.yml\n└── themes                        # Project themes\n    └── default\n        ├── assets                # Theme specific static files / assets (copied to /)\n        │   ├── css\n        │   ├── favicon.ico\n        │   ├── fonts\n        │   ├── img\n        │   ├── js\n        ├── partials              # Theme specific partials. These will override any top-level\n        │   ├── footer.tt         # partials with the same file name.\n        └── layout.mustache       # Theme layout file\n```\nSee [uzu-starter](https://github.com/scmorrison/uzu-starter) for a full example.\n\n# Public and Assets directories\n\n* `public/` - The root public directory is where project-wide static assets are stored.\n* `themes/**/assets/` - The theme's assets directory is where theme-specific static assets are stored.\n\nFiles found in either of these directories are copied wholesale to the root of the `build/` directory on successful build. For example:\n\n* `public/js/site.js` will be copied to `build/js/site.js`\n* `themes/default/assets/img/logo.png` will be copied to `build/img/logo.png`\n\n**Note:** Any tmp / swp files created by editors will also be copied into `build/`. Most editors provide options to configure this behavior. For example, you can have all `vim` `.swp` files saved into a central directory by adding something like this to `~/.vimrc`:\n\n```\nset backupdir=~/.vim/backup//\nset directory=~/.vim/swp//\n```\n\n# i18n YAML and Templating\n\nYou can separate out the content text to YAML files located in a project-root folder called `i18n`. Simply create a separate file for each language, like this:\n\n```\n─ i18n\n  ├── blog\n  │   └── vacation     # Page specific i18n variables\n  │       ├── en.yml   # en i18n variables for page pages/blog/vacation.tt\n  │       └── ja.yml   # ja i18n variables for page pages/blog/vacation.tt\n  ├── en.yml           # Main en i18n variables\n  ├── fr.yml           # Main fr i18n variables\n  └── ja.yml           # Main ja i18n variables\n```\n\nAn example i18n YAML file might look like this:\n```yaml\n---\n# Template access i18n.site_name\nsite_name: The Uzu Project Site\n\n# Template access i18n.url\nurl: https://github.com/scmorrison/uzu-starter\n\n# Template access i18n.founders\nfounders:\n  - name: Sam\n    title: \"Dish Washer\"\n  - name: Elly\n    title: CEO\n  - name: Tomo\n    title: CFO\n\n# Comments start with a #\n\n# Do not use blank values\nthis_will_break_things:\ndo_this_instead: \"\"\n```\n\n### Accessing i18n variables in templates\n\nVariables defined in i18n files can be accessed in templates using the `i18n.variablename` format (e.g. `i18n.site_name`, `i18n.founders`). \n\n```html\n\u003ch1\u003e[% i18n.site_name %]\u003c/h1\u003e\n```\n\n#### Nested i18n variable files\n\nAny variables defined in page specific i18n files, e.g. `i18n/blog/vacation/en.yml`, will override any top-level language i18n file (e.g `i18n/en.yml`) defined variables that share the same name. For example:\n\n```\n# i18n/en.yml\nsite_name: Uzu Starter Project\n```\n\n...will be overridden by:\n\n```\n# i18n/blog/vacation/en.yml\nsite_name: \"Our Vacation 2017\"\n```\n\n## i18n output paths\n\nBy default `uzu` generates language specific files with the following pattern:\n\n`[page name]-[language code].html`\n\nFor example, if the default language is `en` and secondary language is `ja`, the `index` page template would be rendered to the following files:\n\n* Default language: `build/index.html`\n* Subsequent languages: `build/index-ja.html`\n\nThis output behavior can be changed to `directory` in `config.yml` with the `i18n_scheme` variable:\n\n```yaml\ni18n_scheme: 'directory'\n```\n\nWith this option set, the output will be rendered to the following files:\n\n* Default language: `build/index.html`\n* Subsequent languages: `build/ja/index.html`\n\nTemplate Features\n=================\n\n## Template6\n\nUzu supports the [Template Toolkit](http://template-toolkit.org/) templating format for template files. This is the default template engine.\n\n### Features include:\n\n* GET and SET statements, including implicit versions\n\n     * [% get varname %]\n     * [% varname %]\n     * [% set varname = value %]\n     * [% varname = value %]\n\n* FOR statement\n\n     * [% for names as name %]\n     * [% for names -\u003e name %]\n     * [% for name in names %]\n     * [% for name = names %]\n\n     If used with Hashes, you'll need to query the .key or .value accessors.\n\n* IF/ELSIF/ELSE/UNLESS statements.\n\n     * [% if display_links %]\n         -- do this ---\n       [% else %]\n\n         -- do that --\n\n       [% end %]\n\n     * [% unless graphics %]\n\n         -- some html ---\n\n       [% end %]\n\n* Querying nested data structures using a simple dot operator syntax.\n* CALL and DEFAULT statements.\n* INSERT, INCLUDE and PROCESS statements.\n\n### Examples (Template6)\n\n### Single i18n variable\n\n```html\n\u003ca class=\"navbar-brand\" href=\"/\"\u003e[% i18n.site_name %]\u003c/a\u003e\n```\n\n### For loop from yaml dict (non-core variable) defined in config.yml\n```html\n\u003ch1\u003eCompany Founders\u003c/h1\u003e\n\u003cul\u003e\n[% for founder in site.founders %]\n  \u003cli\u003e[% founder.name %], [% founder.title %]\u003c/a\u003e\n[% end %]\n\u003c/ul\u003e\n```\n\n### IF/ELSEIF/UNLESS\n```html\n[% if site.graphics %]\n    \u003cimg src=\"[% images %]/logo.gif\" align=right width=60 height=40\u003e\n[% end %]\n```\n\n## Mustache\n\nUzu also supports the [Mustache](http://mustache.github.io/) templating format for template files. \n\nEnable mustache support by adding the following line to your `config.yml`:\n\n`template_engine: mustache`\n\nFor example:\n\n```yaml\n---\nname: mysite\nlanguage:\n  - en\ntheme: default\ntemplate_engine: mustache\n```\n\n### Examples (Mustache)\n\n### Single i18n variable\n\n```html\n\u003ca class=\"navbar-brand\" href=\"/\"\u003e{{ i18n.site_name }}\u003c/a\u003e\n```\n\n### For loop from yaml dict (non-core variable) defined in config.yml\n```html\n\u003ch1\u003eCompany Founders\u003c/h1\u003e\n\u003cul\u003e\n{{#founders}}\n  \u003cli\u003e{{ name }}, {{ title }}\u003c/a\u003e\n{{/founders}}\n\u003c/ul\u003e\n```\n\n### If conditionals\n\nMustache is a 'logic-less' templating system, but you can test for the existence of a variable, and if it exists then anything inside the test block with be processed. Otherwise it is ignored.\n\n```html\n{{#site.graphics}}\n    \u003cimg src=\"{{ images }}/logo.gif\" align=right width=60 height=40\u003e\n{{/site.graphics}}\n```\n\n## Theme layouts\n\nTheme layout templates are located at the `themes/THEME_NAME/layout.tt` or `themes/THEME_NAME/layout.mustache`. Use the `content` partial to include rendered page content in a layout.\n\nFor `Template6`:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"[% language %]\"\u003e\n[% INCLUDE \"head\" %]\n    \u003cbody\u003e\n      [% INCLUDE \"navigation\" %]\n      \u003c!-- Rendered page content --\u003e\n      [% INCLUDE \"content\" %]\n      [% INCLUDE \"footer\" %]\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nFor `Mustache`:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"{{ language }}\"\u003e\n{{\u003e head }}\n    \u003cbody\u003e\n      {{\u003e navigation }}\n      \u003c!-- Rendered page content --\u003e\n      {{\u003e content }}\n      {{\u003e footer }}\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Partials \n\nPartials are stored in the `partials` and `themes/THEME_NAME/partials` directories. Any theme partial will override any partial found in the top-level `partials` directory with the same file name. Partials can be include in layouts, pages, and other partials.\n\nFor `Template6`:\n\n```html\n[% INCLUDE \"navigation\" %]\n\u003cdiv\u003e\n    [% INCLUDE \"login_form\" %]\n\u003c/div\u003e\n```\n\nFor `Mustache`:\n\n```html\n{{\u003e navigation }}\n\u003cdiv\u003e\n    {{\u003e login_form }}\n\u003c/div\u003e\n```\n\n## Global variables\n\nSome variables are generated dynamically and exposed to templates for use:\n\n* **language**: The current language as a string (e.g. `en`, `ja`, etc.)\n* **lang_**: The `lang_CURRENT_LANG` variable provides the current rendering language. This is useful if you want to display certain content depending on the i18n language.\n    \n    For `Template6`:\n\n    ```html\n    [% if lang_en %]\n    \u003ca href='/index-ja.html'\u003e日本語\u003c/a\u003e\n    [% end %]\n    [% if lang_ja %]\n    \u003ca href='/'\u003eEnglish\u003c/a\u003e\n    [% end %]\n\n    ```\n\n    For `Mustache`:\n\n    ```html\n    {{#lang_en}}\n    \u003ca href='/index-ja.html'\u003e日本語\u003c/a\u003e\n    {{/lang_en}}\n    {{#lang_ja}}\n    \u003ca href='/'\u003eEnglish\u003c/a\u003e\n    {{/lang_ja}}\n    ```\n\n\n* **theme_**: The current theme is exposed to the templates as `theme_NAME_OF_THEM`. For example, the variable `theme_default` will be available if the `default` theme is being used:\n\n    For `Template6`:\n\n    ```html\n    [% if theme_default %]\n    [% INCLUDE \"default_header\" %]\n    [% end %]\n\n    [% if theme_enoshima %]\n    [% INCLUDE \"enoshima_header\" %]\n    [% end %]\n    ```\n\n    For `Mustache`:\n\n    ```html\n    {{#theme_default}}\n    {{\u003e default_header }}\n    {{/theme_default}}\n\n    {{#theme_enoshima}}\n    {{\u003e enoshima_header }}\n    {{/theme_enoshima}}\n    ```\n\n\n* **randnum**: A dynamically generated 16 digit integer. This value is generated any time a page is generated / regenerated.\n    ```html\n    \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"/css/site.css?v=[% randnum %]\"\u003e\n    ```\n* **dt**: A date hash that includes common date values. This is a dynamic variable that contains `datetime` data for current build.\n    ```html\n    \u003cspan\u003e\u0026copy;[% dt.year %] Uzu, Inc.\u003c/span\u003e\n\n    ```\n    Available `dt` values:\n\n    * dt.hour\n    * dt.minute\n    * dt.second\n    * dt.day\n    * dt.month\n    * dt.year\n    * dt.hh-mm-ss\n    * dt.utc\n    * dt.day-of-month\n    * dt.day-of-week\n    * dt.weekday-of-month\n    * dt.is-leap-year\n    * dt.day-of-year\n    * dt.week-year\n    * dt.daycount\n    * dt.week-number\n    * dt.days-in-month\n    * dt.week\n    * dt.yyyy-mm-dd\n    * dt.timezone\n\n### Extended variables\n\nUzu can be extended with external / dynamically generated data provided via a local `Raku` module.\n\nIn order to inject external data into your project you must use the `PERL6LIB` environment variable when running `uzu`:\n\n```\nPERL6LIB=lib uzu watch\n```\n\nCreate your module, for example `MyApp`, in your `uzu` project directory under `lib` (e.g. `lib/MyApp.pm6`). The app must export a subroutine named `context()`. This is `uzu`'s entry point:\n\n```raku\n# lib/MyApp.pm6\n\nunit module MyApp;\n\nour sub context(--\u003e Hash) {\n    return %{\n        number_of_products =\u003e get-remote-product-count(),\n        favorite_food      =\u003e 'Bean Burrito',\n    }\n}\n```\n\nAdd the name of your `Raku` module to your config as `extended` (do not add the module file extension):\n\n```yaml\nextended: 'MyApp'\n```\n\nWhen `uzu` starts it will attempt to load the local module and inject the `Hash` returned by `context()` into the global render context Hash. The keys defined in the injected Hash will be available from within templates.\n\n```html\n\u003cspan\u003eTotal Products: [% number_of_products %]\u003c/span\u003e\n```\n\nIf `\u0026MyApp::context()` is unavailable, `uzu` will print a message indicating that `MyApp` or `\u0026MyApp::context()` could not be loaded.\n\nThe external module will be executed on every build by default. To disable this behavior while using the local dev server (`uzu watch`) set the config variable `refresh_extended` to `false` in your config.yml:\n\n```yaml\nrefresh_extended: false\n```\n\n### Page variables\n\nThe `page` hash, accessible from within templates, includes the following details:\n\n* `page.id`: The internal page ID within the site index (e.g. `/index`, `/path/to/page`)\n* `page.extension`: The file extension used for the render (e.g. `html`, `json`)\n* `page.path`: The full resource path for the page (e.g. `/index.html`, `/path/to/page.html`)\n\nTo access these variables inside of a template use the following format:\n\nFor `Template6`:\n\n```html\n[% page.id %]\n[% page.extension %]\n[% page.path %]\n```\n\n...and for `Mustache`:\n\n```html\n{{ page.id }}\n{{ page.extension }}\n{{ page.path }}\n```\n\n### Template variables\n\nYou can define variables using a yaml block at the top of any page or partial (`pages/`, `partials/`):\n\n`pages/index.tt`\n\n```html\n---\ntitle: 'Welcome to Uzu'\nsubtitle:  'The best'\n---\n```\n\nTo access these variables inside of a template you do not need to use the `i18n.` scope prefix.\n\nFor `Template6`:\n\n`partials/head.tt`\n\n```html\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003ctitle\u003e[% title %] - [% subtitle %]\u003c/title\u003e\n\u003c/head\u003e\n```\n\n...and for `Mustache`:\n\n`partials/head.mustache`\n\n```html\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003ctitle\u003e{{ title }} - {{ subtitle }}\u003c/title\u003e\n\u003c/head\u003e\n```\n\n### Layout variables\n\nYou can define variables in the layout template and access them using the `layout.` prefix in templates;\n\nFor example:\n\nDefine yaml definitions in `themes/**/layout.tt` or `themes/**/layout.mustache`:\n\n```\n---\nroot_url: https://www.raku.org\nname: Dark Theme\n---\n\u003c!doctype html\u003e\n\u003chtml\u003e\n...\n```\n\nWill be accessible in templates like this:\n\nFor `Template6`:\n\n```\n\u003ca href=\"[% layout.root_url %]/about-this-theme.html\"\u003e[% layout.name %]\u003c/a\u003e\n```\n\n...and for `Mustache`:\n\n```\n\u003ca href=\"{{ layout.root_url }}/about-this-theme.html\"\u003e{{ layout.name }}\u003c/a\u003e\n```\n\n### Related / linked pages\n\nUzu will append any yaml dict ending with `_pages` with additional page-related variables if the variables are defined in the associated page template.\n\nFor `Template6`:\n\n```html\n---\nrelated_pages:\n    - page: about\n    - page: blog/fiji\n    - page: https://www.raku.org\n      title: The Raku Programming Language\n      author: Raku\n---\n\u003cul\u003e\n[% for rp in related_pages %]\n    \u003cli\u003e\n        \u003ca href=\"[% rp.url %]\"\u003e[% rp.title %]\u003c/a\u003e [[% rp.author %]]\n    \u003c/li\u003e\n[% end %]\n\u003c/ul\u003e\n```\n\n...and for `Mustache`:\n\n```html\n\u003cul\u003e\n{{#related_pages}}\n    \u003cli\u003e\n        \u003ca href=\"{{ url }}\"\u003e{{ title }}\u003c/a\u003e [{{ author }}]\n    \u003c/li\u003e\n{{/related_pages}}\n\u003c/ul\u003e\n```\n\nThe above produces the following HTML. Note that the `author` and `title` values are pulled from the related page's template yaml variables: \n\n```html\n\u003cul\u003e\n    \u003cli\u003e\n        \u003ca href=\"/about.html\"\u003eAbout Us\u003c/a\u003e [Camelia]\n    \u003c/li\u003e\n    \u003cli\u003e\n        \u003ca href=\"/blog/fiji.html\"\u003eFiji Vacation\u003c/a\u003e [Camelia]\n    \u003c/li\u003e\n    \u003cli\u003e\n        \u003ca href=\"https://www.raku.org\"\u003eThe Raku Programming Language\u003c/a\u003e [Raku]\n    \u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### Disable layout rendering for page template\n\nTo disable layout rendering for specific pages add the `nolayout` variable to the page's yaml variables:\n\n```yaml\n---\nnolayout: true\n---\n```\n\n# Page render conditions\n\nIn order to reduce build times Uzu will try to avoid rerendering a page if it hasn't been modified.\n\nPages will only be rendered under the following conditions:\n\n* Rendered page does not exist in `build` directory\n* The page template has been modified\n* A partial file included in the layout, page, or any partial included in the page has been modified\n* The page includes a related / linked pages `_pages` yaml dict and one of the linked pages templates has been modified\n* Running `uzu --clear build` will rebuild all pages\n* Pressing `c enter` while running `uzu watch` will rebuild all pages\n\nInstallation\n============\n\n```\nzef install Uzu\n```\nInstallation issue? See [Troubleshooting](#troubleshooting).\n\nTodo\n====\n\n* More tests\n* Uglify JS / CSS\n* Build deploy process push to remote services\n* Features\n  * Additional templating support (markdown)\n  * Dynamic variables (categories, tags, pagination) \n\nRequirements\n============\n\n* [Raku](http://raku.org/)\n\nTroubleshooting\n===============\n\n* **Errors installing from previous version:**\n  \n  Remove the zef tmp / store uzu.git directories:\n\n  ```\n  # Delete these folders from your zef install \n  # directory.\n  rm -rf ~/.zef/store/uzu.git ~/.zef/tmp/uzu.git \n  ```\n\n  In some instances it might help to delete your local `~/.raku/precomp` directory. \n\n* **Tests failing during install**\n\nSometimes tests might fail during install. Try re-installing all of the dependencies via `zef`:\n\n```\nzef install --force-install --/test \\\n    File::Directory::Tree \\\n    File::Find File::Temp \\\n    Terminal::ANSIColor \\\n    Template6 \\\n    Template::Mustache \\\n    Test::Output \\\n    HTTP::Parser \\\n    HTTP::Server::Tiny \\\n    YAMLish;\n```\n\nIn some instances it might help to delete your local `~/.raku/precomp` directory. \n\nIf installing from source, remove the `lib/.precomp` folder inside the `uzu` root folder and attempt the install again.\n\nAuthors\n=======\n\n* [Sam Morrison](@samcns)\n\nContributors\n============\n\n* [ab5tract ](@ab5tract)\n\n\nLicense\n=======\n\nUzu is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0. (Note that, unlike the Artistic License 1.0, version 2.0 is GPL compatible by itself, hence there is no benefit to having an Artistic 2.0 / GPL disjunction.) See the file LICENSE for details.\n\nSee also\n========\n\n* [Template6](https://github.com/supernovus/template6)\n* [Mustache](https://github.com/softmoth/p6-Template-Mustache/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscmorrison%2Fuzu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscmorrison%2Fuzu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscmorrison%2Fuzu/lists"}