[{"data":1,"prerenderedAt":2086},["ShallowReactive",2],{"navigation":3,"\u002Fgetting-started\u002Finstallation":773,"\u002Fgetting-started\u002Finstallation-surround":2081},[4,28,63,85,103,112,269,355,453,485,506,542,576,594,647,669,693,721,747],{"title":5,"path":6,"stem":7,"children":8,"icon":27},"Getting Started","\u002Fgetting-started","01.getting-started\u002F01.index",[9,11,15,19,23],{"title":10,"path":6,"stem":7},"Introduction",{"title":12,"path":13,"stem":14},"Installation","\u002Fgetting-started\u002Finstallation","01.getting-started\u002F02.installation",{"title":16,"path":17,"stem":18},"Quickstart with AI","\u002Fgetting-started\u002Fquickstart-with-ai","01.getting-started\u002F03.quickstart-with-ai",{"title":20,"path":21,"stem":22},"Quickstart by Hand","\u002Fgetting-started\u002Fquickstart-by-hand","01.getting-started\u002F04.quickstart-by-hand",{"title":24,"path":25,"stem":26},"The Admin","\u002Fgetting-started\u002Fadmin-tour","01.getting-started\u002F05.admin-tour","i-lucide-rocket",{"title":29,"icon":30,"path":31,"stem":32,"children":33,"page":62},"Concepts","i-lucide-lightbulb","\u002Fconcepts","02.concepts",[34,38,42,46,50,54,58],{"title":35,"path":36,"stem":37},"PostgreSQL First","\u002Fconcepts\u002Fpostgresql-first","02.concepts\u002F01.postgresql-first",{"title":39,"path":40,"stem":41},"Resources","\u002Fconcepts\u002Fresources","02.concepts\u002F02.resources",{"title":43,"path":44,"stem":45},"Users and Roles","\u002Fconcepts\u002Fusers-and-roles","02.concepts\u002F03.users-and-roles",{"title":47,"path":48,"stem":49},"Permissions","\u002Fconcepts\u002Fpermissions","02.concepts\u002F04.permissions",{"title":51,"path":52,"stem":53},"Drafts and Publishing","\u002Fconcepts\u002Fdrafts-and-publishing","02.concepts\u002F05.drafts-and-publishing",{"title":55,"path":56,"stem":57},"Audit and Events","\u002Fconcepts\u002Faudit-and-events","02.concepts\u002F06.audit-and-events",{"title":59,"path":60,"stem":61},"Object Access","\u002Fconcepts\u002Fobject-access","02.concepts\u002F07.object-access",false,{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":62},"App","i-lucide-app-window","\u002Fapp","03.app",[69,73,77,81],{"title":70,"path":71,"stem":72},"The App","\u002Fapp\u002Foverview","03.app\u002F01.overview",{"title":74,"path":75,"stem":76},"DataViews","\u002Fapp\u002Fdataviews","03.app\u002F02.dataviews",{"title":78,"path":79,"stem":80},"Dashboards","\u002Fapp\u002Fdashboards","03.app\u002F03.dashboards",{"title":82,"path":83,"stem":84},"Arrange menu","\u002Fapp\u002Farrange-menu","03.app\u002F04.arrange-menu",{"title":86,"icon":87,"path":88,"stem":89,"children":90,"page":62},"Database","i-lucide-database","\u002Fdatabase","04.database",[91,95,99],{"title":92,"path":93,"stem":94},"Tables","\u002Fdatabase\u002Ftables","04.database\u002F01.tables",{"title":96,"path":97,"stem":98},"Views","\u002Fdatabase\u002Fviews","04.database\u002F02.views",{"title":100,"path":101,"stem":102},"Functions","\u002Fdatabase\u002Ffunctions","04.database\u002F03.functions",{"title":104,"icon":105,"path":106,"stem":107,"children":108,"page":62},"SQL Console","i-lucide-square-terminal","\u002Fsql-console","05.sql-console",[109],{"title":104,"path":110,"stem":111},"\u002Fsql-console\u002Foverview","05.sql-console\u002F01.overview",{"title":74,"icon":113,"path":114,"stem":115,"children":116,"page":62},"i-lucide-layout-list","\u002Fdataviews","06.dataviews",[117,121,125,129,183,214],{"title":118,"path":119,"stem":120},"Overview","\u002Fdataviews\u002Foverview","06.dataviews\u002F01.overview",{"title":122,"path":123,"stem":124},"Creating a DataView","\u002Fdataviews\u002Fcreating","06.dataviews\u002F02.creating",{"title":126,"path":127,"stem":128},"Publishing","\u002Fdataviews\u002Fpublishing","06.dataviews\u002F03.publishing",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":62},"Types","i-lucide-shapes","\u002Fdataviews\u002Ftypes","06.dataviews\u002F04.types",[135,139,143,147,151,155,159,163,167,171,175,179],{"title":136,"path":137,"stem":138},"Table","\u002Fdataviews\u002Ftypes\u002Ftable","06.dataviews\u002F04.types\u002F01.table",{"title":140,"path":141,"stem":142},"Cards","\u002Fdataviews\u002Ftypes\u002Fcards","06.dataviews\u002F04.types\u002F02.cards",{"title":144,"path":145,"stem":146},"Kanban","\u002Fdataviews\u002Ftypes\u002Fkanban","06.dataviews\u002F04.types\u002F03.kanban",{"title":148,"path":149,"stem":150},"Calendar","\u002Fdataviews\u002Ftypes\u002Fcalendar","06.dataviews\u002F04.types\u002F04.calendar",{"title":152,"path":153,"stem":154},"Gantt","\u002Fdataviews\u002Ftypes\u002Fgantt","06.dataviews\u002F04.types\u002F05.gantt",{"title":156,"path":157,"stem":158},"Map","\u002Fdataviews\u002Ftypes\u002Fmap","06.dataviews\u002F04.types\u002F06.map",{"title":160,"path":161,"stem":162},"Tree","\u002Fdataviews\u002Ftypes\u002Ftree","06.dataviews\u002F04.types\u002F07.tree",{"title":164,"path":165,"stem":166},"Form","\u002Fdataviews\u002Ftypes\u002Fform","06.dataviews\u002F04.types\u002F08.form",{"title":168,"path":169,"stem":170},"Master-detail","\u002Fdataviews\u002Ftypes\u002Fmaster-detail","06.dataviews\u002F04.types\u002F09.master-detail",{"title":172,"path":173,"stem":174},"Settings","\u002Fdataviews\u002Ftypes\u002Fsettings","06.dataviews\u002F04.types\u002F10.settings",{"title":176,"path":177,"stem":178},"Custom","\u002Fdataviews\u002Ftypes\u002Fcustom","06.dataviews\u002F04.types\u002F11.custom",{"title":180,"path":181,"stem":182},"External Frame","\u002Fdataviews\u002Ftypes\u002Fexternal-frame","06.dataviews\u002F04.types\u002F12.external-frame",{"title":172,"icon":184,"path":185,"stem":186,"children":187,"page":62},"i-lucide-settings-2","\u002Fdataviews\u002Fsettings","06.dataviews\u002F05.settings",[188,192,196,199,202,206,210],{"title":189,"path":190,"stem":191},"General","\u002Fdataviews\u002Fsettings\u002Fgeneral","06.dataviews\u002F05.settings\u002F01.general",{"title":193,"path":194,"stem":195},"Data","\u002Fdataviews\u002Fsettings\u002Fdata","06.dataviews\u002F05.settings\u002F02.data",{"title":96,"path":197,"stem":198},"\u002Fdataviews\u002Fsettings\u002Fviews","06.dataviews\u002F05.settings\u002F03.views",{"title":164,"path":200,"stem":201},"\u002Fdataviews\u002Fsettings\u002Fform","06.dataviews\u002F05.settings\u002F04.form",{"title":203,"path":204,"stem":205},"Actions","\u002Fdataviews\u002Fsettings\u002Factions","06.dataviews\u002F05.settings\u002F05.actions",{"title":207,"path":208,"stem":209},"Security","\u002Fdataviews\u002Fsettings\u002Fsecurity","06.dataviews\u002F05.settings\u002F06.security",{"title":211,"path":212,"stem":213},"Versions","\u002Fdataviews\u002Fsettings\u002Fversions","06.dataviews\u002F05.settings\u002F07.versions",{"title":215,"icon":216,"path":217,"stem":218,"children":219,"page":62},"Design Form","i-lucide-pencil-ruler","\u002Fdataviews\u002Fdesign-form","06.dataviews\u002F06.design-form",[220,223,257,261,265],{"title":118,"path":221,"stem":222},"\u002Fdataviews\u002Fdesign-form\u002Foverview","06.dataviews\u002F06.design-form\u002F01.overview",{"title":224,"icon":131,"path":225,"stem":226,"children":227,"page":62},"Widgets","\u002Fdataviews\u002Fdesign-form\u002Fwidgets","06.dataviews\u002F06.design-form\u002F02.widgets",[228,231,234,238,242,246,250,254],{"title":224,"path":229,"stem":230},"\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Foverview","06.dataviews\u002F06.design-form\u002F02.widgets\u002F01.overview",{"title":164,"path":232,"stem":233},"\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Fform","06.dataviews\u002F06.design-form\u002F02.widgets\u002F02.form",{"title":235,"path":236,"stem":237},"Inputs","\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Finputs","06.dataviews\u002F06.design-form\u002F02.widgets\u002F03.inputs",{"title":239,"path":240,"stem":241},"Display","\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Fdisplay","06.dataviews\u002F06.design-form\u002F02.widgets\u002F04.display",{"title":243,"path":244,"stem":245},"Embeds","\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Fembeds","06.dataviews\u002F06.design-form\u002F02.widgets\u002F05.embeds",{"title":247,"path":248,"stem":249},"Layout","\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Flayout","06.dataviews\u002F06.design-form\u002F02.widgets\u002F06.layout",{"title":251,"path":252,"stem":253},"Overlays","\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Foverlays","06.dataviews\u002F06.design-form\u002F02.widgets\u002F07.overlays",{"title":203,"path":255,"stem":256},"\u002Fdataviews\u002Fdesign-form\u002Fwidgets\u002Factions","06.dataviews\u002F06.design-form\u002F02.widgets\u002F08.actions",{"title":258,"path":259,"stem":260},"Variables","\u002Fdataviews\u002Fdesign-form\u002Fvariables","06.dataviews\u002F06.design-form\u002F03.variables",{"title":262,"path":263,"stem":264},"Code","\u002Fdataviews\u002Fdesign-form\u002Fcode","06.dataviews\u002F06.design-form\u002F04.code",{"title":266,"path":267,"stem":268},"Formulas","\u002Fdataviews\u002Fdesign-form\u002Fformulas","06.dataviews\u002F06.design-form\u002F05.formulas",{"title":78,"icon":270,"path":271,"stem":272,"children":273,"page":62},"i-lucide-layout-dashboard","\u002Fdashboards","07.dashboards",[274,277,281,285,332],{"title":118,"path":275,"stem":276},"\u002Fdashboards\u002Foverview","07.dashboards\u002F01.overview",{"title":278,"path":279,"stem":280},"Creating a Dashboard","\u002Fdashboards\u002Fcreating","07.dashboards\u002F02.creating",{"title":282,"path":283,"stem":284},"Editor","\u002Fdashboards\u002Feditor","07.dashboards\u002F03.editor",{"title":224,"icon":286,"path":287,"stem":288,"children":289,"page":62},"i-lucide-chart-bar","\u002Fdashboards\u002Fwidgets","07.dashboards\u002F04.widgets",[290,293,297,301,305,309,313,317,321,324,328],{"title":224,"path":291,"stem":292},"\u002Fdashboards\u002Fwidgets\u002Foverview","07.dashboards\u002F04.widgets\u002F01.overview",{"title":294,"path":295,"stem":296},"Editing a Widget","\u002Fdashboards\u002Fwidgets\u002Fediting-a-widget","07.dashboards\u002F04.widgets\u002F02.editing-a-widget",{"title":298,"path":299,"stem":300},"Indicators","\u002Fdashboards\u002Fwidgets\u002Findicators","07.dashboards\u002F04.widgets\u002F03.indicators",{"title":302,"path":303,"stem":304},"Comparison","\u002Fdashboards\u002Fwidgets\u002Fcomparison","07.dashboards\u002F04.widgets\u002F04.comparison",{"title":306,"path":307,"stem":308},"Trend","\u002Fdashboards\u002Fwidgets\u002Ftrend","07.dashboards\u002F04.widgets\u002F05.trend",{"title":310,"path":311,"stem":312},"Proportion","\u002Fdashboards\u002Fwidgets\u002Fproportion","07.dashboards\u002F04.widgets\u002F06.proportion",{"title":314,"path":315,"stem":316},"Distribution and Relation","\u002Fdashboards\u002Fwidgets\u002Fdistribution-and-relation","07.dashboards\u002F04.widgets\u002F07.distribution-and-relation",{"title":318,"path":319,"stem":320},"Maps","\u002Fdashboards\u002Fwidgets\u002Fmaps","07.dashboards\u002F04.widgets\u002F08.maps",{"title":92,"path":322,"stem":323},"\u002Fdashboards\u002Fwidgets\u002Ftables","07.dashboards\u002F04.widgets\u002F09.tables",{"title":325,"path":326,"stem":327},"Visualization and Insertion","\u002Fdashboards\u002Fwidgets\u002Fvisualization-and-insertion","07.dashboards\u002F04.widgets\u002F10.visualization-and-insertion",{"title":329,"path":330,"stem":331},"SQL Conventions","\u002Fdashboards\u002Fwidgets\u002Fsql-conventions","07.dashboards\u002F04.widgets\u002F11.sql-conventions",{"title":172,"icon":184,"path":333,"stem":334,"children":335,"page":62},"\u002Fdashboards\u002Fsettings","07.dashboards\u002F05.settings",[336,339,342,345,349,352],{"title":189,"path":337,"stem":338},"\u002Fdashboards\u002Fsettings\u002Fgeneral","07.dashboards\u002F05.settings\u002F01.general",{"title":258,"path":340,"stem":341},"\u002Fdashboards\u002Fsettings\u002Fvariables","07.dashboards\u002F05.settings\u002F02.variables",{"title":193,"path":343,"stem":344},"\u002Fdashboards\u002Fsettings\u002Fdata","07.dashboards\u002F05.settings\u002F03.data",{"title":346,"path":347,"stem":348},"Share","\u002Fdashboards\u002Fsettings\u002Fshare","07.dashboards\u002F05.settings\u002F04.share",{"title":207,"path":350,"stem":351},"\u002Fdashboards\u002Fsettings\u002Fsecurity","07.dashboards\u002F05.settings\u002F05.security",{"title":211,"path":353,"stem":354},"\u002Fdashboards\u002Fsettings\u002Fversions","07.dashboards\u002F05.settings\u002F06.versions",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":62},"Workflows","i-lucide-workflow","\u002Fworkflows","08.workflows",[361,364,368,371,393,432],{"title":118,"path":362,"stem":363},"\u002Fworkflows\u002Foverview","08.workflows\u002F01.overview",{"title":365,"path":366,"stem":367},"Creating a Workflow","\u002Fworkflows\u002Fcreating","08.workflows\u002F02.creating",{"title":282,"path":369,"stem":370},"\u002Fworkflows\u002Feditor","08.workflows\u002F03.editor",{"title":372,"icon":373,"path":374,"stem":375,"children":376,"page":62},"Triggers","i-lucide-zap","\u002Fworkflows\u002Ftriggers","08.workflows\u002F04.triggers",[377,381,385,389],{"title":378,"path":379,"stem":380},"Manual","\u002Fworkflows\u002Ftriggers\u002Fmanual","08.workflows\u002F04.triggers\u002F01.manual",{"title":382,"path":383,"stem":384},"Database Event","\u002Fworkflows\u002Ftriggers\u002Fdatabase-event","08.workflows\u002F04.triggers\u002F02.database-event",{"title":386,"path":387,"stem":388},"Schedule","\u002Fworkflows\u002Ftriggers\u002Fschedule","08.workflows\u002F04.triggers\u002F03.schedule",{"title":390,"path":391,"stem":392},"Webhook","\u002Fworkflows\u002Ftriggers\u002Fwebhook","08.workflows\u002F04.triggers\u002F04.webhook",{"title":394,"icon":357,"path":395,"stem":396,"children":397,"page":62},"Steps","\u002Fworkflows\u002Fsteps","08.workflows\u002F05.steps",[398,401,405,408,412,416,420,424,428],{"title":193,"path":399,"stem":400},"\u002Fworkflows\u002Fsteps\u002Fdata","08.workflows\u002F05.steps\u002F01.data",{"title":402,"path":403,"stem":404},"Control","\u002Fworkflows\u002Fsteps\u002Fcontrol","08.workflows\u002F05.steps\u002F02.control",{"title":262,"path":406,"stem":407},"\u002Fworkflows\u002Fsteps\u002Fcode","08.workflows\u002F05.steps\u002F03.code",{"title":409,"path":410,"stem":411},"Integration","\u002Fworkflows\u002Fsteps\u002Fintegration","08.workflows\u002F05.steps\u002F04.integration",{"title":413,"path":414,"stem":415},"Communication","\u002Fworkflows\u002Fsteps\u002Fcommunication","08.workflows\u002F05.steps\u002F05.communication",{"title":417,"path":418,"stem":419},"Files","\u002Fworkflows\u002Fsteps\u002Ffiles","08.workflows\u002F05.steps\u002F06.files",{"title":421,"path":422,"stem":423},"Documents","\u002Fworkflows\u002Fsteps\u002Fdocuments","08.workflows\u002F05.steps\u002F07.documents",{"title":425,"path":426,"stem":427},"Composition","\u002Fworkflows\u002Fsteps\u002Fcomposition","08.workflows\u002F05.steps\u002F08.composition",{"title":429,"path":430,"stem":431},"Values","\u002Fworkflows\u002Fsteps\u002Fvalues","08.workflows\u002F05.steps\u002F09.values",{"title":172,"icon":184,"path":433,"stem":434,"children":435,"page":62},"\u002Fworkflows\u002Fsettings","08.workflows\u002F06.settings",[436,439,443,446,449],{"title":189,"path":437,"stem":438},"\u002Fworkflows\u002Fsettings\u002Fgeneral","08.workflows\u002F06.settings\u002F01.general",{"title":440,"path":441,"stem":442},"Trigger","\u002Fworkflows\u002Fsettings\u002Ftrigger","08.workflows\u002F06.settings\u002F02.trigger",{"title":207,"path":444,"stem":445},"\u002Fworkflows\u002Fsettings\u002Fsecurity","08.workflows\u002F06.settings\u002F03.security",{"title":211,"path":447,"stem":448},"\u002Fworkflows\u002Fsettings\u002Fversions","08.workflows\u002F06.settings\u002F04.versions",{"title":450,"path":451,"stem":452},"Runs","\u002Fworkflows\u002Fsettings\u002Fruns","08.workflows\u002F06.settings\u002F05.runs",{"title":417,"icon":454,"path":455,"stem":456,"children":457,"page":62},"i-lucide-files","\u002Ffiles","09.files",[458,461,465,469,473,477,481],{"title":118,"path":459,"stem":460},"\u002Ffiles\u002Foverview","09.files\u002F01.overview",{"title":462,"path":463,"stem":464},"Uploading","\u002Ffiles\u002Fuploading","09.files\u002F02.uploading",{"title":466,"path":467,"stem":468},"File Details","\u002Ffiles\u002Ffile-details","09.files\u002F03.file-details",{"title":470,"path":471,"stem":472},"Editing Files","\u002Ffiles\u002Fediting-files","09.files\u002F04.editing-files",{"title":474,"path":475,"stem":476},"Using Files in Tables","\u002Ffiles\u002Fusing-files-in-tables","09.files\u002F05.using-files-in-tables",{"title":478,"path":479,"stem":480},"Image Transformations","\u002Ffiles\u002Fimage-transformations","09.files\u002F06.image-transformations",{"title":482,"path":483,"stem":484},"Who Can See a File","\u002Ffiles\u002Fwho-can-see-a-file","09.files\u002F07.who-can-see-a-file",{"title":486,"icon":487,"path":488,"stem":489,"children":490,"page":62},"Templates","i-lucide-file-text","\u002Ftemplates","10.templates",[491,494,498,502],{"title":118,"path":492,"stem":493},"\u002Ftemplates\u002Foverview","10.templates\u002F01.overview",{"title":495,"path":496,"stem":497},"Emails","\u002Ftemplates\u002Femails","10.templates\u002F02.emails",{"title":499,"path":500,"stem":501},"PDF","\u002Ftemplates\u002Fpdf","10.templates\u002F03.pdf",{"title":503,"path":504,"stem":505},"System Emails","\u002Ftemplates\u002Fsystem-emails","10.templates\u002F04.system-emails",{"title":507,"icon":508,"path":509,"stem":510,"children":511,"page":62},"Users","i-lucide-users","\u002Fusers","11.users",[512,516,520,524,528],{"title":513,"path":514,"stem":515},"Managing Users","\u002Fusers\u002Fmanaging-users","11.users\u002F01.managing-users",{"title":517,"path":518,"stem":519},"A User's Page","\u002Fusers\u002Fa-users-page","11.users\u002F02.a-users-page",{"title":521,"path":522,"stem":523},"API Tokens","\u002Fusers\u002Fapi-tokens","11.users\u002F03.api-tokens",{"title":525,"path":526,"stem":527},"Sessions","\u002Fusers\u002Fsessions","11.users\u002F04.sessions",{"title":529,"icon":530,"path":531,"stem":532,"children":533,"page":62},"Insights","i-lucide-chart-line","\u002Fusers\u002Finsights","11.users\u002F05.insights",[534,538],{"title":535,"path":536,"stem":537},"Sign-ins","\u002Fusers\u002Finsights\u002Fsign-ins","11.users\u002F05.insights\u002F01.sign-ins",{"title":539,"path":540,"stem":541},"Activity","\u002Fusers\u002Finsights\u002Factivity","11.users\u002F05.insights\u002F02.activity",{"title":543,"icon":544,"path":545,"stem":546,"children":547,"page":62},"Roles","i-lucide-shield-check","\u002Froles","12.roles",[548,552,556,560,564,568,572],{"title":549,"path":550,"stem":551},"Creating a Role","\u002Froles\u002Fcreating-a-role","12.roles\u002F01.creating-a-role",{"title":553,"path":554,"stem":555},"Granting Permissions","\u002Froles\u002Fgranting-permissions","12.roles\u002F02.granting-permissions",{"title":557,"path":558,"stem":559},"Row Filters","\u002Froles\u002Frow-filters","12.roles\u002F03.row-filters",{"title":561,"path":562,"stem":563},"Payload Checks","\u002Froles\u002Fpayload-checks","12.roles\u002F04.payload-checks",{"title":565,"path":566,"stem":567},"Members","\u002Froles\u002Fmembers","12.roles\u002F05.members",{"title":569,"path":570,"stem":571},"Access Reviews","\u002Froles\u002Faccess-reviews","12.roles\u002F06.access-reviews",{"title":573,"path":574,"stem":575},"Delegated Administration","\u002Froles\u002Fdelegated-administration","12.roles\u002F07.delegated-administration",{"title":577,"icon":578,"path":579,"stem":580,"children":581,"page":62},"Logs","i-lucide-scroll-text","\u002Flogs","13.logs",[582,586,590],{"title":583,"path":584,"stem":585},"Audit Log","\u002Flogs\u002Faudit-log","13.logs\u002F01.audit-log",{"title":587,"path":588,"stem":589},"An Entry","\u002Flogs\u002Fan-entry","13.logs\u002F02.an-entry",{"title":591,"path":592,"stem":593},"Where Else It Shows","\u002Flogs\u002Fwhere-else-it-shows","13.logs\u002F03.where-else-it-shows",{"title":595,"icon":596,"path":597,"stem":598,"children":599,"page":62},"Data API","i-lucide-braces","\u002Fdata-api","14.data-api",[600,603,607,611,615,619,623,627,631,635,639,643],{"title":118,"path":601,"stem":602},"\u002Fdata-api\u002Foverview","14.data-api\u002F01.overview",{"title":604,"path":605,"stem":606},"Authentication","\u002Fdata-api\u002Fauthentication","14.data-api\u002F02.authentication",{"title":608,"path":609,"stem":610},"Reading","\u002Fdata-api\u002Freading","14.data-api\u002F03.reading",{"title":612,"path":613,"stem":614},"Filtering","\u002Fdata-api\u002Ffiltering","14.data-api\u002F04.filtering",{"title":616,"path":617,"stem":618},"Aggregating","\u002Fdata-api\u002Faggregating","14.data-api\u002F05.aggregating",{"title":620,"path":621,"stem":622},"Writing","\u002Fdata-api\u002Fwriting","14.data-api\u002F06.writing",{"title":624,"path":625,"stem":626},"Nested Writes","\u002Fdata-api\u002Fnested-writes","14.data-api\u002F07.nested-writes",{"title":628,"path":629,"stem":630},"Transactions","\u002Fdata-api\u002Ftransactions","14.data-api\u002F08.transactions",{"title":632,"path":633,"stem":634},"Calling Functions","\u002Fdata-api\u002Fcalling-functions","14.data-api\u002F09.calling-functions",{"title":636,"path":637,"stem":638},"OpenAPI","\u002Fdata-api\u002Fopenapi","14.data-api\u002F10.openapi",{"title":640,"path":641,"stem":642},"Routes","\u002Fdata-api\u002Froutes","14.data-api\u002F11.routes",{"title":644,"path":645,"stem":646},"A client, end to end","\u002Fdata-api\u002Fa-client","14.data-api\u002F12.a-client",{"title":172,"icon":648,"path":649,"stem":650,"children":651,"page":62},"i-lucide-settings","\u002Fsettings","15.settings",[652,655,659,662,665],{"title":189,"path":653,"stem":654},"\u002Fsettings\u002Fgeneral","15.settings\u002F01.general",{"title":656,"path":657,"stem":658},"Access","\u002Fsettings\u002Faccess","15.settings\u002F02.access",{"title":207,"path":660,"stem":661},"\u002Fsettings\u002Fsecurity","15.settings\u002F03.security",{"title":595,"path":663,"stem":664},"\u002Fsettings\u002Fdata-api","15.settings\u002F04.data-api",{"title":666,"path":667,"stem":668},"Features","\u002Fsettings\u002Ffeatures","15.settings\u002F05.features",{"title":670,"icon":671,"path":672,"stem":673,"children":674,"page":62},"User Profile","i-lucide-circle-user","\u002Fuser-profile","16.user-profile",[675,679,682,686,690],{"title":676,"path":677,"stem":678},"My Account","\u002Fuser-profile\u002Fmy-account","16.user-profile\u002F01.my-account",{"title":525,"path":680,"stem":681},"\u002Fuser-profile\u002Fsessions","16.user-profile\u002F02.sessions",{"title":683,"path":684,"stem":685},"Tokens","\u002Fuser-profile\u002Ftokens","16.user-profile\u002F03.tokens",{"title":687,"path":688,"stem":689},"Preferences","\u002Fuser-profile\u002Fpreferences","16.user-profile\u002F04.preferences",{"title":539,"path":691,"stem":692},"\u002Fuser-profile\u002Factivity","16.user-profile\u002F05.activity",{"title":694,"icon":695,"path":696,"stem":697,"children":698,"page":62},"AI Agents","i-lucide-bot","\u002Fai-agents","17.ai-agents",[699,702,705,709,713,717],{"title":118,"path":700,"stem":701},"\u002Fai-agents\u002Foverview","17.ai-agents\u002F01.overview",{"title":683,"path":703,"stem":704},"\u002Fai-agents\u002Ftokens","17.ai-agents\u002F02.tokens",{"title":706,"path":707,"stem":708},"MCP Server","\u002Fai-agents\u002Fmcp-server","17.ai-agents\u002F03.mcp-server",{"title":710,"path":711,"stem":712},"Recipes","\u002Fai-agents\u002Frecipes","17.ai-agents\u002F04.recipes",{"title":714,"path":715,"stem":716},"Tools","\u002Fai-agents\u002Ftools","17.ai-agents\u002F05.tools",{"title":718,"path":719,"stem":720},"llms.txt","\u002Fai-agents\u002Fllms-txt","17.ai-agents\u002F06.llms-txt",{"title":722,"icon":723,"path":724,"stem":725,"children":726,"page":62},"Operations","i-lucide-server","\u002Foperations","18.operations",[727,731,735,739,743],{"title":728,"path":729,"stem":730},"Deployment","\u002Foperations\u002Fdeployment","18.operations\u002F01.deployment",{"title":732,"path":733,"stem":734},"PostgreSQL","\u002Foperations\u002Fpostgresql","18.operations\u002F02.postgresql",{"title":736,"path":737,"stem":738},"Public URL, Proxy and CORS","\u002Foperations\u002Fpublic-url-proxy-cors","18.operations\u002F03.public-url-proxy-cors",{"title":740,"path":741,"stem":742},"Backup and Restore","\u002Foperations\u002Fbackup-restore","18.operations\u002F04.backup-restore",{"title":744,"path":745,"stem":746},"Upgrading","\u002Foperations\u002Fupgrading","18.operations\u002F05.upgrading",{"title":748,"icon":749,"path":750,"stem":751,"children":752,"page":62},"Reference","i-lucide-library","\u002Freference","19.reference",[753,757,761,765,769],{"title":754,"path":755,"stem":756},"Query Language","\u002Freference\u002Fquery-language","19.reference\u002F01.query-language",{"title":758,"path":759,"stem":760},"Errors","\u002Freference\u002Ferrors","19.reference\u002F02.errors",{"title":762,"path":763,"stem":764},"Admin API","\u002Freference\u002Fadmin-api","19.reference\u002F03.admin-api",{"title":766,"path":767,"stem":768},"Authentication API","\u002Freference\u002Fauth-api","19.reference\u002F04.auth-api",{"title":770,"path":771,"stem":772},"Environment Variables","\u002Freference\u002Fenvironment","19.reference\u002F05.environment",{"id":774,"title":12,"admin":775,"body":776,"description":2076,"extension":2077,"links":775,"meta":2078,"navigation":1425,"path":13,"seo":2079,"stem":14,"__hash__":2080},"docs\u002F01.getting-started\u002F02.installation.md",null,{"type":777,"value":778,"toc":2061},"minimark",[779,796,801,828,832,835,858,868,882,888,892,895,1098,1103,1117,1143,1149,1162,1165,1174,1182,1199,1212,1215,1219,1230,1246,1250,1261,1589,1674,1683,1708,1711,1742,1746,1752,1909,1938,1944,1951,1955,1973,1983,1995,2000,2004,2007,2031,2035,2057],[780,781,782,783,787,788,791,792,795],"p",{},"TotalBase runs as one container. It connects to a PostgreSQL database you provide and serves everything on one port: the admin at ",[784,785,786],"code",{},"\u002Fadmin\u002F",", the Data API at ",[784,789,790],{},"\u002Fapi\u002F",", and the MCP server at ",[784,793,794],{},"\u002Fmcp",".",[797,798,800],"h2",{"id":799},"requirements","Requirements",[802,803,804,812,822],"ul",{},[805,806,807,811],"li",{},[808,809,810],"strong",{},"PostgreSQL 15, 16, 17 or 18."," 18 is recommended for new installations. TotalBase won't start on any other major version.",[805,813,814,817,818,821],{},[808,815,816],{},"A database role that is not a superuser."," TotalBase can do exactly what its role can do. If you want to create tables from the admin, the role needs ",[784,819,820],{},"CREATE"," on those schemas, and the simplest way to get that is to make the role the owner of the database.",[805,823,824,827],{},[808,825,826],{},"Docker"," (or any container runtime) to run the server image.",[797,829,831],{"id":830},"prepare-the-database","Prepare the database",[780,833,834],{},"Create a role and a database it owns. As a PostgreSQL superuser:",[836,837,842],"pre",{"className":838,"code":839,"language":840,"meta":841,"style":841},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE ROLE totalbase LOGIN PASSWORD 'change-me';\nCREATE DATABASE acme OWNER totalbase;\n","sql","",[784,843,844,852],{"__ignoreMap":841},[845,846,849],"span",{"class":847,"line":848},"line",1,[845,850,851],{},"CREATE ROLE totalbase LOGIN PASSWORD 'change-me';\n",[845,853,855],{"class":847,"line":854},2,[845,856,857],{},"CREATE DATABASE acme OWNER totalbase;\n",[780,859,860,861,864,865,867],{},"On PostgreSQL 15 and later, the ",[784,862,863],{},"public"," schema belongs to the database owner, so this role can create tables in ",[784,866,863],{}," right away.",[780,869,870,871,874,875,877,878,881],{},"When the server first starts, it creates its own schema, ",[784,872,873],{},"totalbase",", and runs its migrations there. It doesn't touch your other schemas. If a schema named ",[784,876,873],{}," already exists and holds objects TotalBase didn't create, startup stops with ",[784,879,880],{},"TOTALBASE_SCHEMA_CONFLICT"," and changes nothing.",[883,884,885],"tip",{},[780,886,887],{},"An existing database works the same way. Your tables are discovered at startup, but none of them is reachable through the API until you expose it.",[797,889,891],{"id":890},"configure","Configure",[780,893,894],{},"TotalBase reads its configuration from environment variables. Only the database connection and the first administrator live there. Everything else is a setting you change later in the admin.",[896,897,898,914],"table",{},[899,900,901],"thead",{},[902,903,904,908,911],"tr",{},[905,906,907],"th",{},"Variable",[905,909,910],{},"Required",[905,912,913],{},"Meaning",[915,916,917,944,960,986,998,1018,1039,1051,1070,1084],"tbody",{},[902,918,919,935,938],{},[920,921,922,925,926,925,929,925,932],"td",{},[784,923,924],{},"POSTGRES_HOST",", ",[784,927,928],{},"POSTGRES_DB",[784,930,931],{},"POSTGRES_USER",[784,933,934],{},"POSTGRES_PASSWORD",[920,936,937],{},"yes",[920,939,940,941,943],{},"The connection. The role in ",[784,942,931],{}," is the upper limit of what TotalBase can do.",[902,945,946,951,954],{},[920,947,948],{},[784,949,950],{},"POSTGRES_PORT",[920,952,953],{},"no",[920,955,956,957,795],{},"Default ",[784,958,959],{},"5432",[902,961,962,970,972],{},[920,963,964,925,967],{},[784,965,966],{},"POSTGRES_SSL",[784,968,969],{},"POSTGRES_SSL_CA",[920,971,953],{},[920,973,974,977,978,981,982,985],{},[784,975,976],{},"off"," (default), ",[784,979,980],{},"require"," or ",[784,983,984],{},"verify-full","; a managed PostgreSQL usually wants TLS.",[902,987,988,993,995],{},[920,989,990],{},[784,991,992],{},"TOTALBASE_MASTER_KEY",[920,994,953],{},[920,996,997],{},"Encrypts stored secrets (SMTP passwords, OAuth client secrets). At least 32 characters. Never stored in the database. Unset: TotalBase generates one on the first start and keeps it in the data directory.",[902,999,1000,1005,1007],{},[920,1001,1002],{},[784,1003,1004],{},"TOTALBASE_DATA_DIR",[920,1006,953],{},[920,1008,1009,1010,1013,1014,1017],{},"Where TotalBase keeps what it owns on disk - a generated master key (",[784,1011,1012],{},"master.key","). Default ",[784,1015,1016],{},"\u002Fvar\u002Flib\u002Ftotalbase",": mount a volume there.",[902,1019,1020,1028,1030],{},[920,1021,1022,925,1025],{},[784,1023,1024],{},"TOTALBASE_ADMIN_EMAIL",[784,1026,1027],{},"TOTALBASE_ADMIN_PASSWORD",[920,1029,953],{},[920,1031,1032,1033,1038],{},"The first administrator, created on the first start. Unset: you create it in the browser (see ",[1034,1035,1037],"a",{"href":1036},"#the-first-administrator","The first administrator",").",[902,1040,1041,1046,1048],{},[920,1042,1043],{},[784,1044,1045],{},"TOTALBASE_SETUP_CODE",[920,1047,953],{},[920,1049,1050],{},"The code that first setup asks for, when a program sets it (at least 16 characters). Unset: TotalBase generates one.",[902,1052,1053,1058,1060],{},[920,1054,1055],{},[784,1056,1057],{},"TOTALBASE_PUBLIC_URL",[920,1059,953],{},[920,1061,1062,1063,1066,1067,795],{},"The address users reach the instance at, for links in emails and OAuth callbacks. The first setup asks for it too (",[808,1064,1065],{},"Public URL"," in Settings). Unset: ",[784,1068,1069],{},"http:\u002F\u002Flocalhost:\u003Cport>",[902,1071,1072,1077,1079],{},[920,1073,1074],{},[784,1075,1076],{},"TOTALBASE_PORT",[920,1078,953],{},[920,1080,956,1081,795],{},[784,1082,1083],{},"3050",[902,1085,1086,1091,1093],{},[920,1087,1088],{},[784,1089,1090],{},"LOG_LEVEL",[920,1092,953],{},[920,1094,956,1095,795],{},[784,1096,1097],{},"info",[1099,1100,1102],"h3",{"id":1101},"the-master-key","The master key",[780,1104,1105,1106,1108,1109,1112,1113,1116],{},"You don't have to create it. On the first start, without ",[784,1107,992],{},", TotalBase generates a strong key and keeps it in ",[784,1110,1111],{},"\u002Fvar\u002Flib\u002Ftotalbase\u002Fmaster.key",", readable by the server only; ",[808,1114,1115],{},"Status"," shows where it is. Copy that file somewhere safe, apart from the database backups:",[836,1118,1122],{"className":1119,"code":1120,"language":1121,"meta":841,"style":841},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","docker compose cp totalbase:\u002Fvar\u002Flib\u002Ftotalbase\u002Fmaster.key .\u002Fmaster.key\n","bash",[784,1123,1124],{"__ignoreMap":841},[845,1125,1126,1130,1134,1137,1140],{"class":847,"line":848},[845,1127,1129],{"class":1128},"sBMFI","docker",[845,1131,1133],{"class":1132},"sfazB"," compose",[845,1135,1136],{"class":1132}," cp",[845,1138,1139],{"class":1132}," totalbase:\u002Fvar\u002Flib\u002Ftotalbase\u002Fmaster.key",[845,1141,1142],{"class":1132}," .\u002Fmaster.key\n",[780,1144,1145,1146,1148],{},"To set your own instead, put it in ",[784,1147,992],{}," (at least 32 characters; a shorter one stops the start, and the error suggests one). The variable always wins over the file. TotalBase never generates a second key for an installation that already has one: if the file is gone and the variable is unset, it won't start until you restore it.",[1150,1151,1152],"warning",{},[780,1153,1154,1155,1158,1159,795],{},"A full recovery needs both a PostgreSQL backup ",[808,1156,1157],{},"and"," the master key. If you lose the key you keep all your data, but every stored secret becomes unreadable and has to be entered again. If you start with a different key, startup fails with ",[784,1160,1161],{},"INVALID_MASTER_KEY",[1099,1163,1037],{"id":1164},"the-first-administrator",[780,1166,1167,1168,1170,1171,1173],{},"Without ",[784,1169,1024],{}," and ",[784,1172,1027],{},", the first start writes a link to its log:",[836,1175,1180],{"className":1176,"code":1178,"language":1179,"meta":841},[1177],"language-text","TotalBase needs its first administrator - open http:\u002F\u002Flocalhost:3050\u002Fadmin\u002Fsetup?code=K7QP-M2XD-9WFA-H4TN\n","text",[784,1181,1178],{"__ignoreMap":841},[836,1183,1185],{"className":1119,"code":1184,"language":1121,"meta":841,"style":841},"docker compose logs totalbase\n",[784,1186,1187],{"__ignoreMap":841},[845,1188,1189,1191,1193,1196],{"class":847,"line":848},[845,1190,1129],{"class":1128},[845,1192,1133],{"class":1132},[845,1194,1195],{"class":1132}," logs",[845,1197,1198],{"class":1132}," totalbase\n",[780,1200,1201,1202,1205,1206,1209,1210,795],{},"Open it - with the port you published, if not 3050 - and fill in your name, email and password, the public URL and the language; you're signed in as the administrator. The code is single-use and only someone with access to the server can read it - also in ",[784,1203,1204],{},"\u002Fvar\u002Flib\u002Ftotalbase\u002Fsetup-code"," if the log is gone. Once an administrator exists the setup page is gone. A program (an installer, a hosting panel) can do the same with ",[784,1207,1208],{},"POST \u002Fapi\u002Fsetup"," and its own ",[784,1211,1045],{},[780,1213,1214],{},"With the two variables set, the administrator is created at the first start instead, and there is no setup page. They only matter while no user is an administrator; changing them later doesn't change the existing account. Prefer the setup: the password doesn't stay in the container's environment.",[797,1216,1218],{"id":1217},"run-with-docker-compose","Run with Docker Compose",[780,1220,1221,1222,1225,1226,1229],{},"The image is on Docker Hub, for amd64 and arm64: ",[784,1223,1224],{},"totalbase\u002Ftotalbase:beta"," follows the beta, and ",[784,1227,1228],{},"totalbase\u002Ftotalbase:0.1.0-beta.1"," pins one version. Pick the example that matches your setup: a new PostgreSQL next to TotalBase, or a PostgreSQL you already run.",[883,1231,1232],{},[780,1233,1234,1237,1238,1241,1242,1245],{},[808,1235,1236],{},"From the source code instead",", to try a change of your own: ",[784,1239,1240],{},"docker build --target server -t totalbase:local ."," from the repository root, then use ",[784,1243,1244],{},"totalbase:local"," as the image.",[1099,1247,1249],{"id":1248},"from-scratch-postgresql-included","From scratch, PostgreSQL included",[780,1251,1252,1253,1256,1257,1260],{},"This ",[784,1254,1255],{},"docker-compose.yml"," starts PostgreSQL 18 and TotalBase together. The init script creates the non-superuser role and the database, as in the ",[1034,1258,831],{"href":1259},"#prepare-the-database"," section:",[836,1262,1266],{"className":1263,"code":1264,"filename":1255,"language":1265,"meta":841,"style":841},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","services:\n  postgres:\n    image: postgres:18\n    environment:\n      POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD}\n      TOTALBASE_DB_PASSWORD: ${TOTALBASE_DB_PASSWORD}   # read by the init script\n    volumes:\n      - pgdata:\u002Fvar\u002Flib\u002Fpostgresql\n      - .\u002Fpostgres-init:\u002Fdocker-entrypoint-initdb.d:ro\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U postgres -d acme\"]\n      interval: 5s\n      retries: 20\n\n  totalbase:\n    image: totalbase\u002Ftotalbase:beta\n    depends_on:\n      postgres:\n        condition: service_healthy\n    environment:\n      POSTGRES_HOST: postgres\n      POSTGRES_DB: acme\n      POSTGRES_USER: totalbase\n      POSTGRES_PASSWORD: ${TOTALBASE_DB_PASSWORD}\n    volumes:\n      - data:\u002Fvar\u002Flib\u002Ftotalbase       # uploaded files and the generated master key\n    ports:\n      - \"3050:3050\"\n\nvolumes:\n  pgdata:\n  data:\n","yaml",[784,1267,1268,1278,1285,1297,1305,1316,1331,1339,1348,1356,1364,1397,1408,1420,1427,1435,1445,1453,1461,1472,1479,1490,1501,1511,1521,1528,1539,1547,1560,1565,1573,1581],{"__ignoreMap":841},[845,1269,1270,1274],{"class":847,"line":848},[845,1271,1273],{"class":1272},"swJcz","services",[845,1275,1277],{"class":1276},"sMK4o",":\n",[845,1279,1280,1283],{"class":847,"line":854},[845,1281,1282],{"class":1272},"  postgres",[845,1284,1277],{"class":1276},[845,1286,1288,1291,1294],{"class":847,"line":1287},3,[845,1289,1290],{"class":1272},"    image",[845,1292,1293],{"class":1276},":",[845,1295,1296],{"class":1132}," postgres:18\n",[845,1298,1300,1303],{"class":847,"line":1299},4,[845,1301,1302],{"class":1272},"    environment",[845,1304,1277],{"class":1276},[845,1306,1308,1311,1313],{"class":847,"line":1307},5,[845,1309,1310],{"class":1272},"      POSTGRES_PASSWORD",[845,1312,1293],{"class":1276},[845,1314,1315],{"class":1132}," ${POSTGRES_SUPERUSER_PASSWORD}\n",[845,1317,1319,1322,1324,1327],{"class":847,"line":1318},6,[845,1320,1321],{"class":1272},"      TOTALBASE_DB_PASSWORD",[845,1323,1293],{"class":1276},[845,1325,1326],{"class":1132}," ${TOTALBASE_DB_PASSWORD}",[845,1328,1330],{"class":1329},"sHwdD","   # read by the init script\n",[845,1332,1334,1337],{"class":847,"line":1333},7,[845,1335,1336],{"class":1272},"    volumes",[845,1338,1277],{"class":1276},[845,1340,1342,1345],{"class":847,"line":1341},8,[845,1343,1344],{"class":1276},"      -",[845,1346,1347],{"class":1132}," pgdata:\u002Fvar\u002Flib\u002Fpostgresql\n",[845,1349,1351,1353],{"class":847,"line":1350},9,[845,1352,1344],{"class":1276},[845,1354,1355],{"class":1132}," .\u002Fpostgres-init:\u002Fdocker-entrypoint-initdb.d:ro\n",[845,1357,1359,1362],{"class":847,"line":1358},10,[845,1360,1361],{"class":1272},"    healthcheck",[845,1363,1277],{"class":1276},[845,1365,1367,1370,1372,1375,1378,1381,1383,1386,1389,1392,1394],{"class":847,"line":1366},11,[845,1368,1369],{"class":1272},"      test",[845,1371,1293],{"class":1276},[845,1373,1374],{"class":1276}," [",[845,1376,1377],{"class":1276},"\"",[845,1379,1380],{"class":1132},"CMD-SHELL",[845,1382,1377],{"class":1276},[845,1384,1385],{"class":1276},",",[845,1387,1388],{"class":1276}," \"",[845,1390,1391],{"class":1132},"pg_isready -U postgres -d acme",[845,1393,1377],{"class":1276},[845,1395,1396],{"class":1276},"]\n",[845,1398,1400,1403,1405],{"class":847,"line":1399},12,[845,1401,1402],{"class":1272},"      interval",[845,1404,1293],{"class":1276},[845,1406,1407],{"class":1132}," 5s\n",[845,1409,1411,1414,1416],{"class":847,"line":1410},13,[845,1412,1413],{"class":1272},"      retries",[845,1415,1293],{"class":1276},[845,1417,1419],{"class":1418},"sbssI"," 20\n",[845,1421,1423],{"class":847,"line":1422},14,[845,1424,1426],{"emptyLinePlaceholder":1425},true,"\n",[845,1428,1430,1433],{"class":847,"line":1429},15,[845,1431,1432],{"class":1272},"  totalbase",[845,1434,1277],{"class":1276},[845,1436,1438,1440,1442],{"class":847,"line":1437},16,[845,1439,1290],{"class":1272},[845,1441,1293],{"class":1276},[845,1443,1444],{"class":1132}," totalbase\u002Ftotalbase:beta\n",[845,1446,1448,1451],{"class":847,"line":1447},17,[845,1449,1450],{"class":1272},"    depends_on",[845,1452,1277],{"class":1276},[845,1454,1456,1459],{"class":847,"line":1455},18,[845,1457,1458],{"class":1272},"      postgres",[845,1460,1277],{"class":1276},[845,1462,1464,1467,1469],{"class":847,"line":1463},19,[845,1465,1466],{"class":1272},"        condition",[845,1468,1293],{"class":1276},[845,1470,1471],{"class":1132}," service_healthy\n",[845,1473,1475,1477],{"class":847,"line":1474},20,[845,1476,1302],{"class":1272},[845,1478,1277],{"class":1276},[845,1480,1482,1485,1487],{"class":847,"line":1481},21,[845,1483,1484],{"class":1272},"      POSTGRES_HOST",[845,1486,1293],{"class":1276},[845,1488,1489],{"class":1132}," postgres\n",[845,1491,1493,1496,1498],{"class":847,"line":1492},22,[845,1494,1495],{"class":1272},"      POSTGRES_DB",[845,1497,1293],{"class":1276},[845,1499,1500],{"class":1132}," acme\n",[845,1502,1504,1507,1509],{"class":847,"line":1503},23,[845,1505,1506],{"class":1272},"      POSTGRES_USER",[845,1508,1293],{"class":1276},[845,1510,1198],{"class":1132},[845,1512,1514,1516,1518],{"class":847,"line":1513},24,[845,1515,1310],{"class":1272},[845,1517,1293],{"class":1276},[845,1519,1520],{"class":1132}," ${TOTALBASE_DB_PASSWORD}\n",[845,1522,1524,1526],{"class":847,"line":1523},25,[845,1525,1336],{"class":1272},[845,1527,1277],{"class":1276},[845,1529,1531,1533,1536],{"class":847,"line":1530},26,[845,1532,1344],{"class":1276},[845,1534,1535],{"class":1132}," data:\u002Fvar\u002Flib\u002Ftotalbase",[845,1537,1538],{"class":1329},"       # uploaded files and the generated master key\n",[845,1540,1542,1545],{"class":847,"line":1541},27,[845,1543,1544],{"class":1272},"    ports",[845,1546,1277],{"class":1276},[845,1548,1550,1552,1554,1557],{"class":847,"line":1549},28,[845,1551,1344],{"class":1276},[845,1553,1388],{"class":1276},[845,1555,1556],{"class":1132},"3050:3050",[845,1558,1559],{"class":1276},"\"\n",[845,1561,1563],{"class":847,"line":1562},29,[845,1564,1426],{"emptyLinePlaceholder":1425},[845,1566,1568,1571],{"class":847,"line":1567},30,[845,1569,1570],{"class":1272},"volumes",[845,1572,1277],{"class":1276},[845,1574,1576,1579],{"class":847,"line":1575},31,[845,1577,1578],{"class":1272},"  pgdata",[845,1580,1277],{"class":1276},[845,1582,1584,1587],{"class":847,"line":1583},32,[845,1585,1586],{"class":1272},"  data",[845,1588,1277],{"class":1276},[836,1590,1593],{"className":1119,"code":1591,"filename":1592,"language":1121,"meta":841,"style":841},"#!\u002Fbin\u002Fbash\nset -euo pipefail\npsql -v ON_ERROR_STOP=1 --username \"$POSTGRES_USER\" --dbname postgres \u003C\u003CEOSQL\nCREATE ROLE totalbase LOGIN PASSWORD '${TOTALBASE_DB_PASSWORD}';\nCREATE DATABASE acme OWNER totalbase;\nEOSQL\n","postgres-init\u002F01-totalbase.sh",[784,1594,1595,1600,1612,1649,1666,1670],{"__ignoreMap":841},[845,1596,1597],{"class":847,"line":848},[845,1598,1599],{"class":1329},"#!\u002Fbin\u002Fbash\n",[845,1601,1602,1606,1609],{"class":847,"line":854},[845,1603,1605],{"class":1604},"s2Zo4","set",[845,1607,1608],{"class":1132}," -euo",[845,1610,1611],{"class":1132}," pipefail\n",[845,1613,1614,1617,1620,1623,1626,1629,1631,1635,1637,1640,1643,1646],{"class":847,"line":1287},[845,1615,1616],{"class":1128},"psql",[845,1618,1619],{"class":1132}," -v",[845,1621,1622],{"class":1132}," ON_ERROR_STOP=",[845,1624,1625],{"class":1418},"1",[845,1627,1628],{"class":1132}," --username",[845,1630,1388],{"class":1276},[845,1632,1634],{"class":1633},"sTEyZ","$POSTGRES_USER",[845,1636,1377],{"class":1276},[845,1638,1639],{"class":1132}," --dbname",[845,1641,1642],{"class":1132}," postgres",[845,1644,1645],{"class":1276}," \u003C\u003C",[845,1647,1648],{"class":1276},"EOSQL\n",[845,1650,1651,1654,1657,1660,1663],{"class":847,"line":1299},[845,1652,1653],{"class":1132},"CREATE ROLE totalbase LOGIN PASSWORD '",[845,1655,1656],{"class":1276},"${",[845,1658,1659],{"class":1633},"TOTALBASE_DB_PASSWORD",[845,1661,1662],{"class":1276},"}",[845,1664,1665],{"class":1132},"';\n",[845,1667,1668],{"class":847,"line":1307},[845,1669,857],{"class":1132},[845,1671,1672],{"class":847,"line":1318},[845,1673,1648],{"class":1276},[780,1675,1676,1677,1680,1681,1293],{},"Put the passwords in an ",[784,1678,1679],{},".env"," file next to ",[784,1682,1255],{},[836,1684,1686],{"className":1119,"code":1685,"filename":1679,"language":1121,"meta":841,"style":841},"POSTGRES_SUPERUSER_PASSWORD=change-me-too\nTOTALBASE_DB_PASSWORD=change-me\n",[784,1687,1688,1699],{"__ignoreMap":841},[845,1689,1690,1693,1696],{"class":847,"line":848},[845,1691,1692],{"class":1633},"POSTGRES_SUPERUSER_PASSWORD",[845,1694,1695],{"class":1276},"=",[845,1697,1698],{"class":1132},"change-me-too\n",[845,1700,1701,1703,1705],{"class":847,"line":854},[845,1702,1659],{"class":1633},[845,1704,1695],{"class":1276},[845,1706,1707],{"class":1132},"change-me\n",[780,1709,1710],{},"Then start both services:",[836,1712,1714],{"className":1119,"code":1713,"language":1121,"meta":841,"style":841},"docker compose up -d\ndocker compose logs totalbase   # the link to create the first administrator\n",[784,1715,1716,1728],{"__ignoreMap":841},[845,1717,1718,1720,1722,1725],{"class":847,"line":848},[845,1719,1129],{"class":1128},[845,1721,1133],{"class":1132},[845,1723,1724],{"class":1132}," up",[845,1726,1727],{"class":1132}," -d\n",[845,1729,1730,1732,1734,1736,1739],{"class":847,"line":854},[845,1731,1129],{"class":1128},[845,1733,1133],{"class":1132},[845,1735,1195],{"class":1132},[845,1737,1738],{"class":1132}," totalbase",[845,1740,1741],{"class":1329},"   # the link to create the first administrator\n",[1099,1743,1745],{"id":1744},"against-a-postgresql-that-is-already-running","Against a PostgreSQL that is already running",[780,1747,1748,1749,1751],{},"With a PostgreSQL of your own (on another server, a managed service, or the host machine), TotalBase is the only service. Create its role and database there first, as in ",[1034,1750,831],{"href":1259},", and point the connection at it:",[836,1753,1755],{"className":1263,"code":1754,"filename":1255,"language":1265,"meta":841,"style":841},"services:\n  totalbase:\n    image: totalbase\u002Ftotalbase:beta\n    environment:\n      POSTGRES_HOST: db.example.internal    # host.docker.internal for a PostgreSQL on this machine\n      POSTGRES_PORT: 5432\n      POSTGRES_DB: acme\n      POSTGRES_USER: totalbase\n      POSTGRES_PASSWORD: ${TOTALBASE_DB_PASSWORD}\n      POSTGRES_SSL: require                 # most managed services want TLS; off on a local network\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"   # only for a PostgreSQL on this machine\n    volumes:\n      - data:\u002Fvar\u002Flib\u002Ftotalbase       # uploaded files and the generated master key\n    ports:\n      - \"3050:3050\"\n\nvolumes:\n  data:\n",[784,1756,1757,1763,1769,1777,1783,1795,1805,1813,1821,1829,1842,1849,1863,1869,1877,1883,1893,1897,1903],{"__ignoreMap":841},[845,1758,1759,1761],{"class":847,"line":848},[845,1760,1273],{"class":1272},[845,1762,1277],{"class":1276},[845,1764,1765,1767],{"class":847,"line":854},[845,1766,1432],{"class":1272},[845,1768,1277],{"class":1276},[845,1770,1771,1773,1775],{"class":847,"line":1287},[845,1772,1290],{"class":1272},[845,1774,1293],{"class":1276},[845,1776,1444],{"class":1132},[845,1778,1779,1781],{"class":847,"line":1299},[845,1780,1302],{"class":1272},[845,1782,1277],{"class":1276},[845,1784,1785,1787,1789,1792],{"class":847,"line":1307},[845,1786,1484],{"class":1272},[845,1788,1293],{"class":1276},[845,1790,1791],{"class":1132}," db.example.internal",[845,1793,1794],{"class":1329},"    # host.docker.internal for a PostgreSQL on this machine\n",[845,1796,1797,1800,1802],{"class":847,"line":1318},[845,1798,1799],{"class":1272},"      POSTGRES_PORT",[845,1801,1293],{"class":1276},[845,1803,1804],{"class":1418}," 5432\n",[845,1806,1807,1809,1811],{"class":847,"line":1333},[845,1808,1495],{"class":1272},[845,1810,1293],{"class":1276},[845,1812,1500],{"class":1132},[845,1814,1815,1817,1819],{"class":847,"line":1341},[845,1816,1506],{"class":1272},[845,1818,1293],{"class":1276},[845,1820,1198],{"class":1132},[845,1822,1823,1825,1827],{"class":847,"line":1350},[845,1824,1310],{"class":1272},[845,1826,1293],{"class":1276},[845,1828,1520],{"class":1132},[845,1830,1831,1834,1836,1839],{"class":847,"line":1358},[845,1832,1833],{"class":1272},"      POSTGRES_SSL",[845,1835,1293],{"class":1276},[845,1837,1838],{"class":1132}," require",[845,1840,1841],{"class":1329},"                 # most managed services want TLS; off on a local network\n",[845,1843,1844,1847],{"class":847,"line":1366},[845,1845,1846],{"class":1272},"    extra_hosts",[845,1848,1277],{"class":1276},[845,1850,1851,1853,1855,1858,1860],{"class":847,"line":1399},[845,1852,1344],{"class":1276},[845,1854,1388],{"class":1276},[845,1856,1857],{"class":1132},"host.docker.internal:host-gateway",[845,1859,1377],{"class":1276},[845,1861,1862],{"class":1329},"   # only for a PostgreSQL on this machine\n",[845,1864,1865,1867],{"class":847,"line":1410},[845,1866,1336],{"class":1272},[845,1868,1277],{"class":1276},[845,1870,1871,1873,1875],{"class":847,"line":1422},[845,1872,1344],{"class":1276},[845,1874,1535],{"class":1132},[845,1876,1538],{"class":1329},[845,1878,1879,1881],{"class":847,"line":1429},[845,1880,1544],{"class":1272},[845,1882,1277],{"class":1276},[845,1884,1885,1887,1889,1891],{"class":847,"line":1437},[845,1886,1344],{"class":1276},[845,1888,1388],{"class":1276},[845,1890,1556],{"class":1132},[845,1892,1559],{"class":1276},[845,1894,1895],{"class":847,"line":1447},[845,1896,1426],{"emptyLinePlaceholder":1425},[845,1898,1899,1901],{"class":847,"line":1455},[845,1900,1570],{"class":1272},[845,1902,1277],{"class":1276},[845,1904,1905,1907],{"class":847,"line":1463},[845,1906,1586],{"class":1272},[845,1908,1277],{"class":1276},[780,1910,1911,1912,1914,1915,1917,1918,1921,1922,1925,1926,1929,1930,1933,1934,1937],{},"The same ",[784,1913,1679],{},", without ",[784,1916,1692],{},". Then ",[784,1919,1920],{},"docker compose up -d",". A PostgreSQL on this machine must accept connections from Docker's network: ",[784,1923,1924],{},"listen_addresses"," in ",[784,1927,1928],{},"postgresql.conf"," and a ",[784,1931,1932],{},"host"," line in ",[784,1935,1936],{},"pg_hba.conf"," for the role.",[780,1939,1940,1941,1943],{},"The database may already hold your tables. TotalBase adds only its own ",[784,1942,873],{}," schema; your tables show up as resources, hidden until you expose them.",[780,1945,1946,1947,1950],{},"In both examples the ",[784,1948,1949],{},"files"," volume holds uploaded files. Back it up together with the database.",[797,1952,1954],{"id":1953},"check-that-its-running","Check that it's running",[836,1956,1958],{"className":1119,"code":1957,"language":1121,"meta":841,"style":841},"curl http:\u002F\u002Flocalhost:3050\u002Fhealth\u002Fready\n# {\"status\":\"ready\"}\n",[784,1959,1960,1968],{"__ignoreMap":841},[845,1961,1962,1965],{"class":847,"line":848},[845,1963,1964],{"class":1128},"curl",[845,1966,1967],{"class":1132}," http:\u002F\u002Flocalhost:3050\u002Fhealth\u002Fready\n",[845,1969,1970],{"class":847,"line":854},[845,1971,1972],{"class":1329},"# {\"status\":\"ready\"}\n",[780,1974,1975,1978,1979,1982],{},[784,1976,1977],{},"\u002Fhealth\u002Flive"," answers as soon as the process is up. ",[784,1980,1981],{},"\u002Fhealth\u002Fready"," answers once migrations have run and the database is reachable. Use it for a load balancer's health check.",[780,1984,1985,1986,1989,1990,1170,1992,1994],{},"Open the link from the log to create the first administrator (",[784,1987,1988],{},"http:\u002F\u002Flocalhost:3050\u002Fadmin\u002F"," takes you there too, and asks for the code). With ",[784,1991,1024],{},[784,1993,1027],{}," set, sign in with them instead.",[1996,1997],"screenshot",{"caption":1998,"id":1999},"A new instance asks for its first administrator.","install-setup",[797,2001,2003],{"id":2002},"what-happens-on-startup","What happens on startup",[780,2005,2006],{},"Each start runs the same sequence. If any step fails, the process stops before it accepts requests:",[2008,2009,2010,2013,2019,2022,2025,2028],"ol",{},[805,2011,2012],{},"Connect to PostgreSQL and check the major version (15-18).",[805,2014,2015,2016,2018],{},"Create the ",[784,2017,873],{}," schema if it doesn't exist, and apply pending migrations, each one in its own transaction.",[805,2020,2021],{},"Check the master key - the variable, else the file in the data directory, else (a new installation only) a new one.",[805,2023,2024],{},"Create the first administrator from the variables if no user is an administrator yet; without them, write the setup link to the log.",[805,2026,2027],{},"Read the PostgreSQL catalog and register every table, view and function as a resource. New resources start hidden.",[805,2029,2030],{},"Start listening, and start the background workers.",[797,2032,2034],{"id":2033},"next-steps","Next steps",[802,2036,2037,2042,2047,2052],{},[805,2038,2039,2041],{},[1034,2040,16],{"href":17},": describe an application and let an agent build it.",[805,2043,2044,2046],{},[1034,2045,20],{"href":21},": build a table, a kanban board and a dashboard yourself.",[805,2048,2049,2051],{},[1034,2050,728],{"href":729},": TLS, a reverse proxy and the public URL in production.",[805,2053,2054,795],{},[1034,2055,2056],{"href":741},"Backup and restore",[2058,2059,2060],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":841,"searchDepth":848,"depth":854,"links":2062},[2063,2064,2065,2069,2073,2074,2075],{"id":799,"depth":854,"text":800},{"id":830,"depth":854,"text":831},{"id":890,"depth":854,"text":891,"children":2066},[2067,2068],{"id":1101,"depth":1287,"text":1102},{"id":1164,"depth":1287,"text":1037},{"id":1217,"depth":854,"text":1218,"children":2070},[2071,2072],{"id":1248,"depth":1287,"text":1249},{"id":1744,"depth":1287,"text":1745},{"id":1953,"depth":854,"text":1954},{"id":2002,"depth":854,"text":2003},{"id":2033,"depth":854,"text":2034},"Run TotalBase with Docker against your PostgreSQL 15-18 database.","md",{},{"title":12,"description":2076},"EtC9zbVFyVxvWiBsvtMAOk8yr7UotrAjGROMNqEZTI8",[2082,2084],{"title":10,"path":6,"stem":7,"description":2083,"children":-1},"What TotalBase is: a PostgreSQL application platform you can build by hand or by describing what you need to an AI agent.",{"title":16,"path":17,"stem":18,"description":2085,"children":-1},"Describe the application you need in plain language, and an AI agent builds it in TotalBase: tables, rules, roles, screens, dashboards and workflows.",1792339941046]