{"id":165,"date":"2026-08-22T03:20:27","date_gmt":"2026-08-22T03:20:27","guid":{"rendered":"https:\/\/sifency.com\/docs\/?p=165"},"modified":"2026-08-27T05:02:05","modified_gmt":"2026-08-27T05:02:05","slug":"sifency-admin-options-framework","status":"publish","type":"post","link":"https:\/\/sifency.com\/docs\/sifency-admin-options-framework\/","title":{"rendered":"Sifency Admin Option Builder"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Sifency Admin Option Builder \u2014 Documentation<\/title>\n<style>\n  :root{\n    --ink:#1b2230;\n    --ink-soft:#4b5468;\n    --paper:#f7f6f2;\n    --panel:#ffffff;\n    --line:#e2ded3;\n    --rail:#efece3;\n    --accent:#2f6f5e;\n    --accent-soft:#e4efe9;\n    --amber:#b9822f;\n    --mono-bg:#12181f;\n    --mono-fg:#dbe6e0;\n    --mono-key:#7fb8a4;\n    --mono-str:#d3a86a;\n    --radius:3px;\n    --serif: \"Iowan Old Style\",\"Palatino Linotype\",Palatino,Georgia,serif;\n    --sans: -apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif;\n    --mono: \"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;\n  }\n  *{box-sizing:border-box;}\n  html{scroll-behavior:smooth;}\n  body{\n    margin:0;\n    background:var(--paper);\n    color:var(--ink);\n    font-family:var(--sans);\n    font-size:16px;\n    line-height:1.6;\n  }\n\n  \/* ---- layout shell ---- *\/\n  .shell{display:grid;grid-template-columns:272px 1fr;min-height:100vh;}\n  @media (max-width: 880px){ .shell{grid-template-columns:1fr;} .rail{display:none;} }\n\n  .rail{\n    background:var(--rail);\n    border-right:1px solid var(--line);\n    padding:28px 22px 60px;\n    position:sticky;top:0;height:100vh;overflow-y:auto;\n  }\n  .rail-mark{\n    display:flex;align-items:baseline;gap:8px;margin-bottom:6px;\n  }\n  .rail-mark .tag{\n    font-family:var(--mono);font-size:11px;letter-spacing:.06em;\n    color:var(--accent);border:1px solid var(--accent);\n    padding:1px 6px;border-radius:2px;\n  }\n  .rail-title{\n    font-family:var(--serif);font-size:19px;font-weight:600;\n    line-height:1.25;margin:10px 0 2px;\n  }\n  .rail-sub{font-size:12.5px;color:var(--ink-soft);margin-bottom:26px;}\n\n  .rail nav{display:flex;flex-direction:column;}\n  .rail-group{margin-bottom:20px;}\n  .rail-group-label{\n    font-family:var(--mono);font-size:10.5px;letter-spacing:.09em;\n    text-transform:uppercase;color:#8a8471;margin:0 0 8px 2px;\n  }\n  .rail a{\n    display:block;color:var(--ink-soft);text-decoration:none;\n    font-size:13.5px;padding:5px 8px 5px 10px;border-radius:2px;\n    border-left:2px solid transparent;\n  }\n  .rail a:hover{color:var(--ink);background:#e6e1d3;}\n  .rail a.active{color:var(--accent);border-left-color:var(--accent);background:var(--accent-soft);font-weight:600;}\n\n  \/* ---- main content ---- *\/\n  main{padding:0;}\n  .hero{\n    padding:64px 56px 42px;\n    border-bottom:1px solid var(--line);\n    background:\n      linear-gradient(180deg, #fffefb 0%, var(--paper) 100%);\n    position:relative;\n  }\n  .hero::before{\n    content:\"\";position:absolute;top:0;left:0;right:0;height:5px;\n    background:repeating-linear-gradient(90deg, var(--accent) 0 26px, transparent 26px 30px);\n    opacity:.55;\n  }\n  .kicker{\n    font-family:var(--mono);font-size:12px;letter-spacing:.1em;color:var(--amber);\n    text-transform:uppercase;margin-bottom:14px;\n  }\n  .hero h1{\n    font-family:var(--serif);font-weight:600;font-size:44px;line-height:1.08;\n    margin:0 0 16px;max-width:16ch;color:var(--ink);\n  }\n  .hero p.lede{\n    font-size:17px;color:var(--ink-soft);max-width:62ch;margin:0 0 24px;\n  }\n  .meta-row{display:flex;flex-wrap:wrap;gap:10px;}\n  .pill{\n    font-family:var(--mono);font-size:12px;color:var(--ink-soft);\n    background:var(--panel);border:1px solid var(--line);\n    padding:5px 11px;border-radius:20px;\n  }\n\n  .content{padding:8px 56px 100px;max-width:880px;}\n\n  section{padding-top:52px;scroll-margin-top:24px;}\n  section h2{\n    font-family:var(--serif);font-size:27px;font-weight:600;\n    display:flex;align-items:baseline;gap:12px;margin:0 0 6px;\n  }\n  section h2 .num{\n    font-family:var(--mono);font-size:14px;color:var(--amber);font-weight:600;\n  }\n  section > .h2-rule{height:1px;background:var(--line);margin:14px 0 26px;}\n  h3{font-family:var(--sans);font-size:16px;font-weight:700;margin:28px 0 10px;color:var(--ink);}\n  h3 code{font-size:14px;}\n  p{color:#2c3140;}\n  .lead-note{color:var(--ink-soft);}\n\n  table{width:100%;border-collapse:collapse;margin:16px 0 26px;font-size:14.5px;}\n  th{\n    text-align:left;font-family:var(--mono);font-size:11px;letter-spacing:.06em;\n    text-transform:uppercase;color:var(--ink-soft);\n    border-bottom:1px solid var(--ink);padding:8px 14px 8px 0;\n  }\n  td{padding:10px 14px 10px 0;border-bottom:1px solid var(--line);vertical-align:top;}\n  tr:last-child td{border-bottom:none;}\n  td code, li code, p code{\n    font-family:var(--mono);font-size:.86em;background:var(--accent-soft);\n    color:#1f4a3d;padding:1px 6px;border-radius:2px;\n  }\n\n  pre{\n    background:var(--mono-bg);color:var(--mono-fg);\n    border-radius:6px;padding:18px 20px;overflow-x:auto;\n    font-family:var(--mono);font-size:13px;line-height:1.65;margin:14px 0 24px;\n    box-shadow:0 1px 0 rgba(0,0,0,.04);\n  }\n  pre code{background:none;color:inherit;padding:0;font-size:inherit;}\n  .tok-key{color:var(--mono-key);}\n  .tok-str{color:var(--mono-str);}\n  .tok-com{color:#6c7a86;font-style:italic;}\n  .tok-fn{color:#9cc4e4;}\n\n  .callout{\n    border-left:3px solid var(--accent);background:var(--accent-soft);\n    padding:14px 18px;border-radius:0 4px 4px 0;margin:18px 0 26px;font-size:14.5px;\n  }\n  .callout.warn{border-left-color:var(--amber);background:#fbf1e2;}\n  .callout p{margin:0;color:#26382f;}\n  .callout.warn p{color:#4a3819;}\n\n  ul{padding-left:20px;color:#2c3140;}\n  li{margin-bottom:6px;}\n\n  .type-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px;margin:16px 0 28px;}\n  .type-chip{\n    font-family:var(--mono);font-size:12.5px;background:var(--panel);\n    border:1px solid var(--line);border-radius:3px;padding:8px 10px;color:var(--ink);\n  }\n  .type-chip.only{border-style:dashed;color:var(--ink-soft);}\n\n  .faq dt{font-weight:700;margin-top:18px;color:var(--ink);}\n  .faq dd{margin:6px 0 0;color:var(--ink-soft);}\n\n  .changelog-item{border-left:2px solid var(--line);padding-left:18px;margin-bottom:22px;position:relative;}\n  .changelog-item::before{\n    content:\"\";position:absolute;left:-5px;top:4px;width:8px;height:8px;border-radius:50%;\n    background:var(--accent);\n  }\n  .changelog-version{font-family:var(--mono);font-weight:700;color:var(--accent);font-size:14px;}\n\n  footer{\n    border-top:1px solid var(--line);padding:28px 56px 60px;\n    font-size:12.5px;color:#8a8471;font-family:var(--mono);\n  }\n  a{color:var(--accent);}\n<\/style>\n<\/head>\n<body>\n<div class=\"shell\">\n\n  <aside class=\"rail\">\n    <div class=\"rail-mark\"><span class=\"tag\">PLUGIN<\/span><\/div>\n    <div class=\"rail-title\">Sifency Admin<br>Option Builder<\/div>\n    <div class=\"rail-sub\">v1.0.0 \u00b7 WordPress 6.5+ \u00b7 PHP 7.4+<\/div>\n\n    <nav>\n      <div class=\"rail-group\">\n        <div class=\"rail-group-label\">Start here<\/div>\n        <a href=\"#overview\">1. Overview<\/a>\n        <a href=\"#installation\">2. Installation<\/a>\n      <\/div>\n      <div class=\"rail-group\">\n        <div class=\"rail-group-label\">No-code<\/div>\n        <a href=\"#builder\">3. Visual builder<\/a>\n      <\/div>\n      <div class=\"rail-group\">\n        <div class=\"rail-group-label\">Developer API<\/div>\n        <a href=\"#api\">4. Framework API<\/a>\n        <a href=\"#types\">5. Field types<\/a>\n        <a href=\"#customizer\">6. Customizer bridge<\/a>\n        <a href=\"#structural\">7. Tabs &amp; groups<\/a>\n      <\/div>\n      <div class=\"rail-group\">\n        <div class=\"rail-group-label\">Reference<\/div>\n        <a href=\"#faq\">8. FAQ<\/a>\n        <a href=\"#changelog\">9. Changelog<\/a>\n      <\/div>\n    <\/nav>\n  <\/aside>\n\n  <main>\n    <div class=\"hero\">\n      <div class=\"kicker\">Plugin documentation<\/div>\n      <h1>Build WordPress option panels by dragging, or by writing five lines of PHP.<\/h1>\n      <p class=\"lede\">One engine, two doors in. Site admins build panels visually on the <strong>Option Builder<\/strong> screen; theme and plugin developers register the same kind of panel through a small static PHP API \u2014 <code>Sifency_Admin_Options_Framework<\/code> \u2014 with sanitization, tabs, and a Customizer bridge handled automatically either way.<\/p>\n      <div class=\"meta-row\">\n        <span class=\"pill\">GPLv2 or later<\/span>\n        <span class=\"pill\">Zero external requests<\/span>\n        <span class=\"pill\">manage_options capability<\/span>\n        <span class=\"pill\">Local storage only<\/span>\n      <\/div>\n    <\/div>\n\n    <div class=\"content\">\n\n      <section id=\"overview\">\n        <h2><span class=\"num\">01<\/span>Overview<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <table>\n          <tr><th>Approach<\/th><th>Who it&#8217;s for<\/th><th>Where<\/th><\/tr>\n          <tr><td>Visual builder<\/td><td>Site admins, no code<\/td><td><em>Option Builder<\/em> menu item in WP Admin<\/td><\/tr>\n          <tr><td>PHP API<\/td><td>Theme \/ plugin developers<\/td><td><code>Sifency_Admin_Options_Framework::<\/code> static methods<\/td><\/tr>\n        <\/table>\n        <p>Both paths produce the same kind of panel: sections (tabs) containing fields, saved as one serialized array under a single <code>option_name<\/code>, sanitized per field type automatically, with an optional bridge into the WordPress Customizer.<\/p>\n        <div class=\"callout\"><p>The plugin makes no external requests and stores everything locally in the WordPress database \u2014 nothing is collected, transmitted, or shared.<\/p><\/div>\n      <\/section>\n\n      <section id=\"installation\">\n        <h2><span class=\"num\">02<\/span>Installation<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <ul>\n          <li>Upload the <code>sifency-admin-option-builder<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install it via the Plugins screen.<\/li>\n          <li>Activate it from the <strong>Plugins<\/strong> screen.<\/li>\n          <li>Open <strong>Option Builder<\/strong> in the WP Admin menu to create your first panel.<\/li>\n        <\/ul>\n        <div class=\"callout warn\"><p>Only users with the <code>manage_options<\/code> capability (administrators on a standard single-site install) can access the builder or edit any panel&#8217;s saved values.<\/p><\/div>\n      <\/section>\n\n      <section id=\"builder\">\n        <h2><span class=\"num\">03<\/span>Using the visual builder<\/h2>\n        <div class=\"h2-rule\"><\/div>\n\n        <h3>Panels<\/h3>\n        <ul>\n          <li>Create any number of panels, each with its own title and an option-name prefix \u2014 the <code>option_name<\/code> its values are saved under.<\/li>\n          <li>The panel-settings block (title, prefix, &#8220;Show On&#8221;, menu placement) collapses once a panel is set up, keeping it out of the way of the section\/field builder below.<\/li>\n          <li>Per panel, choose where it appears: its own admin page, the Customizer, or both.<\/li>\n        <\/ul>\n\n        <h3>Sections and fields<\/h3>\n        <ul>\n          <li>Add sections (tabs) to a panel; nest a section under another as a sub-tab via &#8220;Nest as tab under.&#8221;<\/li>\n          <li>Drag fields into a section from a type palette. Reorder sections and fields by drag-and-drop.<\/li>\n          <li>For each field, set its <strong>ID<\/strong>, <strong>label<\/strong>, <strong>CSS class<\/strong>, <strong>default value<\/strong>, and <strong>description<\/strong> directly in the UI.<\/li>\n        <\/ul>\n        <p class=\"lead-note\">The visual builder currently exposes this subset of field types:<\/p>\n        <div class=\"type-grid\">\n          <div class=\"type-chip\">text<\/div><div class=\"type-chip\">textarea<\/div>\n          <div class=\"type-chip\">wp_editor<\/div><div class=\"type-chip\">code_editor<\/div>\n          <div class=\"type-chip\">number<\/div><div class=\"type-chip\">select<\/div>\n          <div class=\"type-chip\">button_set<\/div><div class=\"type-chip\">image_select<\/div>\n          <div class=\"type-chip\">color<\/div><div class=\"type-chip\">link_color<\/div>\n          <div class=\"type-chip\">media<\/div><div class=\"type-chip\">icon<\/div>\n          <div class=\"type-chip\">datetime<\/div><div class=\"type-chip\">link<\/div>\n          <div class=\"type-chip\">heading<\/div><div class=\"type-chip\">subheading<\/div>\n          <div class=\"type-chip\">notice<\/div>\n        <\/div>\n\n        <h3>Save, deactivate, uninstall<\/h3>\n        <ul>\n          <li><strong>Deactivating<\/strong> the plugin keeps all saved data intact.<\/li>\n          <li><strong>Deleting<\/strong> it via the Plugins screen removes every builder-created panel&#8217;s values <em>and<\/em> the builder layout itself.<\/li>\n          <li>This cleanup only touches builder-created panels \u2014 panels registered by a theme or plugin through the PHP API (\u00a74) are left untouched, since that data belongs to whichever product created it.<\/li>\n        <\/ul>\n      <\/section>\n\n      <section id=\"api\">\n        <h2><span class=\"num\">04<\/span>Developer API<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <p>For anything the visual builder doesn&#8217;t cover, register a panel directly in PHP \u2014 a separate registration path from builder-created panels.<\/p>\n\n        <h3><code>createOptions( $prefix, $args )<\/code><\/h3>\n        <p class=\"lead-note\">Registers a new options page\/panel. <code>$prefix<\/code> is the unique <code>option_name<\/code> every field in the panel is stored under, as one serialized array.<\/p>\n<pre><code><span class=\"tok-fn\">Sifency_Admin_Options_Framework::createOptions<\/span>( <span class=\"tok-str\">'my_plugin_options'<\/span>, array(\n    <span class=\"tok-str\">'menu_title'<\/span>         => <span class=\"tok-str\">'My Plugin'<\/span>,\n    <span class=\"tok-str\">'framework_title'<\/span>    => <span class=\"tok-str\">'My Plugin Settings'<\/span>,\n    <span class=\"tok-str\">'menu_icon'<\/span>          => <span class=\"tok-str\">'dashicons-admin-generic'<\/span>,\n    <span class=\"tok-str\">'menu_position'<\/span>      => null,\n    <span class=\"tok-str\">'menu_parent'<\/span>        => null,        <span class=\"tok-com\">\/\/ e.g. 'themes.php' to nest under Appearance<\/span>\n    <span class=\"tok-str\">'capability'<\/span>         => <span class=\"tok-str\">'manage_options'<\/span>,\n    <span class=\"tok-str\">'theme'<\/span>              => <span class=\"tok-str\">'light'<\/span>,\n    <span class=\"tok-str\">'footer_text'<\/span>        => <span class=\"tok-str\">''<\/span>,\n    <span class=\"tok-str\">'show_in_customizer'<\/span> => false,       <span class=\"tok-com\">\/\/ true to also bridge into the Customizer<\/span>\n    <span class=\"tok-str\">'hide_admin_menu'<\/span>    => false,       <span class=\"tok-com\">\/\/ true for a Customizer-only panel<\/span>\n) );<\/code><\/pre>\n\n        <h3><code>createSection( $prefix, $args )<\/code><\/h3>\n        <p class=\"lead-note\">Registers a section (top-level tab), or a nested sub-section when <code>parent<\/code> is supplied.<\/p>\n<pre><code><span class=\"tok-fn\">Sifency_Admin_Options_Framework::createSection<\/span>( <span class=\"tok-str\">'my_plugin_options'<\/span>, array(\n    <span class=\"tok-str\">'id'<\/span>       => <span class=\"tok-str\">'general'<\/span>,\n    <span class=\"tok-str\">'title'<\/span>    => <span class=\"tok-str\">'General'<\/span>,\n    <span class=\"tok-str\">'subtitle'<\/span> => <span class=\"tok-str\">''<\/span>,\n    <span class=\"tok-str\">'icon'<\/span>     => <span class=\"tok-str\">'dashicons-admin-generic'<\/span>,\n    <span class=\"tok-str\">'fields'<\/span>   => array(\n        array( <span class=\"tok-str\">'id'<\/span> => <span class=\"tok-str\">'my_field'<\/span>, <span class=\"tok-str\">'type'<\/span> => <span class=\"tok-str\">'text'<\/span>, <span class=\"tok-str\">'title'<\/span> => <span class=\"tok-str\">'My Field'<\/span> ),\n    ),\n) );<\/code><\/pre>\n        <p class=\"lead-note\">Pass <code>'parent' => 'general'<\/code> on a second call to nest it as a sub-tab inside <code>general<\/code> instead of creating a new top-level tab.<\/p>\n\n        <h3><code>createField( $prefix, $section_id, $field )<\/code><\/h3>\n        <p class=\"lead-note\">Extension point: appends a field to an already-registered top-level section without editing the file that created it.<\/p>\n<pre><code><span class=\"tok-fn\">Sifency_Admin_Options_Framework::createField<\/span>( <span class=\"tok-str\">'my_plugin_options'<\/span>, <span class=\"tok-str\">'general'<\/span>, array(\n    <span class=\"tok-str\">'id'<\/span>    => <span class=\"tok-str\">'extra_field'<\/span>,\n    <span class=\"tok-str\">'type'<\/span>  => <span class=\"tok-str\">'text'<\/span>,\n    <span class=\"tok-str\">'title'<\/span> => <span class=\"tok-str\">'Extra Field'<\/span>,\n) );<\/code><\/pre>\n\n        <h3>Reading saved values<\/h3>\n<pre><code><span class=\"tok-com\">\/\/ Static framework call \u2014 needs the exact prefix.<\/span>\n$value = <span class=\"tok-fn\">Sifency_Admin_Options_Framework::getOption<\/span>( <span class=\"tok-str\">'my_plugin_options'<\/span>, <span class=\"tok-str\">'my_field'<\/span>, <span class=\"tok-str\">'default'<\/span> );\n\n<span class=\"tok-com\">\/\/ Global helper \u2014 reads from the theme's own panel without hardcoding a prefix.<\/span>\n$value = <span class=\"tok-fn\">sifency_option<\/span>( <span class=\"tok-str\">'my_field'<\/span>, <span class=\"tok-str\">'default'<\/span> );   <span class=\"tok-com\">\/\/ alias of sifency_options()<\/span>\n$all    = <span class=\"tok-fn\">sifency_options<\/span>();                        <span class=\"tok-com\">\/\/ every saved value for the resolved prefix<\/span><\/code><\/pre>\n        <p class=\"lead-note\"><code>sifency_option()<\/code> \/ <code>sifency_options()<\/code> resolve their prefix as <code>{theme_slug}_options<\/code> by default (or the parent theme&#8217;s slug on a child theme). Point them at a custom prefix with a filter instead of forking the functions:<\/p>\n<pre><code><span class=\"tok-fn\">add_filter<\/span>( <span class=\"tok-str\">'sifency_option_prefix'<\/span>, function () {\n    return <span class=\"tok-str\">'my_custom_options'<\/span>;\n} );<\/code><\/pre>\n        <div class=\"callout\"><p>Call <code>sifency_flush_options_cache()<\/code> after a save\/import\/reset so subsequent reads in the same request see fresh data. It also purges common page caches (LiteSpeed Cache, WP Rocket, W3 Total Cache, WP Super Cache) so a saved setting doesn&#8217;t stay invisible behind a stale cached page.<\/p><\/div>\n      <\/section>\n\n      <section id=\"types\">\n        <h2><span class=\"num\">05<\/span>Field types<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <p>The full engine supports more types than the visual builder currently exposes \u2014 composite types are PHP-API only for now.<\/p>\n        <table>\n          <tr><th>Category<\/th><th>Types<\/th><\/tr>\n          <tr><td>Basic input<\/td><td><code>text<\/code>, <code>textarea<\/code>, <code>number<\/code>, <code>select<\/code>, <code>button_set<\/code>, <code>image_select<\/code><\/td><\/tr>\n          <tr><td>Color<\/td><td><code>color<\/code>, <code>link_color<\/code><\/td><\/tr>\n          <tr><td>Composite <span class=\"lead-note\">(PHP API only)<\/span><\/td><td><code>background<\/code>, <code>border<\/code>, <code>dimensions<\/code>, <code>spacing<\/code>, <code>typography<\/code><\/td><\/tr>\n          <tr><td>Rich content<\/td><td><code>wp_editor<\/code>, <code>code_editor<\/code><\/td><\/tr>\n          <tr><td>Media \/ icon<\/td><td><code>media<\/code>, <code>icon<\/code><\/td><\/tr>\n          <tr><td>Date &amp; links<\/td><td><code>datetime<\/code>, <code>link<\/code><\/td><\/tr>\n          <tr><td>Structural<\/td><td><code>fieldset<\/code>, <code>tabbed<\/code>, <code>group<\/code><\/td><\/tr>\n          <tr><td>Layout-only <span class=\"lead-note\">(no saved value)<\/span><\/td><td><code>heading<\/code>, <code>subheading<\/code>, <code>content<\/code>, <code>notice<\/code><\/td><\/tr>\n          <tr><td>Utility<\/td><td><code>backup<\/code> (export\/import)<\/td><\/tr>\n        <\/table>\n        <p>Every field type has its own server-side sanitizer that runs automatically on save \u2014 this isn&#8217;t something the implementer has to wire up.<\/p>\n\n        <h3>Overriding or adding a field type<\/h3>\n<pre><code><span class=\"tok-fn\">add_filter<\/span>( <span class=\"tok-str\">'sifency_fw_render_field_mytype'<\/span>, function ( $html, $field, $value, $name ) {\n    <span class=\"tok-com\">\/\/ return your own markup<\/span>\n    return $html;\n}, 10, 4 );<\/code><\/pre>\n        <p class=\"lead-note\">Sanitization is filterable the same way, via <code>sifency_fw_sanitize_field_{type}<\/code>.<\/p>\n      <\/section>\n\n      <section id=\"customizer\">\n        <h2><span class=\"num\">06<\/span>Customizer bridge<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <p>Set <code>'show_in_customizer' => true<\/code> on a panel (or choose <strong>Customizer<\/strong> \/ <strong>Both<\/strong> in the visual builder) to have its compatible fields appear live in <strong>Appearance \u2192 Customize<\/strong>, alongside \u2014 or instead of, with <code>hide_admin_menu<\/code> \u2014 the dedicated settings page.<\/p>\n        <p class=\"lead-note\">Only these field types currently bridge into the Customizer:<\/p>\n        <div class=\"type-grid\">\n          <div class=\"type-chip\">text<\/div><div class=\"type-chip\">icon<\/div>\n          <div class=\"type-chip\">textarea<\/div><div class=\"type-chip\">wp_editor<\/div>\n          <div class=\"type-chip\">number<\/div><div class=\"type-chip\">color<\/div>\n          <div class=\"type-chip\">link_color<\/div><div class=\"type-chip\">select<\/div>\n          <div class=\"type-chip\">image_select<\/div><div class=\"type-chip\">button_set<\/div>\n          <div class=\"type-chip\">media<\/div>\n        <\/div>\n        <div class=\"callout warn\"><p>Fields of any other type remain editable only on the panel&#8217;s own settings page.<\/p><\/div>\n      <\/section>\n\n      <section id=\"structural\">\n        <h2><span class=\"num\">07<\/span>Tabs &amp; groups<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <ul>\n          <li><code>fieldset<\/code> \u2014 a pure UI wrapper: groups child fields visually without storing a value of its own.<\/li>\n          <li><code>tabbed<\/code> \u2014 lets a single section fan out into nested tabs, each with its own <code>fields<\/code> array, without a separate <code>createSection()<\/code> call per tab.<\/li>\n          <li><code>group<\/code> \u2014 a repeatable row of sub-fields, stored as one array under the group&#8217;s own field id. Unlike <code>fieldset<\/code>\/<code>tabbed<\/code>, a <code>group<\/code> is treated as a single leaf value, not flattened.<\/li>\n        <\/ul>\n      <\/section>\n\n      <section id=\"faq\">\n        <h2><span class=\"num\">08<\/span>FAQ<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <dl class=\"faq\">\n          <dt>Do I need a specific theme?<\/dt>\n          <dd>No \u2014 the Option Builder screen works with any theme, out of the box.<\/dd>\n          <dt>Who can access the builder or edit values?<\/dt>\n          <dd>Users with the <code>manage_options<\/code> capability.<\/dd>\n          <dt>Does the plugin send data externally?<\/dt>\n          <dd>No. All settings are stored locally in the WordPress database; no external requests are made.<\/dd>\n          <dt>Can I add my own panel as a developer?<\/dt>\n          <dd>Yes, via <code>createOptions()<\/code> \/ <code>createSection()<\/code> (\u00a74) \u2014 entirely separate from panels made with the visual builder.<\/dd>\n          <dt>Will a built panel show up in the Customizer?<\/dt>\n          <dd>Only if &#8220;Customizer&#8221; or &#8220;Both&#8221; is chosen for that panel, and only for the field types listed in \u00a76.<\/dd>\n          <dt>What happens on deactivate vs. uninstall?<\/dt>\n          <dd>Deactivating preserves all data. Uninstalling removes every builder-created panel&#8217;s values and the builder layout itself \u2014 not panels registered via the PHP API by another theme\/plugin.<\/dd>\n        <\/dl>\n      <\/section>\n\n      <section id=\"changelog\">\n        <h2><span class=\"num\">09<\/span>Changelog<\/h2>\n        <div class=\"h2-rule\"><\/div>\n        <div class=\"changelog-item\">\n          <div class=\"changelog-version\">1.0.0<\/div>\n          <ul><li>Initial release.<\/li><\/ul>\n        <\/div>\n      <\/section>\n\n    <\/div>\n\n    <footer>Sifency Admin Option Builder \u00b7 v1.0.0 \u00b7 GPLv2 or later<\/footer>\n  <\/main>\n<\/div>\n\n<script>\n  \/\/ Highlight the active section link in the rail as you scroll.\n  const links = Array.from(document.querySelectorAll('.rail nav a'));\n  const sections = links.map(a => document.querySelector(a.getAttribute('href')));\n  function onScroll(){\n    let current = sections[0];\n    for (const s of sections){\n      if (s && s.getBoundingClientRect().top - 90 <= 0) current = s;\n    }\n    links.forEach(a => a.classList.toggle('active', current && a.getAttribute('href') === '#' + current.id));\n  }\n  document.addEventListener('scroll', onScroll, { passive: true });\n  onScroll();\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Sifency Admin Option Builder \u2014 Documentation PLUGIN Sifency AdminOption Builder v1.0.0 \u00b7 WordPress 6.5+ \u00b7 PHP 7.4+ Start here 1. Overview 2. Installation No-code 3. Visual builder Developer API 4. Framework API 5. Field types 6. Customizer bridge 7. Tabs &amp; groups Reference 8. FAQ 9. Changelog Plugin documentation Build WordPress option panels by dragging, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"elementor_canvas","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-165","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/posts\/165","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/comments?post=165"}],"version-history":[{"count":8,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/posts\/165\/revisions"}],"predecessor-version":[{"id":174,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/posts\/165\/revisions\/174"}],"wp:attachment":[{"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/media?parent=165"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/categories?post=165"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sifency.com\/docs\/wp-json\/wp\/v2\/tags?post=165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}