A quick-lookup page for theme authors. For the concepts, start with Theme development .
Variables every template gets
Variable Contents $baseURL prefix of the install: '' at a domain root, /blog in a subfolder $site_title, $taglineFrom the Customizer (Site identity) $logo_url, $favicon_urlImage URLs, or empty $footer_textFooter text from the Customizer, or empty $primary_menu, $footer_menuMenu trees for the primary and footer locations, ready for menu_html() $seoThis page's title, description and so on, for showing (a breadcrumb, a share link). Core prints the tags itself $current_urlThe request path $custom_cssThe site's custom CSS (already printed by bh_head()) $is_hometrue on the front page$is_previewtrue when an editor is previewing a draft
Per template
Template Variables index.php$posts (rows for this page), $meta (pagination)single.php$post, $terms (its categories and tags), $comments (approved), $comments_count, $comments_openpage.php$postarchive.php$posts, $meta, $archive_type (category, tag or author), $term (for categories and tags), $author (for authors), $titlesearch.php$posts, $meta, $query
Note: On single.php and page.php, $page holds the same row as $post, not a page number. Read pagination from $meta['page'].
When the front page is set to a static page, core renders page.php for it with $is_home = true.
['page' => 2, 'per_page' => 10, 'total' => 57, 'last_page' => 6]
A post row ($post, items of $posts)
Field Notes id, uuid, slug, typetype is post or pagetitle, excerptPlain text; escape when printing contentFinished HTML on single and page templates. Print as is content_formatblocks, markdown or html: how it was written, not how it arrivesstatuspublished, or draft/pending in a previewpublished_at, created_at, updated_atUTC, Y-m-d H:i:s. Show with bh_date() author_id, author_name, author_avatar_urlThe author featured_url, featured_alt, featured_width, featured_height, featured_sizesFeatured image; use bh_post_image() comment_statusopen or closedview_countViews counted by core
A term row ($terms, $term)
id, name, slug, description, parent_id, count, and on $terms also taxonomy_slug (category or tag). Link a term with:
<?php $prefix = $t['taxonomy_slug'] === 'tag' ? '/tag/' : '/category/'; ?>
<a href="<?= htmlspecialchars(link_to($prefix . $t['slug'])) ?>"><?= htmlspecialchars($t['name']) ?></a>
id, parent_id (empty for a top-level comment), author_name, author_url, content (plain text: escape it), created_at (UTC).
Page structure
Helper Use bh_head()Echo inside <head>. Required bh_footer()Echo before </body>. Required bh_body_class($extra)Classes for <body>: is-home or is-inner, the theme slug, preview state, plus $extra bh_ajax_client()Load Basehim.ajax on the public site. Call before bh_head() bh_is_preview()true inside the Customizer's preview frame
Links and assets
Helper Returns link_to($path)$path with the install's base path, e.g. link_to('/search')\App\Core\Helpers::postUrl($post)A post's or page's path under the current permalink setting (prefix with $base) theme_asset($file, $version = true)URL of a file in this theme's assets/, with ?v= icon($name, $class)A Heroicon as inline SVG, e.g. icon('magnifying-glass', 'w-4 h-4')
Helper Use menu_html($items, $opts)Nested <ul> with dropdowns to three levels. $opts: class (default bh-menu; keep bh-menu in it for the built-in styles), aria, depth menu_at($location)Items for any location declared in theme.json menu_has_children($items)Whether any item has children menu_assets()Dropdown CSS and behaviour; echo once in <head>
<?= menu_html($primary_menu, ['class' => 'bh-menu site-nav', 'aria' => 'Primary']) ?>
<?= menu_html(menu_at('utility')) ?>
Helper Use widget_area($key)Rendered widgets of an area, or '' has_widget_area($key)Whether the area has any widgets
<?php if (has_widget_area('sidebar')): ?>
<aside><?= widget_area('sidebar') ?></aside>
<?php endif; ?>
Helper Use bh_comment_form($post, $args)Core's comment form: CSRF token, honeypot, replies, no page reload. Returns the "closed" text when comments are off bh_comment_count($post)Approved comments on a post
Mark a count so the form updates it after a new comment:
<span data-bh-comment-count="<?= (int) $post['id'] ?>"><?= (int) $comments_count ?></span>
Any element with data-bh-reply data-id="…" data-name="…" turns the form into a reply to that comment. Style hooks and options (class, button_class, label_submit, styles => false…) are listed in Customizer, menus and widgets .
Authors
Helper Returns bh_author_box($post, $args)The author box (avatar, name, bio, link). Empty when Settings → Reading → Author box on posts is off bh_author($post)Public profile: display_name, bio, slug, url, avatar_url, post_count bh_author_url($post)Path to the author's archive, or '' when archives are off or the author has no posts bh_avatar($userOrPost, $size)An avatar <img>, or initials
Images
Helper Returns bh_post_image($post, $size, $attrs)Responsive <img> of the featured image (srcset, width, height, lazy loading), or '' bh_image_url($post, $size)One size's URL; falls back to the original bh_image_sizes($post)All sizes, smallest first: name => [url, width, height]
Sizes: thumbnail (square), medium, large, full (original).
Dates and times
Stored times are UTC. These show them in the site's timezone and formats:
Helper Example output bh_date($t, $format = null)October 10, 2026 bh_time($t, $format = null)1:32 pm bh_datetime($t, $format = null)October 10, 2026 1:32 pm bh_time_ago($t, $maxDays = 7)5 minutes ago bh_time_tag($t, $format = null, $relative = false)<time datetime="2026-10-10T13:32:00+05:00">…</time>bh_iso8601($t)2026-10-10T13:32:00+05:00 bh_local_time($t)DateTimeImmutable in the site timezonebh_to_utc($local)A time typed in the site timezone, as UTC to store bh_now()Now, UTC, for storing bh_timezone()e.g. Asia/Karachi
Settings and options
Helper Returns bh_theme_option($key, $default)A Customizer option of this theme, preview-aware bh_setting($group, $key, $default)A site setting, e.g. bh_setting('reading', 'posts_per_page', 10)
SEO
Helper Use bh_seo()This page's SEO head: set(), get(), addJsonLd(), disable(), handOff() bh_seo_value($key)Read one value back, e.g. bh_seo_value('title')
See SEO, dates and images .
AI agents (WebMCP)
Helper Use bh_webmcp_form($name, $description, $opts)Attributes that describe a form to in-browser agents bh_webmcp_param($description)Describes one form field
Both return '' while WebMCP is off, so they are safe to leave in. See AI discovery .
Leave a comment