LayoutHub

docs.layouthub.com
SaaS & Products

LayoutHub is an easy page builder that helps merchants quickly set up an online store with any kind of page type by using our library of pre-designed layouts and blocks. Based on all pre-made templates you can easily import a complete page layout or insert each individual block in any position of the page.

llms.txt
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GitBook</title>
<link rel="manifest" href="/public/manifest.json">
<link rel="icon" sizes="512x512" href="/public/images/icon-512.png" media="(prefers-color-scheme: light)">
<link rel="icon" sizes="512x512" href="/public/images/icon-512-dark.png" media="(prefers-color-scheme: dark)">
<link rel="apple-touch-icon" sizes="512x512" href="/public/images/icon-ios/icon_512x512.png">
<link rel="apple-touch-icon" sizes="512x512@2x" href="/public/images/icon-ios/icon_512x512@2x.png">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="GitBook">
<meta name="theme-color" content="#f7f7f7">
<meta name="description" content="GitBook">
<link rel="preconnect" href="https://v2-content.gitbook.com">
<script type="text/javascript" defer="" src="https://cdn.iframe.ly/embed.js" async=""></script>
<!-- 
  Google Tag Manager tracking script to track conversions from the site.
  See https://gitbook.slack.com/archives/C07AQA4256G/p1721923712258389 for more info 
-->
<script>
  (function (w, d, s, l, i) {
      w[l] = w[l] || [];
      w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
      var f = d.getElementsByTagName(s)[0],
          j = d.createElement(s),
          dl = l != 'dataLayer' ? '&l=' + l : '';
      j.async = true;
      j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
      f.parentNode.insertBefore(j, f);
  })(window, document, 'script', 'dataLayer', 'GTM-PVD2ZHVC');
      // 1. Adapt to dark/light theme
      const theme = localStorage.getItem('@recoil/userThemeAtom');
      if (theme?.includes('dark')) {
        document.documentElement.classList.add('theme-color-dark');
      } else if (theme?.includes('light')) {
        document.documentElement.classList.add('theme-color-light');
      }
      
      function hideSidebar() {
          const sidebar = document.querySelector('.sidebar');
          if (sidebar) sidebar.style.display = 'none';
      }
      
      function applySidebarSizing() {
          let sidebarWidth;
          let isSidebarCollapsed = false;

          function applySidebarWidth() {
              const sidebar = document.querySelector('.sidebar');
              if (!sidebar) return;
              
              if (isSidebarCollapsed) {
                  sidebar.style.setProperty('--sidebar-width', '0px')
              } else if (sidebarWidth) {
                  sidebar.style.setProperty('--sidebar-width', sidebarWidth + 'px');
              }
          }

          try {
              const dbName = 'keyval-store';
              const storeName = 'keyval';
              const request = indexedDB.open(dbName, 1);

              request.onupgradeneeded = (event) => {
                  const db = event.target.result;
                  if (!db.objectStoreNames.contains(storeName)) {
                      db.createObjectStore(storeName);
                  }
              };

              request.onsuccess = (event) => {
                  const db = event.target.result;
                  if (db.objectStoreNames.contains(storeName)) {
                      const transaction = db.transaction(storeName, 'readonly');
                      const store = transaction.objectStore(storeName);

                      const widthRequest = store.get('@recoil/sidebarWidth');
                      widthRequest.onsuccess = () => {
                          if (widthRequest.result !== undefined) {
                              sidebarWidth = widthRequest.result;
                          }
                          const collapsedRequest = store.get('@recoil/sidebarCollapsed');
                          collapsedRequest.onsuccess = () => {
                              if (collapsedRequest.result !== undefined) {
                                  isSidebarCollapsed = collapsedRequest.result;
                              }
                              applySidebarWidth();
                          };
                      };
                  } else {
                      applySidebarWidth();
                  }
              };

              request.onerror = () => {
                  applySidebarWidth();
              };

          } catch (e) {
              applySidebarWidth();
          }
      }
      
      // Leave early if no indexedDB
      if (!('indexedDB' in window)) {
          hideSidebar();
          return;
      }
    
    const path = window.location.pathname;
    const urlParams = new URLSearchParams(window.location.search);
    const hasAuthToken = urlParams.has('auth_token');
    
    // Detect SAML auth flows (auth_token without apiTestMode) to skip problematic Firebase checks
    const isSamlAuth = hasAuthToken && !urlParams.has('apiTestMode');
    
    // 2. Check auth state. Sign-in page layout doesn't match editor, so we need to hide the sidebar there. Skip Firebase auth checks for SAML flows to avoid race conditions in CI
    if (!isSamlAuth) {
        let authCheckTimeout;
        try {
            const firebaseDbName = 'firebaseLocalStorageDb';
            const firebaseRequest = indexedDB.open(firebaseDbName, 1);

            // Add timeout to prevent blocking page render in CI
            authCheckTimeout = setTimeout(() => {
                hideSidebar();
            }, 1000);

            firebaseRequest.onsuccess = (event) => {
                if (authCheckTimeout !== undefined) {
                    clearTimeout(authCheckTimeout);
                    authCheckTimeout = undefined;
                }
                const db = event.target.result;
                const objectStoreNames = Array.from(db.objectStoreNames);
                
                if (!objectStoreNames.length) {
                    return hideSidebar();
                }
                
                const transaction = db.transaction(objectStoreNames, 'readonly');
                const store = transaction.objectStore(objectStoreNames[0]);
                
                // Look for Firebase auth user key pattern
                const getAllRequest = store.getAllKeys();
                getAllRequest.onsuccess = () => {
                const keys = getAllRequest.result;
                const authKey = keys.find(key => 
                    typeof key === 'string' && 
                    key.includes('firebase:authUser:') && 
                    key.includes('[DEFAULT]')
                );
                
                if (!authKey) {
                    return hideSidebar();
                }
                
                // Check if the auth user actually has data
                const getRequest = store.get(authKey);
                getRequest.onsuccess = () => {
                    if (!getRequest.result) {
                        return hideSidebar();
                    }
                // At this point, user is logged in. Apply sidebar width/collapsed logic.
                applySidebarSizing();
                };
                };
            };

            firebaseRequest.onerror = () => {
                if (authCheckTimeout !== undefined) {
                    clearTimeout(authCheckTimeout);
                    authCheckTimeout = undefined;
                }
                hideSidebar();
            };
        } catch (e) {
            if (authCheckTimeout !== undefined) {
                clearTimeout(authCheckTimeout);
                authCheckTimeout = undefined;
            }
            hideSidebar();
        }
    } else {
        // For SAML auth flows, still apply sidebar sizing but skip Firebase auth checks
        // This ensures SAML users get their sidebar preferences without CI race conditions
        applySidebarSizing();
    }

    // Adds header nav bars (Space, OpenAPI, Site, Integration detail page)
    const pagesWithHeader = ['/openapi/', '/s/', '/site', '/integrations/'];
    const showSpaceheader = pagesWithHeader.some(route => path.includes(route));
    
    if (showSpaceheader) {
        document.documentElement.classList.add('show-spaceheader');
    }
})();
</script>
<div id="root" class="app-root-container">
    <div id="gitbook-root" class="app-root"></div>
    <div id="portals-root"></div>
