Themes
Change how the hosted pages look: theme options, languages and texts in the console, or your own Handlebars templates.
The hosted pages (sign-in, sign-up, codes, two-factor, consent, account, device and errors) use a theme. The built-in 9in Default theme is designed to be branded through options; for full control, write your own theme in Handlebars.
#Edit on the preview
Themes in the console shows a live preview of every page, on desktop, tablet and phone, in each of your languages. With Edit on page on:
- Click anything (the logo, a button, the card, the background, the side panel) to see its options in the inspector on the right: accent color, corners, logo images and alignment, card border, side panel and more. The path above them (Page › Layout › Card › Button) selects the elements around it.
- Click any text to change it in place, in the language you're previewing.
- Dashed "+" chips mark things that are switched off, such as "+ Show a side panel"; click one to turn it on. Things hidden at the current screen size are listed under Hidden here.
- Show an error displays a typical error message for the page, so you can see and reword it.
Changes are previewed instantly and go live when you save. The Design tab also lists every option, and Themes switches between the built-in theme and your own.
#Logos and images
Upload images under Branding. The logo and icon there are the defaults everywhere (pages, emails, favicon); a theme can use other images from the same library for dark pages and the side panel. Uploaded files get private names made from their content, so their public URLs say nothing about the original file.
#Texts and languages
Every text on the pages and in the emails exists in English, Arabic, Chinese, French, German, Hebrew, Japanese, Persian, Russian, Spanish and Turkish. Choose your languages under Themes → Languages (and the default, used when the browser asks for none of them). Pages follow the visitor's browser, or the ui_locales parameter of the authorization request, and right-to-left languages are laid out right to left.
Change texts by clicking them in a preview, or in the full list under Translations, which also shows texts that aren't translated yet. Texts you leave alone keep getting 9in's updates.
#Per-application themes
An application can use a different theme from the rest of the tenant (Applications → app → Settings → Theme for this app), for example a product with its own brand.
#Your own theme
Themes → Import theme, or Edit code to start from the default theme in the browser editor with a live preview. A theme is a set of Handlebars templates:
layout.hbs: the page shell, with named blocks ({{#component brand}}…{{/component}}) placed with{{#render brand}}{{/render}};- one partial per page:
login,registration,otp-options,otp-verification,password-recovery,password-reset,authorization,account,logout,error,lost,redirect,device,mfa,mfa-enroll; manifest.json: the options your theme offers in the console, and the outside origins it may load.
Pages your theme doesn't include come from the default theme. Templates see translations as {{ $.login.title }}, your options as {{ theme.button_color }}, and the page's data (application, user, errors, csrf…). Scripts need nonce="{{ csp_nonce }}". Uploaded CSS, scripts and fonts are referenced as {{ assets_url }}<file name>.
Themes from SSOfy import as they are. Every variable, helper, page and manifest field is in the theme reference.
#Make your theme editable on the preview
9in works out what each option affects from your templates: anything you output from {{ theme.x }}, or show inside {{#if theme.x}}, becomes clickable, and when an option hides something, a "+" chip offers to turn it back on. Optional hints make it more precise:
{
"version": 1,
"options": {
"Look": {
"properties": {
"button_color": {
"title": "Accent color",
"type": "color",
"default": "#1a1a1a",
"target": ".btn-primary",
"css_var": "--primary",
"preview": { "page": "login", "device": "desktop" }
}
}
}
}
}target: a CSS selector for the elements an option styles, for options used only in CSS.css_var(andunit, such aspx): the custom property the option sets, so the preview updates instantly instead of re-rendering. The page also gets a9in:optionsevent ondocument, so scripts that derive colors (readable text on the accent, for example) can recompute.preview: the page and device where the option shows, so the console takes the preview there.
In a template, {{option-target "logo logo_position" name="Logo"}} inside a tag marks an element by hand and names it in the console. On real pages it writes nothing.