fontlab-www-toolkit
Shared ProperDocs + MaterialX site builder and deploy helpers used by the
FontLab web properties (www.fontlab.com, www.vexy.art, and the
api.fontlab.com/www-admin/ PHP UI).
Install
uv add fontlab-www-toolkit # in a project
uvx fontlab-www-toolkit --help # one-shot
pip install fontlab-www-toolkit
CLI
Three equivalent ways to invoke it:
fontlab-www-toolkit COMMAND # console script (works under uvx too)
fontlab-build COMMAND # backwards-compat alias
python -m fontlab_www_toolkit COMMAND
Commands:
| Command | Effect |
|---|---|
build [--skip_webflow] [--update_stubs] |
Pull Webflow stubs, build with MkDocs/ProperDocs, overlay wf_cache/ + static_docs/, publish to public/. |
pull-webflow [--update_stubs] |
Refresh wf_cache/ only. |
convert-old |
Regenerate OLD pages from src_docs/old-pages.yml. |
clean |
Delete build_docs/ and public/. |
setup [--venv PATH] [--clear] |
Create / refresh a uv venv for the admin pipeline. |
mirror --manifest_url URL --dest DIR [--dry_run] |
Mirror a static site folder over HTTPS from its manifest.json (size + SHA-256 verified, atomic folder swap). |
version |
Print the installed version. |
All commands accept --root PATH; default is the current working directory.
Mirroring a published static site
Some properties are not built by this toolkit but by their own CI — e.g. the
TTH Debugger, whose GitHub Actions build lands in
https://fontlab.dev/tth-debugger/alpha-sdx992/. Such a build exposes a
manifest.json (schema: fontlab-site-manifest/1) listing every file with
path, size, sha256, type (HTML entries may add sha256Normalized, the hash with ASCII whitespace removed), plus name, version, commit, builtAt,
baseUrl, entry. mirror consumes that:
fontlab-www-toolkit mirror \
--manifest_url https://fontlab.dev/tth-debugger/alpha-sdx992/manifest.json \
--dest /path/to/live/studio.fontlab.com/public/tth-debugger
Files already present with a matching hash are reused; everything else is
downloaded, verified, and the folder is swapped in with a rename so the live
site never sees a half-written tree. Cloudflare's injected bot-detection
<script> in HTML responses is stripped before verification. The manifest is
saved into the destination as manifest.json for provenance. Standard library
only — no extra dependencies in the admin venv.
Site repo layout it expects
Sites can set theme_assets in fontlab-www-toolkit.json to a list of HTTPS
CSS and JavaScript URLs. The builder adds missing links and deferred scripts
after all Webflow/static overlays, so imported pages use the same shared theme
as Markdown pages. Existing asset URLs are deduplicated. This is opt-in.
site/
├── src_docs/
│ ├── mkdocs.yml
│ ├── md/ # Markdown sources (+ Webflow stubs via frontmatter)
│ └── old-pages.yml # OPTIONAL — one-time HTML → MD conversions
├── static_docs/ # Copied verbatim over build_docs/ during overlay
├── wf_cache/ # Generated — Webflow snapshots
├── build_docs/ # Generated — MkDocs output
└── public/ # Generated — final publish tree
A Webflow stub is any Markdown file with frontmatter:
---
title: Page
webflow-import-url: https://example.webflow.io/page
---
Refreshing stub bodies (--update_stubs)
Normally only wf_cache/ is refreshed; the stub Markdown body stays as a
placeholder (the cached HTML overlays it at build time). Pass --update_stubs
to pull-webflow or build to also rewrite each stub's body from the
freshly cached HTML, while preserving the stub's frontmatter verbatim:
fontlab-www-toolkit pull-webflow --update_stubs
For each stub it strips non-prose noise (<script>/<style>/<noscript> and
hidden Webflow Windflow plugin metadata), serves the cleaned cached HTML over
a loopback HTTP server, and runs url22md
to extract Markdown. This requires the url22md CLI on PATH (or set
url22md_bin in config); it is an external runtime tool, not a packaged
dependency.
Configuration
You can customize the builder's behavior using a JSON configuration file (by default fontlab-www-toolkit.json in the root directory, or passed via --config CLI option). Alternatively, individual pages can specify page-specific overrides inside the input HTML:
<head>
<script id="fontlab-toolkit-config" type="application/json">
{
"cloudinary": {
"cl_responsive": {
"methodology": "legacy"
}
}
}
</script>
</head>
Global Overrides
The following settings can be overridden in the root configuration object:
frontmatter_key(string): The YAML frontmatter key used to identify Webflow URLs. Defaults to"webflow-import-url".webflow_badge_hide_css(string): CSS injected to hide the Webflow badge.old_pages_config(string): Path to the legacy pages mapping file. Defaults to"src_docs/old-pages.yml".mkdocs_command(string | array): The custom build command for MkDocs/ProperDocs. Can include the{config_file}placeholder.user_agent(string): Custom User-Agent header used when pulling Webflow pages. Defaults to"fontlab_www_toolkit".split_google_fonts(bool): When true (default), split a multi-familyfonts.googleapis.com/css2?family=A&family=B&…link into one?family=X&display=swaplink per family. This keeps web fonts loading even if a downstream step truncates the served URL at the first&(otherwise only the first family loads and the rest fall back to a system font).url22md_bin(string): Path to theurl22mdexecutable used by--update_stubs. Defaults to whatever is found onPATH.url22md_tool(int | null): Forces a specificurl22mdextraction engine (1=trafilatura,3=readability, …). Defaults to1for offline, deterministic extraction; set tonullto let url22md run its full fallback chain (may reach cloud tools).url22md_timeout(int): Per-page extraction timeout in seconds. Defaults to60.
Cloudinary Options
The cloudinary block allows automatic mapping of image URLs to Cloudinary and setup of responsive client-side loading:
{
"cloudinary": {
"cl_cloud": "mycloud",
"cl_map": {
"https://cdn.example-files.com/assets": "assets_prefix",
"https://images.example.com": "images_prefix"
},
"cl_trans": "c_limit,w_auto/f_auto,q_auto,dpr_auto/",
"cl_responsive": {
"cl_trans_thumb": "c_limit,w_128/f_auto,q_1/",
"cl_core_js": "https://unpkg.com/cloudinary-core@latest",
"methodology": "modern"
}
}
}
cl_cloud: Cloudinary cloud name.cl_map: Map of source URL prefixes to Cloudinary upload folder prefixes. Any matching image URLs found in attributes (likesrc,href,stylebackground-image) will be replaced.cl_trans: The default Cloudinary image transformation string.cl_responsive: (Optional) Enables responsive client-side images:- Adds
class="cld-responsive"to matching<img>elements. - Sets the
srcattribute to a thumbnail transformation (usingcl_trans_thumb). - Sets the
data-srcattribute to the main transformation (usingcl_trans). - Clears
srcsetto avoid browser conflict. - Injects responsive initialization scripts before the closing
</body>tag:methodology: "modern"(Recommended): Injects a lightweight vanilla JS script usingResizeObserverto update image source dynamically, avoiding heavy external library dependencies.methodology: "legacy": Injects thecloudinary-corelibrary (cl_core_js) and invokescl.responsive().
- Adds
Deploy helpers (library use)
from pathlib import Path
from fontlab_www_toolkit import DeployTarget, run_full_deploy
target = DeployTarget(
site_root=Path("/path/to/site"),
site_label="www.example.com",
local_source=Path("/path/to/site/public"),
backup_dest=Path("/path/to/web-fontlab/src/ionos/live/example.com/public"),
remote_path="live/example.com/public",
)
run_full_deploy(target, commit_message="Deploy www.example.com")
Mirrors the local backup, rsyncs to the remote, commits both the site repo and
(if present) the web-fontlab/ mirror repo.
Develop
git clone git@github.com:Fontlab/fontlab-www-toolkit.git
cd fontlab-www-toolkit
uv sync --group dev
uv run ruff check src/ tests/ # lint
uv run mypy src/fontlab_www_toolkit/ # typecheck
uv run pytest -q # test
Version comes from git tags via hatch-vcs. Tag with semver (v1.2.3) to bump.
See CHANGELOG.md for release history and src_docs/ for
full documentation covering the four-layer build flow, Webflow stub format,
wf_cache/ layout, and www-admin integration.
Publish
./publish.sh # uvx hatch clean ; uvx gitnextver ; uv build ; uv publish
Requires UV_PUBLISH_TOKEN (PyPI token) in the environment.
Release files for fontlab-www-toolkit 1.0.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fontlab_www_toolkit-1.0.14.tar.gz | 45.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fontlab_www_toolkit-1.0.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.9 kB
Release files / fontlab_www_toolkit-1.0.14.tar.gz
| Download URL | fontlab_www_toolkit-1.0.14.tar.gz |
|---|---|
| Size | 45.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
295480ec77d266646c5ba2403dc4bc292c31ccd457163ffe79e494ba102bd0c8
|
|
BLAKE2b-256 checksum How to use checksums |
81e210f51071aed2ce7480e292448ccc496c1d9b37505a04c1e6a1ee0b351e8e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / fontlab_www_toolkit-1.0.14-py3-none-any.whl
| Download URL | fontlab_www_toolkit-1.0.14-py3-none-any.whl |
|---|---|
| Size | 33.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5c59a5925b671c092aade234c2f6b1143bd2a732aff79d7dae47eda0cc149af4
|
|
BLAKE2b-256 checksum How to use checksums |
bcb632fce37bc2d0532aa4cb2372ba2d0c59d422d568a2362d7d97bb6af436f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|