Reference → Pages — Reference

Pages — Reference

The Pages surface is where the static structure of a site lives — the home page, about, contact, landing pages, every routable URL that isn't a blog post, event, product, or other content-type record. It owns the URL slug, the layout, the SG-Builder canvas state, the publication state, the SEO meta, and the per-post revision history.

This page is a reference for platform engineers and integrators. Customer-facing walkthroughs for adding, editing, and publishing pages live in the customer docs set; this page describes the surface, not the workflow.


Overview

Pages live under the Pages module in SG-Admin. The module renders three primary views — the page list, the create / edit form, and the per-page revision history — and shares its write surface with the broader post-record system. The shared write surface is important: many of the operations described below (duplicate, soft-delete, restore, revision-restore, set-homepage, import) are implemented once at the post-record layer and reused by Pages, Blog posts, Events, and custom content types.

When you read the SG-Admin source, you will see the Pages module file is intentionally thin — most of the heavy work lives in the shared post-actions surface. Integrators should think of Pages as "the post-record surface filtered to records of type page" rather than as a separate engine.

Where it lives in SG-Admin:

  • Sidebar: SG-Admin → Pages
  • URL prefix: /sg-admin/pages/
  • View templates: application/views/Admin/Pages/
  • Shared write surface: the post-record action layer (also used by Blog, Events, Custom Objects)
A site has exactly one homepage at any moment. The homepage role is a property of the post record, not of the URL — see Data model below.
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Pages [+ Add new] │├──────────────────────────────────────────────────────────────────────┤│ Title Slug Status Homepage Updated ││ ────────────── ────────────────── ────────── ──────── ─────────││ Home home published ★ 2d ago ││ About about published — 5d ago ││ Pricing pricing published — 1d ago ││ Contact contact draft — now││ Legacy Landing legacy/spring-26 archived — 44d ago ││ ││ [⋯ Edit] [⋯ Duplicate] [⋯ Set as homepage] [⋯ Delete] │└──────────────────────────────────────────────────────────────────────┘

Actions

The Pages surface exposes the following operations. Some are implemented directly on the Pages module; most route into the shared post-record action layer.

List and search

Returns the page records, paginated, with title, slug, status, homepage flag, author, and updated-at columns. Supports column sort, free-text filter, and per-page count. The page list is the post-record list filtered to type page.

Create page

Opens an empty editor. Required: title and slug (slug auto-derives from title but stays editable until first save). Optional: layout template, parent page (for hierarchical URLs), SEO meta, visibility, and the SG-Builder canvas state. On submit, the record persists in draft status by default.

Edit page

Loads an existing record into the same editor used for create. Submit replaces the stored state with the posted values. The editor preserves the SG-Builder canvas as a serialized component tree on the record — opening the editor a second time deserializes that tree into the canvas.

Save and publish

Two-step publication. Save persists the draft; Publish moves the record into the published state and assigns it a publication timestamp. Republishing an already-published record updates the timestamp. The two operations are deliberately split so an operator can stage many edits before they go live.

Duplicate

Creates a new page record with the same content, a copy-suffix in the title, and a unique slug. The duplicate starts in draft status regardless of the source's status. The duplicate carries its own record identifier — relationships pointing to the source page do not transfer.

Set as homepage

Marks the page as the site's homepage. Exactly one page holds this role at any time; setting it on a new page clears it on the previous one. The homepage role affects URL resolution — the homepage's canonical URL is /, not /.

Engineering note. When a page becomes the homepage, the front-end sheds the body class derived from the slug. CSS scoped to body.page- stops applying. Scope custom CSS to body.page_id- (the numeric record identifier) for rules that should survive a homepage flip.

Soft delete

Marks the record as trash. Soft-deleted pages disappear from the default list but remain queryable via the trash filter. URL resolution stops serving the page immediately.

Restore

Returns a trashed page to its prior status (draft or published). The slug is preserved; if a new page has been created at the same slug in the meantime, restore returns a structured rejection with the conflicting slug named.

Permanent delete

