Tutorial: Configuring Header & Footer

Header & Footer is the admin panel where you control the structural areas of the site — the header, footer, and content templates for single posts, pages, archives, 404 pages, and search results. Each area uses a preset: a self-contained folder of PHP, SCSS, and a manifest that defines the design and its configurable settings.

This tutorial covers how to use the Header & Footer admin UI: selecting presets, adjusting settings, previewing changes, and saving.

For how to create a new preset from scratch, see Create a New Preset. For how to edit an existing preset's files, see Edit an Existing Preset.

Note: the five content tabs (Single Posts, Pages, Archives, 404, Search) below are being phased out in favor of the new Site Layout CPT — visual, Page-Builder-authored templates instead of hand-written PHP presets. A content type keeps using its preset here until you explicitly assign a Site Layout entry to it; nothing changes automatically. Header and footer are unaffected and stay preset-based permanently.


Go to WordPress Admin → Header & Footer in the admin menu. The page opens on the last active tab (or the Header tab by default).


Understanding the Tabs

The Header & Footer panel has seven tabs, one per structural area:

Tab What it controls Has configurable settings?
Header The site header rendered on every page Yes — slot groups
Footer The site footer rendered on every page Yes — slot groups
Single Posts The layout for single post pages No (empty slot_groups)
Pages The layout for static page templates No
Archives Category/tag/date archive pages No
404 The 404 Not Found page No
Search The search results page No

Header and footer presets expose configurable slots (colors, menus, widget area assignments, etc.) that appear as a settings panel in the admin UI. Content-type presets (single, pages, archives, etc.) currently have no configurable slots — they just render a pre-built layout.


How Rendering Works

The theme fires an action hook at the right place in each template file:

do_action('sanilwb_render_header')   // fired in header.php
do_action('sanilwb_render_footer')   // fired in footer.php
do_action('sanilwb_render_single')   // fired in single.php
// …and so on for page, archive, 404, search

The plugin's renderer classes listen to these hooks. When a hook fires, the renderer:

  1. Reads the active preset slug from the WordPress option sanilwb_{type}_preset.
  2. Finds the preset folder at public/presets/{type}/{slug}/.
  3. Merges the manifest defaults with saved DB settings to build the $settings array.
  4. Calls require on the preset's index.php, injecting $settings and $common as local variables.

If no preset has been saved yet for a tab, the first discovered preset is activated automatically so the frontend always renders something.


Selecting a Preset

In any tab, the top of the settings panel shows a Preset dropdown listing all available presets for that tab type.

To switch presets:

  1. Open the desired tab (e.g. Header).
  2. Click the Preset dropdown and choose a preset from the list.
  3. The settings panel below the dropdown updates to show that preset's slot groups.
  4. The preview iframe reloads to show the new preset.
  5. Click Save to make this preset the active one on the live site.

Before saving, the change only applies to the preview iframe — the live site still uses the old preset. After saving, the new preset slug is written to the WordPress option sanilwb_{type}_preset and takes effect for all visitors immediately.


Header and footer presets expose configurable slots grouped into named sections. Slots appear as form fields in the settings panel. Common slot types:

Slot type Field it shows
color Color picker
text Plain text input
toggle On/Off switch
menu_select Dropdown listing all registered WordPress nav menus
sidebar_select Dropdown listing all registered WordPress widget areas
font_family Font family picker (from the Google Fonts list)
font_weight Font weight dropdown
select Dropdown with options defined in the manifest
image_url Image URL field
shortcode Text input for a shortcode string

Change any value. The Preview iframe does not update until you click Preview Changes — it does not auto-refresh on every keystroke.


Device-Responsive Settings

Some slots support different values per device (desktop, tablet, mobile). The Header & Footer panel has a Device bar at the top that switches between Desktop, Tablet, and Mobile.

When you switch to Tablet: - Slots whose breakpoints array includes "tablet" remain visible and editable. - Slots whose breakpoints array does not include "tablet" are hidden. - Any value you set while Tablet is active is stored under the slot's __tablet key.

The cascade at render time: mobile → falls back to tablet → falls back to desktop if no override is set for the current device.

How to set a responsive slot value:

  1. Switch to the device you want to override (Tablet or Mobile).
  2. Change the slot value in the settings panel.
  3. Switch back to Desktop to confirm the desktop value is unchanged.
  4. Click Preview Changes to verify both breakpoints in the preview.
  5. Click Save.

Previewing Changes

Click Preview Changes to refresh the preview iframe. The current (unsaved) slot values are sent as URL parameters to the isolated preview endpoint:

/?sanilwb_sl_preview={slug}&sanilwb_sl_type=header&{slot_id}={value}&...

The preview endpoint renders the preset's index.php with those values, so you see exactly what the frontend will look like with the current settings — without needing to save first.

You can safely click Preview Changes as many times as you want while adjusting settings. No data is saved until you click Save.

Content tabs (Single, Pages, Archives, etc.)

Content tabs use a real WordPress page as the preview. The preview shows the active preset rendered on a real piece of content so you can see how it looks with actual post data.

