[{"data":1,"prerenderedAt":728},["ShallowReactive",2],{"navigation":3,"\u002Fbooki-documentation\u002F3.local-development":303,"\u002Fbooki-documentation\u002F3.local-development-surround":723},[4,55,105],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":54},"Nuxt Guide","i-lucide-layout","\u002Fnuxt-guide","1.nuxt-guide",[10,14,19,24,29,34,39,44,49],{"title":11,"path":12,"stem":13,"icon":6},"Overview","\u002Fnuxt-guide\u002Foverview","1.nuxt-guide\u002F1.overview",{"title":15,"path":16,"stem":17,"icon":18},"Folder Structure","\u002Fnuxt-guide\u002Ffolder-structure","1.nuxt-guide\u002F2.folder-structure","i-lucide-folder-tree",{"title":20,"path":21,"stem":22,"icon":23},"Components","\u002Fnuxt-guide\u002Fcomponents","1.nuxt-guide\u002F3.components","i-lucide-component",{"title":25,"path":26,"stem":27,"icon":28},"Composables","\u002Fnuxt-guide\u002Fcomposables","1.nuxt-guide\u002F4.composables","i-lucide-puzzle",{"title":30,"path":31,"stem":32,"icon":33},"Pages & Routing","\u002Fnuxt-guide\u002Fpages-routing","1.nuxt-guide\u002F5.pages-routing","i-lucide-file-text",{"title":35,"path":36,"stem":37,"icon":38},"Middleware","\u002Fnuxt-guide\u002Fmiddleware","1.nuxt-guide\u002F6.middleware","i-lucide-shield-check",{"title":40,"path":41,"stem":42,"icon":43},"Plugins","\u002Fnuxt-guide\u002Fplugins","1.nuxt-guide\u002F7.plugins","i-lucide-plug",{"title":45,"path":46,"stem":47,"icon":48},"State Management","\u002Fnuxt-guide\u002Fstate-management","1.nuxt-guide\u002F8.state-management","i-lucide-database",{"title":50,"path":51,"stem":52,"icon":53},"TypeScript","\u002Fnuxt-guide\u002Ftypescript","1.nuxt-guide\u002F9.typescript","i-lucide-braces",false,{"title":56,"icon":57,"path":58,"stem":59,"children":60,"page":54},"Node \u002F Express Guide","i-lucide-server","\u002Fnode-express-guide","2.node-express-guide",[61,64,69,72,77,82,86,91,96,100],{"title":11,"path":62,"stem":63,"icon":57},"\u002Fnode-express-guide\u002Foverview","2.node-express-guide\u002F1.overview",{"title":65,"path":66,"stem":67,"icon":68},"Error Handling","\u002Fnode-express-guide\u002Ferror-handling","2.node-express-guide\u002F10.error-handling","i-lucide-alert-triangle",{"title":15,"path":70,"stem":71,"icon":18},"\u002Fnode-express-guide\u002Ffolder-structure","2.node-express-guide\u002F2.folder-structure",{"title":73,"path":74,"stem":75,"icon":76},"Controllers","\u002Fnode-express-guide\u002Fcontrollers","2.node-express-guide\u002F3.controllers","i-lucide-cpu",{"title":78,"path":79,"stem":80,"icon":81},"Services","\u002Fnode-express-guide\u002Fservices","2.node-express-guide\u002F4.services","i-lucide-workflow",{"title":83,"path":84,"stem":85,"icon":48},"Repositories","\u002Fnode-express-guide\u002Frepositories","2.node-express-guide\u002F5.repositories",{"title":87,"path":88,"stem":89,"icon":90},"Models","\u002Fnode-express-guide\u002Fmodels","2.node-express-guide\u002F6.models","i-lucide-boxes",{"title":92,"path":93,"stem":94,"icon":95},"Routes","\u002Fnode-express-guide\u002Froutes","2.node-express-guide\u002F7.routes","i-lucide-route",{"title":35,"path":97,"stem":98,"icon":99},"\u002Fnode-express-guide\u002Fmiddleware","2.node-express-guide\u002F8.middleware","i-lucide-shield",{"title":101,"path":102,"stem":103,"icon":104},"Validation","\u002Fnode-express-guide\u002Fvalidation","2.node-express-guide\u002F9.validation","i-lucide-check-circle",{"title":106,"icon":107,"path":108,"stem":109,"children":110,"page":54},"Booki Documentation","i-lucide-book-open","\u002Fbooki-documentation","3.booki-documentation",[111,115,120,125,130,229,244,257],{"title":112,"path":113,"stem":114,"icon":107},"Project Overview","\u002Fbooki-documentation\u002Foverview","3.booki-documentation\u002F1.overview",{"title":116,"path":117,"stem":118,"icon":119},"Installation","\u002Fbooki-documentation\u002F1.installation","3.booki-documentation\u002F2.1.installation","i-lucide-download",{"title":121,"path":122,"stem":123,"icon":124},"Development Overview","\u002Fbooki-documentation\u002F2.architecture","3.booki-documentation\u002F2.2.architecture","i-lucide-layers",{"title":126,"path":127,"stem":128,"icon":129},"Local Development","\u002Fbooki-documentation\u002F3.local-development","3.booki-documentation\u002F2.3.local-development","i-lucide-monitor",{"title":131,"icon":57,"path":132,"stem":133,"children":134,"page":54},"API","\u002Fbooki-documentation\u002Fapi","3.booki-documentation\u002F3.api",[135,139,144,149,154,159,163,168,173,178,183,188,192,197,202,206,211,216,220,224],{"title":136,"path":137,"stem":138,"icon":57},"Booki API Reference","\u002Fbooki-documentation\u002Fapi\u002Fbooki-api","3.booki-documentation\u002F3.api\u002F1.booki-api",{"title":140,"path":141,"stem":142,"icon":143},"Auth - Login & Refresh","\u002Fbooki-documentation\u002Fapi\u002Fauth","3.booki-documentation\u002F3.api\u002F2.auth","i-lucide-key",{"title":145,"path":146,"stem":147,"icon":148},"Auth - Customer Registration","\u002Fbooki-documentation\u002Fapi\u002Fauth-customer-register","3.booki-documentation\u002F3.api\u002F2.auth-customer-register","i-lucide-user-check",{"title":150,"path":151,"stem":152,"icon":153},"Auth - Owner Registration","\u002Fbooki-documentation\u002Fapi\u002Fauth-owner-register","3.booki-documentation\u002F3.api\u002F2.auth-owner-register","i-lucide-user-plus",{"title":155,"path":156,"stem":157,"icon":158},"Bookings","\u002Fbooki-documentation\u002Fapi\u002Fbookings","3.booki-documentation\u002F3.api\u002F3.bookings","i-lucide-calendar-check",{"title":160,"path":161,"stem":162,"icon":158},"Bookings - Authenticated","\u002Fbooki-documentation\u002Fapi\u002Fbookings-auth","3.booki-documentation\u002F3.api\u002F3.bookings-auth",{"title":164,"path":165,"stem":166,"icon":167},"Bookings - Public & Guest","\u002Fbooki-documentation\u002Fapi\u002Fbookings-public","3.booki-documentation\u002F3.api\u002F3.bookings-public","i-lucide-calendar-plus",{"title":169,"path":170,"stem":171,"icon":172},"Booking Services","\u002Fbooki-documentation\u002Fapi\u002Fbooking-services","3.booki-documentation\u002F3.api\u002F4.booking-services","i-lucide-box",{"title":174,"path":175,"stem":176,"icon":177},"Organizations - Branches","\u002Fbooki-documentation\u002Fapi\u002Fbranches","3.booki-documentation\u002F3.api\u002F5.branches","i-lucide-git-branch",{"title":179,"path":180,"stem":181,"icon":182},"Organizations - Business Hours","\u002Fbooki-documentation\u002Fapi\u002Fbusiness-hours","3.booki-documentation\u002F3.api\u002F5.business-hours","i-lucide-clock",{"title":184,"path":185,"stem":186,"icon":187},"Organizations - Base","\u002Fbooki-documentation\u002Fapi\u002Forganizations","3.booki-documentation\u002F3.api\u002F5.organizations","i-lucide-building-2",{"title":189,"path":190,"stem":191,"icon":172},"Organizations - Packages","\u002Fbooki-documentation\u002Fapi\u002Fpackages","3.booki-documentation\u002F3.api\u002F5.packages",{"title":193,"path":194,"stem":195,"icon":196},"Organizations - Payments & Integrations","\u002Fbooki-documentation\u002Fapi\u002Fpayments","3.booki-documentation\u002F3.api\u002F5.payments","i-lucide-credit-card",{"title":198,"path":199,"stem":200,"icon":201},"Users - Profile & Settings","\u002Fbooki-documentation\u002Fapi\u002Fusers","3.booki-documentation\u002F3.api\u002F6.users","i-lucide-user",{"title":203,"path":204,"stem":205,"icon":196},"Maya Payments","\u002Fbooki-documentation\u002Fapi\u002Fmaya","3.booki-documentation\u002F3.api\u002F7.maya",{"title":207,"path":208,"stem":209,"icon":210},"Owner - Booking Management","\u002Fbooki-documentation\u002Fapi\u002Fowner-bookings","3.booki-documentation\u002F3.api\u002F7.owner-bookings","i-lucide-calendar",{"title":212,"path":213,"stem":214,"icon":215},"Owner - Customer Management","\u002Fbooki-documentation\u002Fapi\u002Fowner-customers","3.booki-documentation\u002F3.api\u002F7.owner-customers","i-lucide-users",{"title":217,"path":218,"stem":219,"icon":196},"Admin - Billing & Subscriptions","\u002Fbooki-documentation\u002Fapi\u002Fadmin-billing","3.booki-documentation\u002F3.api\u002F8.admin-billing",{"title":221,"path":222,"stem":223,"icon":187},"Admin - Organizations Management","\u002Fbooki-documentation\u002Fapi\u002Fadmin-organizations","3.booki-documentation\u002F3.api\u002F8.admin-organizations",{"title":225,"path":226,"stem":227,"icon":228},"Admin - User Management","\u002Fbooki-documentation\u002Fapi\u002Fadmin-users","3.booki-documentation\u002F3.api\u002F8.admin-users","i-lucide-shield-admin",{"title":230,"icon":231,"path":232,"stem":233,"children":234,"page":54},"Shared","i-lucide-package","\u002Fbooki-documentation\u002Fshared","3.booki-documentation\u002F4.shared",[235,240],{"title":236,"path":237,"stem":238,"icon":239},"codi-node-utils","\u002Fbooki-documentation\u002Fshared\u002Fcodi-node-utils","3.booki-documentation\u002F4.shared\u002F1.codi-node-utils","i-lucide-wrench",{"title":241,"path":242,"stem":243,"icon":124},"codi-layer","\u002Fbooki-documentation\u002Fshared\u002Fcodi-layer","3.booki-documentation\u002F4.shared\u002F2.codi-layer",{"title":245,"path":246,"stem":247,"children":248,"page":54},"Flowcharts","\u002Fbooki-documentation\u002Fflowcharts","3.booki-documentation\u002F5.flowcharts",[249,253],{"title":250,"path":251,"stem":252,"icon":158},"Owner Booking Management Flow","\u002Fbooki-documentation\u002Fflowcharts\u002Fowner-booking-management","3.booki-documentation\u002F5.flowcharts\u002F1.owner-booking-management",{"title":254,"path":255,"stem":256,"icon":167},"Customer Booking Flow","\u002Fbooki-documentation\u002Fflowcharts\u002Fcustomer-booking-flow","3.booki-documentation\u002F5.flowcharts\u002F2.customer-booking-flow",{"title":258,"path":259,"stem":260,"children":261,"page":54},"Guides","\u002Fbooki-documentation\u002Fguides","3.booki-documentation\u002Fguides",[262,267,271,275,280,285,290,294,298],{"title":263,"path":264,"stem":265,"icon":266},"Guide - Authentication Flow & Sessions","\u002Fbooki-documentation\u002Fguides\u002Fguides-auth-flow","3.booki-documentation\u002Fguides\u002Fguides-auth-flow","i-lucide-lock",{"title":268,"path":269,"stem":270,"icon":177},"Guide - Branch Management","\u002Fbooki-documentation\u002Fguides\u002Fguides-branch-management","3.booki-documentation\u002Fguides\u002Fguides-branch-management",{"title":272,"path":273,"stem":274,"icon":196},"Guide - Customer Payment Methods","\u002Fbooki-documentation\u002Fguides\u002Fguides-customer-payments","3.booki-documentation\u002Fguides\u002Fguides-customer-payments",{"title":276,"path":277,"stem":278,"icon":279},"Guide - Environment Setup","\u002Fbooki-documentation\u002Fguides\u002Fguides-environment-setup","3.booki-documentation\u002Fguides\u002Fguides-environment-setup","i-lucide-settings",{"title":281,"path":282,"stem":283,"icon":284},"Guide - Common Error Responses","\u002Fbooki-documentation\u002Fguides\u002Fguides-errors","3.booki-documentation\u002Fguides\u002Fguides-errors","i-lucide-alert-circle",{"title":286,"path":287,"stem":288,"icon":289},"Guide - Gmail SMTP Setup","\u002Fbooki-documentation\u002Fguides\u002Fguides-gmail-setup","3.booki-documentation\u002Fguides\u002Fguides-gmail-setup","i-lucide-mail",{"title":291,"path":292,"stem":293,"icon":124},"Guide - Multi-Tenancy & Tenant Slug Resolution","\u002Fbooki-documentation\u002Fguides\u002Fguides-multi-tenancy","3.booki-documentation\u002Fguides\u002Fguides-multi-tenancy",{"title":295,"path":296,"stem":297,"icon":48},"Guide - Redis Caching","\u002Fbooki-documentation\u002Fguides\u002Fguides-redis","3.booki-documentation\u002Fguides\u002Fguides-redis",{"title":299,"path":300,"stem":301,"icon":302},"Guide - Subscription Billing","\u002Fbooki-documentation\u002Fguides\u002Fguides-subscription-billing","3.booki-documentation\u002Fguides\u002Fguides-subscription-billing","i-lucide-receipt",{"id":304,"title":126,"body":305,"description":716,"extension":717,"links":718,"meta":719,"navigation":720,"path":127,"seo":721,"stem":128,"__hash__":722},"docs\u002F3.booki-documentation\u002F2.3.local-development.md",{"type":306,"value":307,"toc":703},"minimark",[308,317,322,411,414,418,421,431,433,437,444,450,452,456,459,465,470,517,528,533,548,550,557,567,580,605,607,614,636,676,678,682,699],[309,310,311,312,316],"p",{},"Each Booki app runs on a separate port. One app requires a ",[313,314,315],"strong",{},"subdomain"," in the local URL to simulate the multi-tenant pattern used in production.",[318,319,321],"h2",{"id":320},"quick-reference","Quick Reference",[323,324,325,341],"table",{},[326,327,328],"thead",{},[329,330,331,335,338],"tr",{},[332,333,334],"th",{},"App",[332,336,337],{},"Local URL Pattern",[332,339,340],{},"Example",[342,343,344,362,378,395],"tbody",{},[329,345,346,353,358],{},[347,348,349],"td",{},[350,351,352],"code",{},"cms-booki-web-app",[347,354,355],{},[350,356,357],{},"http:\u002F\u002Flocalhost:3000\u002F",[347,359,360],{},[350,361,357],{},[329,363,364,369,374],{},[347,365,366],{},[350,367,368],{},"owner-booki-web-app",[347,370,371],{},[350,372,373],{},"http:\u002F\u002Flocalhost:3001\u002F",[347,375,376],{},[350,377,373],{},[329,379,380,385,390],{},[347,381,382],{},[350,383,384],{},"customer-booki-web-app",[347,386,387],{},[350,388,389],{},"http:\u002F\u002F{slug}.localhost:3002\u002F{branchSlug}",[347,391,392],{},[350,393,394],{},"http:\u002F\u002Fjanesbeautysalon.localhost:3002\u002Fpampanga",[329,396,397,402,407],{},[347,398,399],{},[350,400,401],{},"admin-booki-web-app",[347,403,404],{},[350,405,406],{},"http:\u002F\u002Flocalhost:3003\u002F",[347,408,409],{},[350,410,406],{},[412,413],"hr",{},[318,415,417],{"id":416},"cms-owner-admin-apps","CMS, Owner & Admin Apps",[309,419,420],{},"These apps have no tenant context in the URL. Access them directly on their port — no subdomain required.",[422,423,428],"pre",{"className":424,"code":426,"language":427},[425],"language-text","http:\u002F\u002Flocalhost:3000\u002F   # cms-booki-web-app\nhttp:\u002F\u002Flocalhost:3001\u002F   # owner-booki-web-app\nhttp:\u002F\u002Flocalhost:3003\u002F   # admin-booki-web-app\n","text",[350,429,426],{"__ignoreMap":430},"",[412,432],{},[318,434,436],{"id":435},"owner-app","Owner App",[309,438,439,440,443],{},"The owner app runs directly on its port — no subdomain required. The organization context is derived entirely from the authenticated user's JWT (",[350,441,442],{},"req.user.organizationId",") after login.",[422,445,448],{"className":446,"code":447,"language":427},[425],"http:\u002F\u002Flocalhost:3001\u002F\n",[350,449,447],{"__ignoreMap":430},[412,451],{},[318,453,455],{"id":454},"customer-app-subdomain-branch-slug","Customer App — Subdomain + Branch Slug",[309,457,458],{},"The customer app requires both a subdomain (organization slug) and a URL path segment (branch slug).",[422,460,463],{"className":461,"code":462,"language":427},[425],"http:\u002F\u002F{slug}.localhost:3002\u002F{branchSlug}\n\n# Example\nhttp:\u002F\u002Fjanesbeautysalon.localhost:3002\u002Fpampanga\n",[350,464,462],{"__ignoreMap":430},[309,466,467],{},[313,468,469],{},"What each part does:",[323,471,472,484],{},[326,473,474],{},[329,475,476,479,481],{},[332,477,478],{},"Part",[332,480,340],{},[332,482,483],{},"Injected as",[342,485,486,502],{},[329,487,488,491,496],{},[347,489,490],{},"Subdomain",[347,492,493],{},[350,494,495],{},"janesbeautysalon",[347,497,498,501],{},[350,499,500],{},"x-tenant-slug"," header",[329,503,504,507,512],{},[347,505,506],{},"Path segment",[347,508,509],{},[350,510,511],{},"\u002Fpampanga",[347,513,514,501],{},[350,515,516],{},"x-branch-slug",[309,518,519,520,523,524,527],{},"The branch slug comes from the ",[350,521,522],{},"[branchSlug]"," dynamic route parameter. A client plugin syncs it to state on every navigation and injects it into all API requests via a ",[350,525,526],{},"$fetch"," interceptor.",[529,530,532],"h3",{"id":531},"default-branch-redirect","Default branch redirect",[309,534,535,536,539,540,543,544,547],{},"Visiting ",[350,537,538],{},"http:\u002F\u002F{slug}.localhost:3002\u002F"," (no branch slug) triggers an automatic redirect. The app calls ",[350,541,542],{},"GET \u002Fapi\u002Fv1\u002Ftenant\u002F{slug}\u002Fdefault-branch"," and navigates to ",[350,545,546],{},"\u002F{defaultBranchSlug}",".",[412,549],{},[318,551,553,556],{"id":552},"localhost-subdomain-support",[350,554,555],{},"*.localhost"," Subdomain Support",[309,558,559,560,562,563,566],{},"Chrome and Edge resolve ",[350,561,555],{}," natively — no ",[350,564,565],{},"\u002Fetc\u002Fhosts"," changes are needed. Just start the app and open the subdomain URL directly.",[309,568,569,572,573,575,576,579],{},[313,570,571],{},"Firefox"," does not resolve ",[350,574,555],{}," by default. Enable it in ",[350,577,578],{},"about:config",":",[581,582,583,590,596,602],"ol",{},[584,585,586,587,589],"li",{},"Open ",[350,588,578],{}," and accept the warning.",[584,591,592,593,547],{},"Search for ",[350,594,595],{},"network.dns.localDomains",[584,597,598,599,547],{},"Set its value to ",[350,600,601],{},"localhost",[584,603,604],{},"Restart Firefox.",[412,606],{},[318,608,610,613],{"id":609},"base_domain-for-local-development",[350,611,612],{},"BASE_DOMAIN"," for Local Development",[309,615,616,617,620,621,624,625,627,628,631,632,635],{},"When running locally, set ",[350,618,619],{},"BASE_DOMAIN=.localhost"," in each app's ",[350,622,623],{},".env"," so that auth cookies are scoped correctly across ",[350,626,555],{}," subdomains. Using ",[350,629,630],{},".booki.app"," locally will prevent cookies set on ",[350,633,634],{},"janesbeautysalon.localhost"," from being sent to other subdomains.",[422,637,641],{"className":638,"code":639,"language":640,"meta":430,"style":430},"language-env shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Local development\nBASE_DOMAIN=.localhost\n\n# Production\nBASE_DOMAIN=.booki.app\n","env",[350,642,643,651,657,664,670],{"__ignoreMap":430},[644,645,648],"span",{"class":646,"line":647},"line",1,[644,649,650],{},"# Local development\n",[644,652,654],{"class":646,"line":653},2,[644,655,656],{},"BASE_DOMAIN=.localhost\n",[644,658,660],{"class":646,"line":659},3,[644,661,663],{"emptyLinePlaceholder":662},true,"\n",[644,665,667],{"class":646,"line":666},4,[644,668,669],{},"# Production\n",[644,671,673],{"class":646,"line":672},5,[644,674,675],{},"BASE_DOMAIN=.booki.app\n",[412,677],{},[318,679,681],{"id":680},"related","Related",[683,684,685,693],"ul",{},[584,686,687,692],{},[688,689,691],"a",{"href":690},".\u002Fguides\u002Fguides-multi-tenancy","Multi-Tenancy & Tenant Slug Resolution"," — how the API resolves slugs to organization IDs",[584,694,695,698],{},[688,696,116],{"href":697},".\u002F1.installation"," — full setup instructions and environment variable reference",[700,701,702],"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);}",{"title":430,"searchDepth":647,"depth":653,"links":704},[705,706,707,708,711,713,715],{"id":320,"depth":653,"text":321},{"id":416,"depth":653,"text":417},{"id":435,"depth":653,"text":436},{"id":454,"depth":653,"text":455,"children":709},[710],{"id":531,"depth":659,"text":532},{"id":552,"depth":653,"text":712},"*.localhost Subdomain Support",{"id":609,"depth":653,"text":714},"BASE_DOMAIN for Local Development",{"id":680,"depth":653,"text":681},"Local dev URL patterns for each Booki app, *.localhost subdomain setup, and branch slug routing.","md",null,{},{"icon":129},{"title":126,"description":716},"_FXoCdrHeoXBjgS_HvwlOP4iUfDaZKiNkcxgDC8uOm8",[724,726],{"title":121,"path":122,"stem":123,"description":725,"icon":124,"children":-1},"Frontend and backend architecture, folder structure, and tech stack for the Booki web applications.",{"title":136,"path":137,"stem":138,"description":727,"icon":57,"children":-1},"Complete REST API reference for Booki. Base path \u002Fapi\u002Fv1 with real payloads, responses, and multi-tenant flows.",1777787844707]