<!DOCTYPE html> <html> <head> <% # we're going to use the body = Nokogiri::HTML(@body) title = body.css('h1').first&.text.presence || t('bullet_train.tagline') first_paragraph = body.css('p').first preceding_heading = first_paragraph&.xpath("preceding-sibling::h2") description = [preceding_heading&.text, first_paragraph&.text].select(&:present?).join(" — ") || t('bullet_train.description') image_url = "https://avatars.githubusercontent.com/u/5976880?s=280&v=4" site_name = "Bullet Train Developer Documentation" %> <% content_for :title do %> <title><%= [site_name, title, t('bullet_train.tagline')].select(&:present?).uniq.first(2).reverse.join(' — ') %></title> <% end %> <%= render 'themes/light/layouts/head' %> <meta content="<%= t('bullet_train.keywords') %>" name="keywords" /> <meta content="<%= description.truncate(200) %>" name="description" /> <meta name="twitter:image:src" content="<%= image_url %>" /> <meta name="twitter:site" content="@bullettrainco" /> <meta name="twitter:card" content="summary" /> <meta name="twitter:title" content="<%= title.truncate(70) %>" /> <meta name="twitter:description" content="<%= description.truncate(160) %>" /> <meta property="og:image" content="<%= image_url %>" /> <meta property="og:site_name" content="<%= site_name %>" /> <meta property="og:type" content="object" /> <meta property="og:title" content="<%= title.truncate(95) %>" /> <meta property="og:url" content="<%= request.base_url + request.path %>" /> <meta property="og:description" content="<%= description.truncate(200) %>" /> </head> <body class="<%= BulletTrain::Themes::Light.background || "bg-gradient-to-br from-secondary-200 to-primary-400 dark:from-primary-900 dark:to-primary-600" %> text-slate-700 text-sm font-normal dark:text-slate-300"> <div class="md:p-5"> <div class="min-h-screen md:h-auto overflow-hidden md:rounded-lg flex shadow" data-controller="mobile-menu" data-mobile-menu-hidden-class="hidden" > <% menu = capture do %> <div class="flex items-center flex-shrink-0 p-4 bg-blue-700 md:rounded-tl-lg"> <%= image_tag image_path("logo/logo.png"), class: 'h-5 w-auto mx-auto' %> <div class="lg:hidden absolute right-0"> <button class="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" data-action="mobile-menu#close" > <span class="sr-only">Close Application Menu</span> <svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> </svg> </button> </div> </div> <nav class="flex-1 space-y-1 overflow-y-auto"> <div class="px-5 py-4" id="menu"> <%= render 'account/shared/menu/section', title: 'Introduction' do %> <%= render 'account/shared/menu/item', url: '/docs', label: 'Table of Contents' do |p| %> <% p.icon do %> <i class="fal fa-home-lg-alt ti ti-list"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/getting-started', label: 'Getting Started' do |p| %> <% p.icon do %> <i class="fal fa-terminal ti ti-flag"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/upgrades', label: 'Upgrades' do |p| %> <% p.icon do %> <i class="fal fa-sparkles ti ti-arrow-up"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'General Topics' do %> <%= render 'account/shared/menu/item', url: '/docs/modeling', label: 'Domain Modeling' do |p| %> <% p.icon do %> <i class="fal fa-bolt ti ti-ruler-pencil"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/indirection', label: 'Indirection' do |p| %> <% p.icon do %> <i class="fal fa-bolt ti ti-direction"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/overriding', label: 'Overriding' do |p| %> <% p.icon do %> <i class="fal fa-bolt ti ti-spray"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/tunneling', label: 'Tunneling' do |p| %> <% p.icon do %> <i class="fal fa-bolt ti ti-bolt"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/javascript', label: 'JavaScript' do |p| %> <% p.icon do %> <i class="fa-brands fa-js ti ti-pulse"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/i18n', label: 'Internationalization' do |p| %> <% p.icon do %> <i class="fa-brands fa-js ti ti-world"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Developer Tools' do %> <%= render 'account/shared/menu/item', url: '/docs/super-scaffolding', label: 'Super Scaffolding' do |p| %> <% p.icon do %> <i class="fal fa-magic ti ti-wand"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/action-models', label: 'Action Models' do |p| %> <% p.icon do %> <i class="fal fa-bars-progress ti ti-target"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/seeds', label: 'Database Seeds' do |p| %> <% p.icon do %> <i class="fal fa-seedling ti ti-server"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/testing', label: 'Test Suite' do |p| %> <% p.icon do %> <i class="fal fa-check ti ti-check"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: 'https://github.com/bullet-train-co/magic_test', label: 'Magic Test' do |p| %> <% p.icon do %> <i class="fal fa-check ti ti-video-camera"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/application-options', label: 'Application Options' do |p| %> <% p.icon do %> <i class="fal fa-gear ti ti-settings"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/application-hash.md', label: 'Application Hash' do |p| %> <% p.content_for :icon do %> <i class="fal fa-brackets-curly ti ti-view-list-alt"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Accounts & Teams' do %> <%= render 'account/shared/menu/item', url: '/docs/authentication', label: 'Authentication' do |p| %> <% p.icon do %> <i class="fal fa-fingerprint ti ti-id-badge"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/teams', label: 'Teams' do |p| %> <% p.icon do %> <i class="fal fa-users ti ti-user"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/permissions', label: 'Roles & Permissions' do |p| %> <% p.icon do %> <i class="fal fa-lock-alt ti ti-lock"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/onboarding', label: 'Onboarding' do |p| %> <% p.icon do %> <i class="fal fa-snowboarding ti ti-direction"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/namespacing', label: 'Namespacing' do |p| %> <% p.icon do %> <i class="fal fa-object-group ti ti-widgetized"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'User Interface' do %> <%= render 'account/shared/menu/item', url: '/docs/field-partials', label: 'Field Partials' do |p| %> <% p.icon do %> <i class="fal fa-i-cursor ti ti-text"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/themes', label: 'Themes' do |p| %> <% p.icon do %> <i class="fal fa-swatchbook ti ti-palette"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: 'https://github.com/bullet-train-co/nice_partials', label: 'Nice Partials' do |p| %> <% p.icon do %> <i class="fal fa-swatchbook ti ti-widget"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: 'https://github.com/bullet-train-co/showcase', label: 'Showcase' do |p| %> <% p.icon do %> <i class="fal fa-swatchbook ti ti-panel"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Billing' do %> <%= render 'account/shared/menu/item', url: '/docs/billing/stripe', label: 'Stripe' do |p| %> <% p.icon do %> <i class="fab fa-stripe-s ti ti-money"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/billing/usage', label: 'Usage' do |p| %> <% p.icon do %> <i class="fal fa-gauge ti ti-ruler"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Integration' do %> <%= render 'account/shared/menu/item', url: '/docs/api', label: 'REST API' do |p| %> <% p.icon do %> <i class="fal fa-brackets-curly ti ti-settings"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/zapier', label: 'Zapier' do |p| %> <% p.icon do %> <i class="fal fa-bolt ti ti-bolt"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/oauth', label: 'OAuth Providers' do |p| %> <% p.icon do %> <i class="fal fa-at ti ti-reload"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/webhooks/outgoing', label: 'Outgoing Webhooks' do |p| %> <% p.icon do %> <i class="fal fa-outlet ti ti-pulse"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/webhooks/incoming', label: 'Incoming Webhooks' do |p| %> <% p.icon do %> <i class="fal fa-plug ti ti-plug"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Internationalization' do %> <%= render 'account/shared/menu/item', url: '/docs/i18n', label: 'Translations' do |p| %> <% p.icon do %> <i class="fal fa-language ti ti-world"></i> <% end %> <% end %> <% end if false %> <%= render 'account/shared/menu/section', title: 'Add-Ons' do %> <%= render 'account/shared/menu/item', url: '/docs/font-awesome-pro', label: 'Font Awesome Pro' do |p| %> <% p.icon do %> <i class="fal fa-flag ti ti-flag"></i> <% end %> <% end %> <% end %> <%= render 'account/shared/menu/section', title: 'Deployment' do %> <%= render 'account/shared/menu/item', url: '/docs/heroku', label: 'Heroku' do |p| %> <% p.icon do %> <i class="fal fa-cloud ti ti-cloud-up"></i> <% end %> <% end %> <%= render 'account/shared/menu/item', url: '/docs/desktop', label: 'Desktop Applications' do |p| %> <% p.icon do %> <i class="fal fa-window-restore ti ti-desktop"></i> <% end %> <% end %> <% end %> </div> </nav> <% end %> <div class="lg:hidden hidden" data-mobile-menu-target="wrapper" > <div class="fixed inset-0 flex z-40"> <button data-mobile-menu-target="revealable" data-action="mobile-menu#close" data-transition-enter="transition-opacity ease-linear duration-200" data-transition-enter-start="opacity-0" data-transition-enter-end="opacity-100" data-transition-leave="transition-opacity ease-linear duration-200" data-transition-leave-start="opacity-100" data-transition-leave-end="opacity-0" class="fixed inset-0" aria-hidden="true" > <div class="absolute inset-0 bg-gradient-to-br from-secondary-200 to-primary-400 opacity-75"></div> </button> <div data-mobile-menu-target="revealable" data-transition-enter="transition ease-in-out duration-200 transform" data-transition-enter-start="-translate-x-full" data-transition-enter-end="translate-x-0" data-transition-leave="transition ease-in-out duration-200 transform" data-transition-leave-start="translate-x-0" data-transition-leave-end="-translate-x-full" class="relative flex-1 flex flex-col max-w-xs w-full pb-4 bg-gradient-to-br from-primary-900 to-primary-600 shadow-xl" > <%= menu %> </div> <div class="flex-shrink-0 w-14" aria-hidden="true"></div> </div> </div> <div class="hidden lg:flex lg:flex-shrink-0 overflow-y-auto bg-gradient-to-b from-primary-700 to-primary-800 dark:from-slate-800 dark:to-slate-800"> <div class="w-64"> <%= menu %> </div> </div> <div class="flex flex-col w-0 flex-1 overflow-y-auto bg-slate-100 dark:bg-slate-800 lg:border-l dark:border-slate-500"> <main class="flex-1 relative z-0 overflow-y-auto focus:outline-none" tabindex="0"> <button class="lg:hidden h-12 w-12 ml-1 flex-none inline-flex items-center justify-center rounded-md text-slate-500 hover:text-slate-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue" data-action="mobile-menu#open" > <span class="sr-only">Open Application Menu</span> <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /> </svg> </button> <div class="py-2 px-1"> <div class="mx-auto sm:px-6 sm:py-4 px-2"> <div class="bg-white rounded-md shadow sm:py-14 sm:px-12 py-10 px-7"> <div class="prose" style="max-width: none;"> <%= yield %> </div> </div> </div> </div> </main> </div> </div> </div> </body> </html>