A Preview Item dropdown appears for single, page, and archive tabs. It lists up to 10 posts, pages, or categories. Select one to change what the preview iframe shows. Your selection is saved to localStorage and restored on the next page load.

Click Preview Changes to reload the iframe with the current preset (and current slot values for tabs that have settings). The URL appended to the real page URL looks like:

/post-slug/?sanilwb_content_preview=1&sanilwb_sl_type=single&sanilwb_sl_preset={slug}

Saving

Click Save in the top-right area of the panel. The save flow:

  1. The React app collects all current slot values via serialize(responsiveFieldIds).
  2. An AJAX POST sends { type, preset, settings } to sanilwb_save_sl_preset.
  3. The handler writes the active preset slug to sanilwb_{type}_preset in wp_options.
  4. The handler writes the slot settings to sanilwb_{type}_preset_settings in wp_options as a JSON object.
  5. On success, the panel refreshes the preview iframe with a new timestamp so it reloads.

After saving, isDirty resets to false and the Save button returns to its inactive state (no unsaved changes).

The "Leave site?" browser prompt: If you have unsaved changes and try to navigate away (close the tab, click another admin menu item), the browser shows a "Leave site? Changes you made may not be saved" dialog. This is intentional. The Header & Footer panel registers a beforeunload guard when isDirty is true.


Importing Demo Content

Presets that define widget areas can ship default widget content via demo_sidebars in manifest.json. When a preset has demo content, an Import Demo Content button appears in the panel.

Clicking it:

  1. Shows a confirmation dialog warning that existing content in those widget areas will be replaced.
  2. Submits a form POST to admin-post.php?action=sanilwb_sl_import_demo.
  3. PHP reads the demo_sidebars entries from the manifest and creates block or text widget instances in the matching registered sidebars.

After import, the widget areas contain the preset's default content. You can then customize those widget areas further via Appearance → Widgets.


Resetting to Defaults

Click the Reset to Defaults button (next to Save) to clear all saved slot values for the current preset on the current tab.

This does not restore a previous custom configuration — it deletes the saved settings object entirely. On the next page load, the manifest defaults are used for all slots, exactly as if the user had never configured them.

The reset is a form POST to admin-post.php?action=sanilwb_sl_preset_reset. The handler writes an empty {} to sanilwb_{type}_preset_settings and redirects back to the panel.


Where Preset Files Live

All preset files are inside the plugin at:

wp-content/plugins/sanil-website-builder/public/presets/{type}/{slug}/

For example, the default header preset files are at:

public/presets/header/default/
  manifest.json     ← slot definitions, labels, defaults
  index.php         ← PHP template that renders the header HTML
  style.scss        ← SCSS compiled to style.css
  style.css         ← compiled CSS, enqueued on every frontend page
  hooks.php         ← registers nav menus and widget areas

Presets are auto-discovered — dropping a new folder with a valid manifest.json inside the right type directory makes it appear in the admin dropdown automatically. No central registration is needed.


How Saved Settings Flow to the Frontend

When a visitor loads a page:

  1. The theme fires do_action('sanilwb_render_header').
  2. The renderer reads get_option('sanilwb_header_preset') → gets the active slug.
  3. SANILWB_SL_Presets::get_active_settings() reads get_option('sanilwb_header_preset_settings') (the saved JSON blob) and merges it over the manifest defaults to produce a flat $settings array.
  4. The renderer requires public/presets/header/{slug}/index.php with $settings and $common as local variables.
  5. The template reads from $settings using slot IDs and outputs HTML.

The $settings array:

Every slot id in the manifest becomes a key in $settings. For responsive slots, additional __tablet and __mobile suffixed keys are present:

$settings['nav_bg']           // desktop value
$settings['nav_bg__tablet']   // tablet override (may equal desktop if not set separately)
$settings['nav_bg__mobile']   // mobile override

The template never needs to check for missing keys — all keys are always present because missing saved values fall back to manifest defaults.


Common Mistakes

The preset dropdown is empty on a tab

The preset folder is missing manifest.json, or the JSON is invalid. Check the folder exists at public/presets/{type}/{slug}/manifest.json. Validate the JSON with a linter — a trailing comma or missing quote will silently break discovery.

A slot is not visible in the settings panel

The slot's breakpoints array is empty, missing, or contains invalid values. Every slot must have "breakpoints": ["desktop"] at minimum. Check manifest.json.

Slot settings aren't saving

Open the browser DevTools Network tab and look at the AJAX response for sanilwb_save_sl_preset. A nonce failure or PHP error will show in the response. Also check that the nonce (window.SanilWbSiteLayout.nonce) has not expired (nonces expire after 24 hours; a stale tab will fail).

The preview is showing the wrong preset after switching

The preview URL includes the preset slug as a parameter. If the URL is being cached by the browser, add _t={timestamp} to the end manually or click the Preview Changes button again to force a fresh request.

Resetting removed a slot value I wanted to keep

The reset is not reversible through the UI. You must re-enter the slot values manually in the settings panel.