</div>
<div class="gitbook-splashscreen">
  <div class="sidebar">
    <div class="sidebar-header-skeleton">
        <div class="org-switcher-skeleton shimmer-dark"></div>
    </div>
  </div>
  <div class="application">
    <div class="spaceheader"></div>
  </div>
</div>
Related

Workflow automation software for everyone. Automate your work across 7,000+ app integrations—no developers, no IT tickets, no delays.

/llms.txt
27,156 tokens
/llms-full.txt
529,536 tokens
SaaS & Products

Dub.co is the open-source link management platform for modern marketing teams to create marketing campaigns, link sharing features, and referral programs.

/llms.txt
5,889 tokens
/llms-full.txt
216,953 tokens
SaaS & Products

Campsite is designed for distributed teams to cut through the noise of daily work — move faster with more transparent, organized, and thoughtful conversations.

/llms.txt
481 tokens
SaaS & Products

We help modern software companies drive more up-sells, cross-sells and renewals through industry leading product onboarding, engagement, and adoption.

/llms.txt
4,213 tokens
/llms-full.txt
82,141 tokens
SaaS & Products

Respond to customers on any channel, sync with your entire team and turn support conversations into product strategy.

/llms.txt
7,036 tokens
/llms-full.txt
111,729 tokens
SaaS & Products

Platform for businesses to send gifts to customers/employees.

/llms.txt
4,241 tokens
/llms-full.txt
55,038 tokens
SaaS & Products

Loops makes email marketing for modern SaaS companies easy. It's the best way to create, send and track beautiful email campaigns.

/llms.txt
6,337 tokens
/llms-full.txt
277,564 tokens
SaaS & Products

Drive pipeline with 10+ intent data sources, AI, and automation. Scale prospecting, personalization, engagement in one unified workflow.

/llms.txt
4,295 tokens
/llms-full.txt
88,159 tokens
SaaS & Products