Themes
Themes define how Batoi Press renders public pages and posts. A theme should keep presentation separate from stored content.
Theme Goals
- Keep layout and visual design outside content files.
- Use reusable templates for pages, posts, navigation, and shared sections.
- Keep uploaded assets in the typed asset store so the
/assets/{path}route and static exporter can resolve them consistently. - Keep private configuration outside direct public access.
Typical Theme Responsibilities
- Page shell and header.
- Navigation and footer.
- Page and post layouts.
- Content body rendering.
- CSS, JavaScript, image, font, and declared theme assets.
- Site-managed text, logo, and logo-plus-text public branding modes.
- Admin-managed theme activation, preview, duplication, template editing, snapshots, and restore.
Custom CSS and JavaScript uploads are stored separately from versioned third-party libraries. A library package declares its CSS and JavaScript entry points in a root library.json; administrators can install multiple versions, activate one version per library, and choose whether its entries load globally in the public theme. Theme-owned files remain in the theme directory.
Theme manifests are normalized to a schema-versioned contract. Themes can declare ordered styles and scripts, media attributes, defer, async, module loading, and bundled assets served through safe /theme-assets/{theme}/{path} URLs. Layouts and partials receive theme and branding context so public headers can render configured site identity without hardcoding a logo.
The bundled Batoi Versatile theme extends the default presentation surface for company, service, editorial, campaign, and ecommerce-style content pages. Version 3.0.0 supports professional primary and footer menu locations, stable hierarchy, dropdowns, nested children, mega menus, keyboard controls, mobile behavior, static-export parity, featured post images with alternative text, post subtitles and previous/next navigation, per-page Latest posts sections, post sidebar layouts, reusable sidebar widgets, responsive navigation, structured footer markup, reusable hero/section/card/statistics/product/form/contact components, and manifest-declared page templates such as landing, shop, product, cart, checkout, customer account, and contact. These ecommerce layouts are presentation and handoff templates only; inventory, pricing rules, persistent carts, authentication, payments, tax, shipping, and order processing remain outside the Batoi Press scope.
Batoi Versatile is listed on Batoi Exchange as a Website Themes asset. The Exchange record is the public catalog and trust surface for theme version, documentation, compatibility, release provenance, and support ownership.
The default theme uses these layout files:
radpress/theme/default/layouts/base.php
radpress/theme/default/layouts/page.php
radpress/theme/default/layouts/post.php
radpress/theme/default/layouts/blog.php
radpress/theme/default/layouts/archive.php
radpress/theme/default/layouts/404.php
radpress/theme/default/partials/header.php
radpress/theme/default/partials/footer.php
radpress/theme/default/theme.jsonTheme layouts receive sanitized content and metadata from the engine. Theme asset URLs are versioned from the theme manifest so immutable browser caches refresh after theme updates.
Use /admin/themes for theme upload, activation, installed-theme duplication, same-slug upgrade, and previews for home, page, post, blog, archive, and 404 layouts. Duplicating an installed theme lets an administrator provide an editable theme name while Batoi Press generates a unique slug. Theme ZIP uploads ignore harmless macOS metadata entries, but valid theme packages still require theme.json and documented PHP layouts. Legacy Batoi theme archives that only contain templates/*.json are not converted during upload and should be rejected as incompatible. Use /admin/theme-templates for constrained edits to supported theme files such as partials/header.php, partials/footer.php, layouts/base.php, the Contact layout, and bundled theme CSS or JavaScript files. Optional CSS, JavaScript, and Contact layout files may start with safe starter content and be created when saved.
Upload a Theme
1. Prepare one ZIP file whose root contains theme.json. Do not wrap the theme in an extra parent directory. 2. Include only the layouts, partials, styles, scripts, images, fonts, and declared assets needed by the theme. 3. Give every theme a unique slug and a human-readable name. For an upgrade, retain the existing slug and increase the version. 4. Sign in to Batoi Press as an administrator and open /admin/themes. 5. Select **Upload Theme**, choose the ZIP file, and review the validation result before installing it. 6. Preview the installed theme against the home, page, post, blog, archive, and 404 surfaces. 7. Check primary and footer navigation, keyboard use, mobile behavior, light and dark modes when supported, image alternative text, and error pages. 8. Activate the theme only after preview verification. Keep the previously active theme available until the public site has been checked.
An upload must be rejected when theme.json is missing, required layouts are absent, paths escape the theme directory, PHP is placed in an unsupported file, or the archive uses an incompatible legacy format. Uploading a theme does not activate it.
Author a Batoi Press Theme with UIF
UIF is optional for public themes. When you use it, load a local, versioned UIF stylesheet and script declared by the theme instead of fetching an unpinned runtime from a third party.
1. Start with the Batoi Press theme directory contract and create theme.json, layouts/, partials/, and assets/. 2. Define the base document, skip link, header, primary navigation, main landmark, and footer in layouts/base.php and the shared partials. 3. Add page, post, blog, archive, and 404 layouts. Treat all content passed to the theme as data that must be escaped for its output context. 4. Copy the approved UIF distribution into the theme assets or declare the bundled local assets supported by the target Press release. 5. Use semantic UIF classes and tokens for layout, controls, cards, tables, notices, and typography. Keep content fields independent of presentation classes. 6. Declare ordered CSS and JavaScript entries in theme.json, including module, defer, async, and media behavior where applicable. 7. Test without JavaScript first, then verify progressive enhancement, reduced motion, keyboard navigation, zoom, narrow screens, and both color modes. 8. Package the theme root as a ZIP and follow the upload workflow above.
Author a Reusable UIF Widget
A Press widget should be a small, reusable partial with explicit input data. It must not read arbitrary request values, query a database, or create its own publication authority.
1. Define the widget purpose, allowed fields, empty state, and accessibility name. 2. Add a partial such as partials/widgets/callout.php and pass it a bounded associative array from the layout. 3. Escape text with htmlspecialchars, validate URLs before using them in href or src, and reject unsupported markup. 4. Use UIF classes and data-uif-* attributes only for progressive enhancement. The core message and action must remain usable before UIF starts. 5. Scope widget styles under a stable widget class. Do not override global element selectors or theme tokens inside the widget. 6. If JavaScript inserts new icon hosts or components, initialize only the widget subtree and provide a cleanup path when the widget is removed. 7. Test the widget with missing, short, long, and right-to-left text; keyboard navigation; 200 percent zoom; narrow screens; and light and dark tokens.
Example partial:
<?php
$title = htmlspecialchars((string)($widget['title'] ?? ''), ENT_QUOTES, 'UTF-8');
$copy = htmlspecialchars((string)($widget['copy'] ?? ''), ENT_QUOTES, 'UTF-8');
?>
<aside class="press-callout uif-card" aria-labelledby="press-callout-title">
<span data-uif-icon="info" aria-hidden="true"></span>
<h2 id="press-callout-title"><?php echo $title; ?></h2>
<p><?php echo $copy; ?></p>
</aside>See Batoi UIF and AIF for the Press runtime boundary, UIF Icons for icon initialization, and UIF Tokens and Theming for color-mode implementation.
Design Guidance
Use simple, predictable templates. Batoi Press is intended for compact public sites, not heavy application dashboards. Public themes may use the bundled UIF primitives, but they are not required to.