Theme Template Variables
This page is the complete reference for all values and template placeholders available to theme developers.
Themes use a double-bracket syntax: [[variable]]. This is distinct from the single-bracket handlebars syntax {{placeholder}} used inside app template files.
Theme values and app runtime values are related but not identical:
- themes use
[[user.*]]andtemplateData.user - apps use the shared runtime
profileobject available throughwindow.__shuukaCtx.profile,window.shuukaConfig.profile, or native app props
This separation lets all theme types keep their existing flow while apps reuse the same normalized owner identity payload.
Syntax Overview
| Syntax | Used in | Purpose |
|---|---|---|
[[variable]] | Theme HTML templates | Injects a platform or user value |
[[IF condition]]…[[/IF]] | Theme HTML templates | Conditional block |
[[IF condition]]…[[ELSE]]…[[/IF]] | Theme HTML templates | Conditional with fallback |
{{placeholder_key}} | App template.html | App instance setting value (apps only) |
User Values
These values describe the profile owner and are always available in the theme.
| Variable | Type | Description |
|---|---|---|
[[user.name]] | string | Full display name |
[[user.nickname]] | string | Public handle (without @) |
[[user.avatar_url]] | string | Avatar image URL |
[[user.cover_image_url]] | string | Cover / header image URL |
[[user.description]] | string | Profile bio / description |
[[user.category]] | string | Profile category label |
[[user.verification_badge]] | HTML string | Platform-rendered verification badge markup |
[[user.public_id]] | string | Public profile identifier |
[[user.locale]] | string | Active locale, e.g. en |
Usage example
<header class="profile-header">
[[IF settings.show_avatar]]
<img class="avatar" src="[[user.avatar_url]]" alt="[[user.name]]">
[[/IF]]
[[IF settings.show_title]]
<h1 class="profile-name">[[user.name]]</h1>
[[/IF]]
[[IF settings.show_nickname]]
<p class="profile-handle">@[[user.nickname]]</p>
[[/IF]]
[[IF settings.show_description]]
<p class="profile-bio">[[user.description]]</p>
[[/IF]]
</header>
Settings Visibility Flags
These booleans reflect what the profile owner has enabled. Always wrap optional content in these guards.
| Variable | Type | Description |
|---|---|---|
[[settings.show_title]] | boolean | Whether to render the display name |
[[settings.show_avatar]] | boolean | Whether to render the avatar |
[[settings.show_nickname]] | boolean | Whether to render the handle |
[[settings.show_category]] | boolean | Whether to render the category label |
[[settings.show_description]] | boolean | Whether to render the bio |
[[settings.show_cover_image]] | boolean | Whether to render the cover image |
[[settings.show_links]] | boolean | Whether links exist and should render |
[[settings.show_apps]] | boolean | Whether apps exist and should render |
[[settings.show_footnote]] | boolean | Whether to show the platform footnote |
Usage example
[[IF settings.show_cover_image]]
<div class="cover" style="background-image: url('[[user.cover_image_url]]')"></div>
[[/IF]]
[[IF settings.show_links]]
<nav class="links-section">
[[links.markup]]
</nav>
[[/IF]]
[[IF settings.show_apps]]
<section class="apps-section">
[[apps.markup]]
</section>
[[/IF]]
Rendered Markup Slots
These are pre-rendered HTML blocks provided by the platform. Drop them into your template where you want the platform-managed content to appear.
| Variable | Description |
|---|---|
[[links.markup]] | Rendered links list (social icons, URLs) |
[[apps.markup]] | Rendered app cards in a flat sequence |
[[apps.rows_markup]] | Platform-managed rows and columns for app layout (use this for grid/multi-column layouts) |
[[layout.after_markup]] | Platform-injected content after the main surface |
[[layout.outside_markup]] | Platform-injected content outside the main surface (e.g. platform-level overlays) |
[[apps.markup]] vs [[apps.rows_markup]]
- Use
[[apps.markup]]for a simple vertical list of app cards with no column logic. - Use
[[apps.rows_markup]]when the platform should handle multi-column rows. The platform groups apps into row objects and renders the HTML including responsive sizing rules.
Usage example
<main class="profile-content">
[[IF settings.show_links]]
<div class="links-grid">
[[links.markup]]
</div>
[[/IF]]
[[IF settings.show_apps]]
<div class="apps-list">
[[apps.rows_markup]]
</div>
[[/IF]]
</main>
[[layout.after_markup]]
[[layout.outside_markup]]
Layout Values
These values reflect the current layout configuration set by the platform or the profile owner.
| Variable | Type | Description |
|---|---|---|
[[layout.inline_styles]] | HTML string | Platform-injected <style> block with resolved CSS custom properties |
[[layout.article_class]] | string | Root class string for the theme article element |
[[layout.type]] | string | Active layout mode, e.g. hero, classic, sidebar, grid |
Usage example
<!DOCTYPE html>
<html lang="[[user.locale]]">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
[[layout.inline_styles]]
<link rel="stylesheet" href="./dist/theme.css">
</head>
<body>
<article class="shk-profile [[layout.article_class]]">
<!-- profile content -->
</article>
<script src="./dist/index.js"></script>
</body>
</html>
Always place [[layout.inline_styles]] in the <head> so CSS custom properties are available to your stylesheet when it loads.
Theme Config Values
Theme config is directly readable inside the template. These values come from the user's active theme configuration.
| Variable pattern | Description |
|---|---|
[[theme.config.header.show_image]] | Whether to show the header image |
[[theme.config.layout.structure]] | Layout structure key |
[[theme.config.background.color]] | Background color value |
[[theme.config.background.mode]] | Background mode (solid, gradient, image, video) |
[[theme.config.iframe.border_radius]] | App card border radius |
[[theme.config.iframe.background]] | App card background |
[[theme.config.iframe.shadow]] | App card shadow |
[[theme.config.links.alignment]] | Link icon grid alignment |
[[theme.config.links.item_size]] | Link icon size in pixels |
Usage example
<div class="app-card-wrapper" style="border-radius: [[theme.config.iframe.border_radius]]px">
<!-- app content -->
</div>
For most cases, CSS custom properties from [[layout.inline_styles]] are a better approach than inlining config values as attributes.
CSS Custom Properties (Injected at Runtime)
The platform injects these CSS custom properties into [[layout.inline_styles]]. Reference them in your theme SCSS with var(--property-name, fallback).
Wallpaper & Layout Variables
When opting into createThemeBridge({ backgroundFallback: '...' }), the platform exposes the following layout variables automatically:
| CSS Variable | Description |
|---|---|
--shk-wallpaper-background | Resolved final wallpaper value (can be a hex color or full gradient string) |
--theme-accent | Profile accent color |
--theme-text | Profile primary text color |
--theme-muted | Profile secondary text color |
App Card Variables
These are derived from the active config.iframe settings and are used in app card styling.
| CSS Variable | Description |
|---|---|
--app-card-bg | App card background |
--app-card-border | App card border shorthand |
--app-card-border-color | App card border color |
--app-card-radius | App card border radius |
--app-card-shadow | App card box shadow |
--app-card-accent | CTA / accent background color |
--app-card-accent-text | CTA / accent text color |
--app-card-padding | App card inner padding |
--app-card-embed-radius | Inner embed border radius (usually matches card radius) |
Link Icon Variables
These are derived from the active config.links settings.
| CSS Variable | Description |
|---|---|
--links-icon-size | Icon size in pixels |
--links-spacing | Space between link icons |
--links-alignment | Flex alignment value: center, flex-start, flex-end |
SCSS Usage Example
// Always provide fallbacks so your theme looks correct even before
// CSS vars are injected (e.g. during Vite dev proxy mode).
.shk-profile {
background: var(--wallpaper-color, #0a0a0f);
&::before {
background-image: var(--wallpaper-image, none);
}
}
.shk-theme__app-card {
background: var(--app-card-bg, rgba(255, 255, 255, 0.06));
border: var(--app-card-border, 1px solid rgba(255, 255, 255, 0.10));
border-radius: var(--app-card-radius, 16px);
box-shadow: var(--app-card-shadow, 0 4px 24px rgba(0, 0, 0, 0.20));
overflow: hidden;
}
.shk-theme__link {
width: var(--links-icon-size, 48px);
height: var(--links-icon-size, 48px);
}
Conditional Blocks
Use [[IF ...]] to conditionally render HTML.
Basic conditional
[[IF settings.show_avatar]]
<img class="avatar" src="[[user.avatar_url]]" alt="">
[[/IF]]
With else branch
[[IF settings.show_cover_image]]
<div class="cover" style="background-image: url('[[user.cover_image_url]]')"></div>
[[ELSE]]
<div class="cover cover--empty"></div>
[[/IF]]
Nested conditions
[[IF settings.show_apps]]
[[IF settings.show_links]]
<div class="profile-body profile-body--with-links">
[[ELSE]]
<div class="profile-body">
[[/IF]]
[[apps.markup]]
</div>
[[/IF]]
Social Links Array (JavaScript runtime)
When writing JavaScript in your theme src/index.js, the platform context object contains the user's social links.
After shuuka:contextSnapshot or shuuka:ctx message fires, the context includes:
// Available in your shuuka:ctx message handler
context.links // array of link objects
// Each link object:
{
id: 42,
type: 'instagram',
title: 'Instagram',
url: 'https://www.instagram.com/username',
icon_url: '/social_icons/shuuka-Instagram.png',
active: true
}
Most themes do not need to handle this manually — [[links.markup]] already renders the full links UI. Only use the raw links array if you need custom link rendering that the platform markup does not support.
What Themes Must NOT Do
| Wrong | Why |
|---|---|
| Hardcode profile data | User data changes; always use [[user.*]] |
Style .shk-consent-placeholder | Platform-owned, never override |
Add shadows to .billboard-app-container | Creates double-card visual glitch |
Use [[...]] syntax inside app template.html | App templates use {{...}} only |
Skip var(…, fallback) on CSS custom properties | Theme breaks in Vite dev proxy mode |
Next Step
Read Theme App-Card Integration for the complete card-style broadcast protocol, and Theme Manifest for the full theme.config.json reference.