Hard-removes a trashed record. Irreversible. Author attribution on associated revisions is preserved, but the revisions themselves are removed.

Per-page revision history

Every save writes a revision row. The history view lists revisions for a given page in reverse-chronological order with the saving operator, the timestamp, and a short diff summary. Restore revision loads the historic canvas state back into the live record as a new save — the restored state immediately becomes the current draft, with the prior live state preserved as another revision.

Import

Bulk-loads pages from an exported bundle (typically from another SGEN site). Import accepts the bundle file, validates structure and slug collisions, and reports per-record success or skip. The shape and import path are shared with Templates and Posts.


Data model

A page record carries the following fields.

FieldTypeNotes
idintegerPrimary key. Stable across edits.
typeenumAlways page for records managed by this surface.
titlestringDisplay title. Used in admin lists and as the default </code> tag.</td></tr><tr><td><code>slug</code></td><td>string</td><td>URL segment. Unique across pages and posts.</td></tr><tr><td><code>parent_id</code></td><td>integer</td><td>Optional. Enables hierarchical URLs (<code>/parent/child</code>).</td></tr><tr><td><code>status</code></td><td>enum</td><td><code>draft</code>, <code>published</code>, <code>scheduled</code>, <code>trash</code>.</td></tr><tr><td><code>is_homepage</code></td><td>boolean</td><td>True on exactly one page at a time.</td></tr><tr><td><code>layout_template</code></td><td>string</td><td>Theme template slug. Falls back to default.</td></tr><tr><td><code>canvas_state</code></td><td>JSON</td><td>Serialized SG-Builder component tree. Empty for non-Builder pages.</td></tr><tr><td><code>seo_meta</code></td><td>JSON</td><td>Title override, description, canonical, OpenGraph, schema.</td></tr><tr><td><code>author_id</code></td><td>integer</td><td>Owning user. Foreign key to the Users surface.</td></tr><tr><td><code>published_at</code></td><td>timestamp</td><td>Set on first publish, updated on republish.</td></tr><tr><td><code>created_at</code></td><td>timestamp</td><td>Set on create, immutable.</td></tr><tr><td><code>updated_at</code></td><td>timestamp</td><td>Touched on any save.</td></tr></tbody></table><strong>Slug uniqueness.</strong> Slugs are unique across the post-record table, not within Pages. A slug collision with a blog post or a custom-object record will block save. The surface returns a structured rejection naming the conflicting record's type.<p><strong>Homepage uniqueness.</strong> <code>is_homepage = true</code> is exclusive — a database constraint, not a convention. The set-as-homepage action handles the swap atomically.</p><p><strong>Revision storage.</strong> Revisions live in a separate table, one row per save, carrying the full canvas state at that point. Storage cost grows with edit cadence; the Settings module exposes a retention cap (default 25 per page, configurable).</p><pre><code>SAVE ┌─────────────────────┐edit canvas ──► │ page record (live) ││ status: draft │└──────────┬──────────┘│▼┌─────────────────────┐│ revision row │ ← one per save│ snapshot of canvas │ ← FIFO trimmed at retention cap└─────────────────────┘RESTORE REVISIONhistoric row ──► becomes new current draftprior current ──► becomes another revision</code></pre><hr><h2>Permissions</h2><p>Access to the Pages surface is gated at the standard admin layer, plus per-action capability checks.</p><table><thead><tr><th>Capability</th><th>Administrator</th><th>Editor</th><th>Viewer</th></tr></thead><tbody><tr><td>List pages</td><td>✔</td><td>✔</td><td>✔</td></tr><tr><td>Create page</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Edit any page</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Publish</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Set as homepage</td><td>✔</td><td>—</td><td>—</td></tr><tr><td>Duplicate</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Soft delete</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Restore</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Permanent delete</td><td>✔</td><td>—</td><td>—</td></tr><tr><td>View revision history</td><td>✔</td><td>✔</td><td>✔</td></tr><tr><td>Restore revision</td><td>✔</td><td>✔</td><td>—</td></tr><tr><td>Import bundle</td><td>✔</td><td>—</td><td>—</td></tr></tbody></table><strong>Authorship gating.</strong> Custom role configurations may further restrict edit to "own pages only" — under that mode, an editor sees the full list but the edit action rejects on records owned by others.<p><strong>Audit.</strong> Every save, publish, delete, restore, revision restore, homepage swap, and import emits an Activity Log entry with the acting operator and the target record.</p><pre><code>SAVE / PUBLISH / DELETE│▼┌─────────────────────────────┐│ Admin gate │ unauth → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Per-action capability check │ role lacks cap → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Authorship gating (if set) │ not own + "own only" mode → reject└──────────────┬──────────────┘▼┌─────────────────────────────┐│ Slug / homepage uniqueness │ collision → structured rejection└──────────────┬──────────────┘▼action executes│▼Activity Log entry</code></pre><hr><h2>Related references</h2><ul><li><strong>Posts — Reference.</strong> Shares the post-record action layer with Pages. Most of the write operations described above are implemented there.</li><li><strong>Templates — Reference.</strong> Layout templates referenced by <code>layout_template</code> live under Templates. Changes propagate to every page using the template.</li><li><strong>Users — Reference.</strong> Author attribution and the per-action capability checks resolve against the Users module.</li><li><strong>SEO — Reference.</strong> The <code>seo_meta</code> JSON shape is defined and validated under the SEO module.</li><li><strong>Settings — Reference.</strong> Revision retention cap, fallback layout, and slug-rewrite rules live in Settings.</li><li><strong>Media — Reference.</strong> Canvas-embedded image references resolve against the Media library.</li></ul>For the corresponding customer-facing walkthrough — creating a page, setting the homepage, recovering a deleted page from trash — see the Pages section of the customer docs at <code>/docs/pages</code>.</div><div id="i9mx9" data-component-id="sgb_mp2a4osavj1yh" class="sgb-component sgb-component-text"><div class="post-nav"> <nav class="sg-post-navigation"> <ul class="post-nav-list"> <li class="post-nav-prev"> <a href="https://documentationsgen.staging.sgen.com/blog/reference/api-orders" class="btn btn-primary"> <div class="nav-icon"> <i data-lucide="chevron-left" class="icon" aria-hidden="true"></i> </div> <div class="nav-label"> <span class="nav-label-txt">← Previous</span> <span class="nav-label-title">Orders — Reference</span> </div> </a> </li> <li class="post-nav-next"> <a href="https://documentationsgen.staging.sgen.com/blog/reference/api-pdf-templates" class="btn btn-primary"> <div class="nav-label"> <span class="nav-label-txt">Next →</span> <span class="nav-label-title">PDF Templates — Reference</span> </div> <div class="nav-icon"> <i data-lucide="chevron-right" class="icon" aria-hidden="true"></i> </div> </a> </li> </ul> </nav> </div></div></div><div id="comp_mp2a4osainnjt" data-component-id="sgb_mp2a4osainnjt" class="sgb-component docs-toc col cell"><div id="iqpyk" data-component-id="sgb_mp2a4oscig22i" class="sgb-component sgb-component-text"><div class="docs-toc-inner"><div class="toc-label">On this page</div><nav class="toc-list" aria-label="Page sections"><span class="toc-empty">Loading...</span></nav></div></div></div></div></div></section> </main> <footer id="masterfoot"> <div></div> </footer></div> <div id="searchbar" class="sgen-searchbar-overlay" aria-hidden="true" aria-label="Search overlay"> <div class="sgen-searchbar-backdrop" aria-label="Close search"></div> <div class="sgen-searchbar-dialog" role="dialog" aria-modal="true" aria-labelledby="sgen-searchbar-title"> <div class="sgen-searchbar-inner"> <button type="button" class="sgen-searchbar-close" aria-label="Close search">×</button> <h2 id="sgen-searchbar-title" class="sgen-searchbar-title">Search</h2> <form class="sgen-searchbar-form" action="https://documentationsgen.staging.sgen.com/search" method="get" role="search"> <label for="sgen-searchbar-input" class="visually-hidden">Search this site</label> <input type="search" id="sgen-searchbar-input" name="s" class="sgen-searchbar-input" placeholder="Search pages and posts…" autocomplete="off"> <button type="submit" class="btn btn-primary sgen-searchbar-submit">Search</button> </form> </div> </div></div> <script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/defaults/js/lucide.min.js?v=1.0.19" defer /></script><script type="text/javascript" defer />(function(){function run(){if(window.lucide&&typeof window.lucide.createIcons==='function')window.lucide.createIcons()}if(document.readyState!=='loading')run();else document.addEventListener('DOMContentLoaded',run);setTimeout(run,100)})();</script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/defaults/modules/wowjs/dist/wow.min.js?v=1.0.19" defer /></script><script type="text/javascript" defer />if(typeof WOW!=='undefined'){new WOW().init()}</script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/vendors/swiper/swiper-bundle.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/defaults/sgen/assets/js/sg-drawer.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/locations.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/locations-picker.js?v=1.0.19" defer /></script><script type="text/javascript" defer />window.sgenAccessibility={alignment:"right"};</script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/sgen-accessibility.min.js?v=1.0.19" defer /></script><script type="text/javascript" defer />window.sgcom=window.sgcom||{};window.sgcom.config={cart:{mode:'drawer',button:{mode:'redirect',show_count:true,inline_count:false},urls:{cart:'https://documentationsgen.staging.sgen.com/cart/',checkout:'https://documentationsgen.staging.sgen.com/checkout/',state:'https://documentationsgen.staging.sgen.com/do_shopping/cart_state',add:'https://documentationsgen.staging.sgen.com/add_to_cart',remove:'https://documentationsgen.staging.sgen.com/remove_from_cart'}}};window.sgcom.cart=window.sgcom.cart||{};window.sgcom.checkout=window.sgcom.checkout||{};window.sgcom.ui=window.sgcom.ui||{};</script><script type="text/javascript" defer />window.sgcom=window.sgcom||{};window.sgcom.config={cart:{mode:'drawer',button:{mode:'redirect',show_count:true,inline_count:false},urls:{cart:'https://documentationsgen.staging.sgen.com/cart/',checkout:'https://documentationsgen.staging.sgen.com/checkout/',state:'https://documentationsgen.staging.sgen.com/do_shopping/cart_state',add:'https://documentationsgen.staging.sgen.com/add_to_cart',remove:'https://documentationsgen.staging.sgen.com/remove_from_cart'}}};window.sgcom.cart=window.sgcom.cart||{};window.sgcom.checkout=window.sgcom.checkout||{};window.sgcom.ui=window.sgcom.ui||{};</script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/ecommerce.plugin.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/ecommerce.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/defaults/js/plugins.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/forms.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/sessionAttributerForms.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/plugins.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/sgbuilder.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/main.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/sgen-mobile-menu.js?v=1.0.19" defer /></script><script type="text/javascript" src="https://documentationsgen.staging.sgen.com/assets/front/js/lazyLoad.min.js?v=1.0.19" defer /></script><script type="text/javascript" src="/assets/dispenza/js/dispenza.js?v=1.0.19" defer /></script> <script>document.addEventListener('DOMContentLoaded',function(){if(document.querySelector('.docs-sidebar, .docs-article, .docs-toc-inner')){var here=location.pathname.replace(/\/$/,'');document.querySelectorAll('.docs-sidebar a.nav-item').forEach(function(a){var href=(a.getAttribute('href')||'').split('#')[0].split('?')[0].replace(/\/$/,'');if(href&&href===here){a.classList.add('active');var p=a.closest('details.nav-group');if(p)p.open=true}});var tocLinks=document.querySelectorAll('.docs-toc-inner .toc-list a, .docs-toc-inner nav a');if(tocLinks.length&&'IntersectionObserver'in window){var byId={};tocLinks.forEach(function(a){var id=(a.getAttribute('href')||'').replace('#','');if(id)byId[id]=a});var heads=[];Object.keys(byId).forEach(function(id){var h=document.getElementById(id);if(h)heads.push(h)});if(heads.length){var io=new IntersectionObserver(function(entries){entries.forEach(function(e){var a=byId[e.target.id];if(!a)return;if(e.isIntersecting){tocLinks.forEach(function(x){x.classList.remove('active')});a.classList.add('active')}})},{rootMargin:'-80px 0px -65% 0px',threshold:0});heads.forEach(function(h){io.observe(h)})}}}var isMobile=function(){return window.innerWidth<992};var hideViewAll=function(){document.querySelectorAll('#mobile-nav .mega-grid a').forEach(function(a){if(/^view all/i.test((a.textContent||'').trim()))a.style.display='none'})};var blockMainRoute=function(e){if(!isMobile())return;var a=e.target.closest('#mobile-nav .sg-nav-item.is-mega-menu > .sg-nav-link');if(a){e.preventDefault();var li=a.closest('li.is-mega-menu');if(li){li.classList.toggle('mobile-open');var drop=li.querySelector('.sg-dropdown-menu');if(drop){drop.style.display=(drop.style.display==='block'?'none':'block')}}}};document.addEventListener('click',blockMainRoute,true);hideViewAll();document.querySelectorAll('.mobile-toggler-burger').forEach(function(b){b.addEventListener('click',function(){setTimeout(hideViewAll,300)})})});</script><script>(function(){if(window.__SG_MOBILE_ACCORDION_SINGLE)return;function init(){var mn=document.querySelector('#mobile-nav');if(!mn)return false;var triggers=mn.querySelectorAll('ul.sg-site-navigation > li.sg-dropdown > .sg-nav-link, ul.sg-site-navigation > li.sg-dropdown > a');if(!triggers.length)return false;triggers.forEach(function(t){t.addEventListener('click',function(e){var thisLi=t.closest('li.sg-dropdown');if(!thisLi)return;mn.querySelectorAll('li.sg-dropdown.mobile-open').forEach(function(other){if(other!==thisLi)other.classList.remove('mobile-open')})},true)});window.__SG_MOBILE_ACCORDION_SINGLE=true;return true}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else if(!init())setTimeout(init,500)})();</script><script>(function(){if(window.__HL_DATE_SWAP)return;function init(){var cards=document.querySelectorAll('body.page_id-136 #comp_mouzev9o02e6h .article-item');if(!cards.length)return false;var dateRe=/^(January|February|March|April|May|June|July|August|September|October|November|December)\s+(\d{1,2}),\s*(\d{4})/i;cards.forEach(function(card){var desc=card.querySelector('.description');var dateEl=card.querySelector('.article-date');if(!desc||!dateEl)return;var m=desc.textContent.trim().match(dateRe);if(!m)return;var formatted=m[1].slice(0,3).toUpperCase()+' '+m[2]+', '+m[3];var svg=dateEl.querySelector('svg');dateEl.innerHTML='';if(svg)dateEl.appendChild(svg);dateEl.appendChild(document.createTextNode(' '+formatted));desc.innerHTML=desc.innerHTML.replace(/^[^A-Z]*(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{1,2},\s*\d{4}\s*[—–-]\s*/i,'')});window.__HL_DATE_SWAP=true;return true}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else if(!init())setTimeout(init,500)})();</script><script>(function(){if(window.__BLOG_BACK_LINK)return;function init(){if(!document.body.classList.contains('sgposts-blog_single'))return false;var m=location.pathname.match(/^\/blog\/([^\/]+)\/[^\/]+/);var cat=m?m[1]:null;var labels={guides:'Guides',reference:'Reference',changelog:'Changelog',highlights:'Highlights','whats-new':"What's New"};var label=cat&&labels[cat]?labels[cat]:'Blog';var target=cat==='highlights'||cat==='whats-new'?'/':(cat?'/'+cat:'/blog');var bar=document.createElement('div');bar.className='blog-back-bar';bar.innerHTML='<a class="blog-back-link" href="'+target+'">← Back to '+label+'</a>';var content=document.querySelector('main')||document.querySelector('.site-content');if(content)content.insertBefore(bar,content.firstChild);window.__BLOG_BACK_LINK=true;return true}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else if(!init())setTimeout(init,500)})();</script><script>(function(){if(window.__SG_DESKTOP_ACCORDION_SINGLE)return;window.__SG_DESKTOP_ACCORDION_SINGLE=true;function wire(){var sidebars=document.querySelectorAll('.docs-sidebar-inner');if(!sidebars.length)return;sidebars.forEach(function(sb){if(sb.__sgWired)return;sb.__sgWired=true;var topGroups=[].filter.call(sb.children,function(c){return c.tagName==='DETAILS'});topGroups.forEach(function(d){d.addEventListener('toggle',function(){if(!d.open)return;topGroups.forEach(function(other){if(other!==d&&other.open)other.open=false})})})})}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',wire);else wire();var obs=new MutationObserver(wire);obs.observe(document.documentElement,{childList:true,subtree:true})})();</script><script>(function(){if(window.__SG_BLOG_INDEX_REDIRECT)return;window.__SG_BLOG_INDEX_REDIRECT=true;try{var path=location.pathname.replace(/\/+$/,'');if(path!=='/blog')return;var ref=document.referrer||'';var sameOrigin=ref&&ref.indexOf(location.origin)===0;var dest=sameOrigin&&ref.replace(/[#?].*$/,'')!==location.href.replace(/[#?].*$/,'')?ref:'/';location.replace(dest)}catch(e){}})();</script><script>(function(){if(window.__SG_SIDEBAR_INJECTOR)return;window.__SG_SIDEBAR_INJECTOR=true;var CAT_TO_HUB={guides:'/guides',reference:'/reference',changelog:'/changelog',roadmap:'/roadmap',highlights:'/',whatsnew:'/','whats-new':'/'};var TTL_MS=5*60*1000;var pathRe=new RegExp('^/blog/([a-z0-9-]+)/','i');function getCat(){var m=location.pathname.match(pathRe);return m?m[1].toLowerCase():null}function readCache(cat){try{var raw=localStorage.getItem('__sg_sidebar_'+cat);if(!raw)return null;return JSON.parse(raw)}catch(e){return null}}function writeCache(cat,html){try{localStorage.setItem('__sg_sidebar_'+cat,JSON.stringify({t:Date.now(),html:html}))}catch(e){}}function wireAccordion(sidebar){var top=[].filter.call(sidebar.children,function(c){return c.tagName==='DETAILS'});top.forEach(function(d){if(d.__sgAccordionWired)return;d.__sgAccordionWired=true;d.addEventListener('toggle',function(){if(!d.open)return;top.forEach(function(o){if(o!==d&&o.open)o.open=false})})})}function markActive(sidebar){var here=location.pathname.replace(new RegExp('/$'),'');[].forEach.call(sidebar.querySelectorAll('a.nav-item'),function(a){var href=(a.getAttribute('href')||'').replace(new RegExp('/$'),'');if(href===here){a.classList.add('nav-item--active');var det=a.closest('details');if(det)det.open=true}})}function injectInto(target,html){target.innerHTML=html;wireAccordion(target);markActive(target)}function fetchHubSidebar(cat){var hub=CAT_TO_HUB[cat];if(!hub)return Promise.resolve(null);return fetch(hub,{credentials:'same-origin'}).then(function(r){return r.text()}).then(function(txt){var d=new DOMParser().parseFromString(txt,'text/html');var sb=d.querySelector('.docs-sidebar-inner');return sb?sb.innerHTML:null}).catch(function(){return null})}function run(){if(document.body.className.indexOf('sgposts-blog_single')<0)return;var cat=getCat();if(!cat)return;var target=document.querySelector('.docs-sidebar-inner');if(!target)return;var cached=readCache(cat);if(cached&&cached.html)injectInto(target,cached.html);fetchHubSidebar(cat).then(function(fresh){if(!fresh)return;writeCache(cat,fresh);if(!cached||cached.html!==fresh)injectInto(target,fresh)})}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',run);else run()})();</script> </body></html>