[{"data":1,"prerenderedAt":4279},["ShallowReactive",2],{"navigation_docs":3,"-modules-interface-mobile":587,"-modules-interface-mobile-surround":4274},[4,50,155,441,504],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":49},"Get Started","i-lucide-rocket","\u002Fget-started","1.get-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fget-started\u002Fintroduction","1.get-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fget-started\u002Finstallation","1.get-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project structure","\u002Fget-started\u002Fproject-structure","1.get-started\u002F3.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","\u002Fget-started\u002Fconfiguration","1.get-started\u002F4.configuration","i-lucide-settings",{"title":31,"path":32,"stem":33,"icon":34},"Authentication","\u002Fget-started\u002Fauthentication","1.get-started\u002F5.authentication","i-lucide-lock",{"title":36,"path":37,"stem":38,"icon":39},"Adding modules","\u002Fget-started\u002Fadding-modules","1.get-started\u002F6.adding-modules","i-lucide-puzzle",{"title":41,"path":42,"stem":43,"icon":44},"Database","\u002Fget-started\u002Fdatabase","1.get-started\u002F7.database","i-lucide-database",{"title":46,"path":47,"stem":48,"icon":6},"Deployment","\u002Fget-started\u002Fdeployment","1.get-started\u002F8.deployment",false,{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":49},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[56,90,115,125],{"title":57,"icon":49,"path":58,"stem":59,"children":60,"page":49},"Concepts","\u002Fguide\u002Fconcepts","2.guide\u002F1.concepts",[61,66,71,76,80,85],{"title":62,"path":63,"stem":64,"icon":65},"Architecture","\u002Fguide\u002Fconcepts\u002Farchitecture","2.guide\u002F1.concepts\u002F1.architecture","i-lucide-blocks",{"title":67,"path":68,"stem":69,"icon":70},"Access control","\u002Fguide\u002Fconcepts\u002Fauth-and-scopes","2.guide\u002F1.concepts\u002F2.auth-and-scopes","i-lucide-shield-check",{"title":72,"path":73,"stem":74,"icon":75},"Extension points","\u002Fguide\u002Fconcepts\u002Fextension-points","2.guide\u002F1.concepts\u002F3.extension-points","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":44},"Database extensions","\u002Fguide\u002Fconcepts\u002Fdatabase-extensions","2.guide\u002F1.concepts\u002F4.database-extensions",{"title":81,"path":82,"stem":83,"icon":84},"Identity","\u002Fguide\u002Fconcepts\u002Fidentity","2.guide\u002F1.concepts\u002F5.identity","i-lucide-fingerprint",{"title":86,"path":87,"stem":88,"icon":89},"Glossary","\u002Fguide\u002Fconcepts\u002Fglossary","2.guide\u002F1.concepts\u002F6.glossary","i-lucide-book-a",{"title":91,"icon":49,"path":92,"stem":93,"children":94,"page":49},"UX patterns","\u002Fguide\u002Fux-patterns","2.guide\u002F2.ux-patterns",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Layouts and navigation","\u002Fguide\u002Fux-patterns\u002Flayouts-and-navigation","2.guide\u002F2.ux-patterns\u002F1.layouts-and-navigation","i-lucide-layout-template",{"title":101,"path":102,"stem":103,"icon":104},"Pages","\u002Fguide\u002Fux-patterns\u002Fpages","2.guide\u002F2.ux-patterns\u002F2.pages","i-lucide-table",{"title":106,"path":107,"stem":108,"icon":109},"Forms and actions","\u002Fguide\u002Fux-patterns\u002Fforms-and-actions","2.guide\u002F2.ux-patterns\u002F3.forms-and-actions","i-lucide-square-pen",{"title":111,"path":112,"stem":113,"icon":114},"Text and formatting","\u002Fguide\u002Fux-patterns\u002Ftext-and-formatting","2.guide\u002F2.ux-patterns\u002F4.text-and-formatting","i-lucide-type",{"title":116,"icon":49,"path":117,"stem":118,"children":119,"page":49},"Best practices","\u002Fguide\u002Fbest-practices","2.guide\u002F3.best-practices",[120],{"title":121,"path":122,"stem":123,"icon":124},"HTTP routes","\u002Fguide\u002Fbest-practices\u002Fhttp-routes","2.guide\u002F3.best-practices\u002F1.http-routes","i-lucide-route",{"title":126,"icon":49,"path":127,"stem":128,"children":129,"page":49},"Going further","\u002Fguide\u002Fgoing-further","2.guide\u002F4.going-further",[130,135,140,145,150],{"title":131,"path":132,"stem":133,"icon":134},"Use your own OAuth server","\u002Fguide\u002Fgoing-further\u002Fown-oauth-server","2.guide\u002F4.going-further\u002F1.own-oauth-server","i-lucide-key-round",{"title":136,"path":137,"stem":138,"icon":139},"Create an OAuth application","\u002Fguide\u002Fgoing-further\u002Foauth-application","2.guide\u002F4.going-further\u002F2.oauth-application","i-lucide-app-window",{"title":141,"path":142,"stem":143,"icon":144},"Signing keys","\u002Fguide\u002Fgoing-further\u002Fsigning-keys","2.guide\u002F4.going-further\u002F3.signing-keys","i-lucide-key-square",{"title":146,"path":147,"stem":148,"icon":149},"Stripe setup","\u002Fguide\u002Fgoing-further\u002Fstripe-setup","2.guide\u002F4.going-further\u002F4.stripe-setup","i-lucide-credit-card",{"title":151,"path":152,"stem":153,"icon":154},"Migrate to the permission model","\u002Fguide\u002Fgoing-further\u002Fmigrate-access-control","2.guide\u002F4.going-further\u002F5.migrate-access-control","i-lucide-arrow-right-left",{"title":156,"icon":157,"path":158,"stem":159,"children":160},"Modules","i-lucide-boxes","\u002Fmodules","3.modules",[161,163,244,273,320,375],{"title":156,"path":158,"stem":162},"3.modules\u002Findex",{"title":81,"icon":49,"path":164,"stem":165,"children":166,"page":49},"\u002Fmodules\u002Fidentity","3.modules\u002F1.identity",[167,190,194,198,220,224,240],{"title":168,"path":169,"stem":170,"children":171},"Auth","\u002Fmodules\u002Fidentity\u002Fauth","3.modules\u002F1.identity\u002F1.auth\u002Findex",[172,174,178,182,186],{"title":173,"path":169,"stem":170},"Overview",{"title":175,"path":176,"stem":177},"Server API","\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver","3.modules\u002F1.identity\u002F1.auth\u002F2.server",{"title":179,"path":180,"stem":181},"Reference","\u002Fmodules\u002Fidentity\u002Fauth\u002Freference","3.modules\u002F1.identity\u002F1.auth\u002F3.reference",{"title":183,"path":184,"stem":185},"Client mode","\u002Fmodules\u002Fidentity\u002Fauth\u002Fclient-mode","3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode",{"title":187,"path":188,"stem":189},"OAuth providers","\u002Fmodules\u002Fidentity\u002Fauth\u002Foauth-providers","3.modules\u002F1.identity\u002F1.auth\u002F5.oauth-providers",{"title":191,"path":192,"stem":193},"Users","\u002Fmodules\u002Fidentity\u002Fusers","3.modules\u002F1.identity\u002F2.users",{"title":195,"path":196,"stem":197},"Account","\u002Fmodules\u002Fidentity\u002Faccount","3.modules\u002F1.identity\u002F3.account",{"title":199,"path":200,"stem":201,"children":202},"Authorization","\u002Fmodules\u002Fidentity\u002Fauthorization","3.modules\u002F1.identity\u002F4.authorization\u002Findex",[203,204,208,212,216],{"title":173,"path":200,"stem":201},{"title":205,"path":206,"stem":207},"Roles and requirements","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements","3.modules\u002F1.identity\u002F4.authorization\u002F2.roles-and-requirements",{"title":209,"path":210,"stem":211},"Policies","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fpolicies","3.modules\u002F1.identity\u002F4.authorization\u002F3.policies",{"title":213,"path":214,"stem":215},"Client","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient","3.modules\u002F1.identity\u002F4.authorization\u002F4.client",{"title":217,"path":218,"stem":219},"Admin","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fadmin","3.modules\u002F1.identity\u002F4.authorization\u002F5.admin",{"title":221,"path":222,"stem":223},"Preferences","\u002Fmodules\u002Fidentity\u002Fpreferences","3.modules\u002F1.identity\u002F5.preferences",{"title":225,"path":226,"stem":227,"children":228},"OAuth Server","\u002Fmodules\u002Fidentity\u002Foauth-server","3.modules\u002F1.identity\u002F6.oauth-server\u002Findex",[229,230,233,237],{"title":173,"path":226,"stem":227},{"title":175,"path":231,"stem":232},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fserver","3.modules\u002F1.identity\u002F6.oauth-server\u002F2.server",{"title":234,"path":235,"stem":236},"Hooks","\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fhooks","3.modules\u002F1.identity\u002F6.oauth-server\u002F3.hooks",{"title":179,"path":238,"stem":239},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Froutes-and-clients","3.modules\u002F1.identity\u002F6.oauth-server\u002F4.routes-and-clients",{"title":241,"path":242,"stem":243},"OAuth Resource","\u002Fmodules\u002Fidentity\u002Foauth-resource","3.modules\u002F1.identity\u002F8.oauth-resource",{"title":245,"icon":49,"path":246,"stem":247,"children":248,"page":49},"Commerce","\u002Fmodules\u002Fcommerce","3.modules\u002F2.commerce",[249,253,257],{"title":250,"path":251,"stem":252},"Stripe","\u002Fmodules\u002Fcommerce\u002Fstripe","3.modules\u002F2.commerce\u002F1.stripe",{"title":254,"path":255,"stem":256},"Payments","\u002Fmodules\u002Fcommerce\u002Fpayments","3.modules\u002F2.commerce\u002F2.payments",{"title":258,"path":259,"stem":260,"children":261},"Subscriptions","\u002Fmodules\u002Fcommerce\u002Fsubscriptions","3.modules\u002F2.commerce\u002F3.subscriptions\u002Findex",[262,263,266,270],{"title":173,"path":259,"stem":260},{"title":175,"path":264,"stem":265},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fserver","3.modules\u002F2.commerce\u002F3.subscriptions\u002F2.server",{"title":267,"path":268,"stem":269},"App","\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fapp","3.modules\u002F2.commerce\u002F3.subscriptions\u002F3.app",{"title":179,"path":271,"stem":272},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Freference","3.modules\u002F2.commerce\u002F3.subscriptions\u002F4.reference",{"title":274,"icon":49,"path":275,"stem":276,"children":277,"page":49},"Features","\u002Fmodules\u002Ffeatures","3.modules\u002F3.features",[278,293,312,316],{"title":279,"path":280,"stem":281,"children":282},"Events","\u002Fmodules\u002Ffeatures\u002Fevents","3.modules\u002F3.features\u002F1.events\u002Findex",[283,284,287,290],{"title":173,"path":280,"stem":281},{"title":175,"path":285,"stem":286},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fserver","3.modules\u002F3.features\u002F1.events\u002F2.server",{"title":267,"path":288,"stem":289},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fapp","3.modules\u002F3.features\u002F1.events\u002F3.app",{"title":179,"path":291,"stem":292},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Freference","3.modules\u002F3.features\u002F1.events\u002F4.reference",{"title":294,"path":295,"stem":296,"children":297},"Forms","\u002Fmodules\u002Ffeatures\u002Fforms","3.modules\u002F3.features\u002F2.forms\u002Findex",[298,299,303,306,309],{"title":173,"path":295,"stem":296},{"title":300,"path":301,"stem":302},"Definition","\u002Fmodules\u002Ffeatures\u002Fforms\u002Fdefinition","3.modules\u002F3.features\u002F2.forms\u002F2.definition",{"title":175,"path":304,"stem":305},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver","3.modules\u002F3.features\u002F2.forms\u002F3.server",{"title":267,"path":307,"stem":308},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fapp","3.modules\u002F3.features\u002F2.forms\u002F4.app",{"title":179,"path":310,"stem":311},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Freference","3.modules\u002F3.features\u002F2.forms\u002F5.reference",{"title":313,"path":314,"stem":315},"Cookie Consent","\u002Fmodules\u002Ffeatures\u002Fcookie-consent","3.modules\u002F3.features\u002F3.cookie-consent",{"title":317,"path":318,"stem":319},"MCP","\u002Fmodules\u002Ffeatures\u002Fmcp","3.modules\u002F3.features\u002F4.mcp",{"title":321,"icon":49,"path":322,"stem":323,"children":324,"page":49},"Interface","\u002Fmodules\u002Finterface","3.modules\u002F4.interface",[325,350,353,357,361],{"title":326,"path":327,"stem":328,"children":329},"UI","\u002Fmodules\u002Finterface\u002Fui","3.modules\u002F4.interface\u002F1.ui\u002Findex",[330,331,335,339,343,347],{"title":173,"path":327,"stem":328},{"title":332,"path":333,"stem":334},"Page components","\u002Fmodules\u002Finterface\u002Fui\u002Fpage-components","3.modules\u002F4.interface\u002F1.ui\u002F2.page-components",{"title":336,"path":337,"stem":338},"App shell","\u002Fmodules\u002Finterface\u002Fui\u002Fapp-shell","3.modules\u002F4.interface\u002F1.ui\u002F3.app-shell",{"title":340,"path":341,"stem":342},"Form inputs","\u002Fmodules\u002Finterface\u002Fui\u002Fform-inputs","3.modules\u002F4.interface\u002F1.ui\u002F4.form-inputs",{"title":344,"path":345,"stem":346},"Composables and helpers","\u002Fmodules\u002Finterface\u002Fui\u002Fcomposables","3.modules\u002F4.interface\u002F1.ui\u002F5.composables",{"title":179,"path":348,"stem":349},"\u002Fmodules\u002Finterface\u002Fui\u002Freference","3.modules\u002F4.interface\u002F1.ui\u002F6.reference",{"title":217,"path":351,"stem":352},"\u002Fmodules\u002Finterface\u002Fadmin","3.modules\u002F4.interface\u002F2.admin",{"title":354,"path":355,"stem":356},"Menu","\u002Fmodules\u002Finterface\u002Fmenu","3.modules\u002F4.interface\u002F3.menu",{"title":358,"path":359,"stem":360},"Widget","\u002Fmodules\u002Finterface\u002Fwidget","3.modules\u002F4.interface\u002F4.widget",{"title":362,"path":363,"stem":364,"children":365},"Mobile","\u002Fmodules\u002Finterface\u002Fmobile","3.modules\u002F4.interface\u002F5.mobile\u002Findex",[366,367,371],{"title":173,"path":363,"stem":364},{"title":368,"path":369,"stem":370},"CLI and devices","\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices","3.modules\u002F4.interface\u002F5.mobile\u002F2.cli-and-devices",{"title":372,"path":373,"stem":374},"Splash screen","\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen","3.modules\u002F4.interface\u002F5.mobile\u002F3.splash-screen",{"title":376,"icon":49,"path":377,"stem":378,"children":379,"page":49},"Platform","\u002Fmodules\u002Fplatform","3.modules\u002F5.platform",[380,402,406,423],{"title":381,"path":382,"stem":383,"children":384},"Module Kit","\u002Fmodules\u002Fplatform\u002Fmodule-kit","3.modules\u002F5.platform\u002F1.module-kit\u002Findex",[385,386,390,394,398],{"title":173,"path":382,"stem":383},{"title":387,"path":388,"stem":389},"Server toolkit","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fserver-toolkit","3.modules\u002F5.platform\u002F1.module-kit\u002F2.server-toolkit",{"title":391,"path":392,"stem":393},"Registries and menus","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fregistries-and-menus","3.modules\u002F5.platform\u002F1.module-kit\u002F3.registries-and-menus",{"title":395,"path":396,"stem":397},"Translations","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fi18n","3.modules\u002F5.platform\u002F1.module-kit\u002F4.i18n",{"title":399,"path":400,"stem":401},"Database helpers","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fdatabase","3.modules\u002F5.platform\u002F1.module-kit\u002F5.database",{"title":403,"path":404,"stem":405},"Notify","\u002Fmodules\u002Fplatform\u002Fnotify","3.modules\u002F5.platform\u002F2.notify",{"title":407,"path":408,"stem":409,"children":410},"Email Templates","\u002Fmodules\u002Fplatform\u002Femail-templates","3.modules\u002F5.platform\u002F3.email-templates\u002Findex",[411,412,416,419],{"title":173,"path":408,"stem":409},{"title":413,"path":414,"stem":415},"Email components","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fcomponents","3.modules\u002F5.platform\u002F3.email-templates\u002F2.components",{"title":175,"path":417,"stem":418},"\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fserver","3.modules\u002F5.platform\u002F3.email-templates\u002F3.server",{"title":420,"path":421,"stem":422},"Module emails","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fmodule-emails","3.modules\u002F5.platform\u002F3.email-templates\u002F4.module-emails",{"title":424,"path":425,"stem":426,"children":427},"Base Layer","\u002Fmodules\u002Fplatform\u002Fbase-layer","3.modules\u002F5.platform\u002F4.base-layer\u002Findex",[428,429,433,437],{"title":173,"path":425,"stem":426},{"title":430,"path":431,"stem":432},"Content collections","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcontent-collections","3.modules\u002F5.platform\u002F4.base-layer\u002F2.content-collections",{"title":434,"path":435,"stem":436},"Layouts and routing","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Flayouts-and-routing","3.modules\u002F5.platform\u002F4.base-layer\u002F3.layouts-and-routing",{"title":438,"path":439,"stem":440},"Composables and utils","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcomposables-and-utils","3.modules\u002F5.platform\u002F4.base-layer\u002F4.composables-and-utils",{"title":442,"icon":443,"path":444,"stem":445,"children":446,"page":49},"Examples","i-lucide-code-xml","\u002Fexamples","4.examples",[447,466,476],{"title":448,"icon":49,"path":449,"stem":450,"children":451,"page":49},"Starters","\u002Fexamples\u002Fstarters","4.examples\u002F1.starters",[452,456,461],{"title":453,"path":454,"stem":455,"icon":6},"Workspace starter","\u002Fexamples\u002Fstarters\u002Fworkspace","4.examples\u002F1.starters\u002F1.workspace",{"title":457,"path":458,"stem":459,"icon":460},"Mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile","4.examples\u002F1.starters\u002F2.mobile","i-lucide-smartphone",{"title":462,"path":463,"stem":464,"icon":465},"Standalone mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile-standalone","4.examples\u002F1.starters\u002F3.mobile-standalone","i-lucide-tablet-smartphone",{"title":467,"icon":49,"path":468,"stem":469,"children":470,"page":49},"Apps","\u002Fexamples\u002Fapps","4.examples\u002F2.apps",[471],{"title":472,"path":473,"stem":474,"icon":475},"Frigear website app","\u002Fexamples\u002Fapps\u002Ffrigear-nu-website","4.examples\u002F2.apps\u002F1.frigear-nu-website","i-lucide-layout-dashboard",{"title":477,"icon":49,"path":478,"stem":479,"children":480,"page":49},"Tasks","\u002Fexamples\u002Ftasks","4.examples\u002F3.tasks",[481,485,489,494,499],{"title":482,"path":483,"stem":484,"icon":70},"Protect a route","\u002Fexamples\u002Ftasks\u002Fprotect-a-route","4.examples\u002F3.tasks\u002F1.protect-a-route",{"title":486,"path":487,"stem":488,"icon":475},"Add an admin page","\u002Fexamples\u002Ftasks\u002Fadd-an-admin-page","4.examples\u002F3.tasks\u002F2.add-an-admin-page",{"title":490,"path":491,"stem":492,"icon":493},"Sell event tickets","\u002Fexamples\u002Ftasks\u002Fsell-event-tickets","4.examples\u002F3.tasks\u002F3.sell-event-tickets","i-lucide-ticket",{"title":495,"path":496,"stem":497,"icon":498},"Build a form","\u002Fexamples\u002Ftasks\u002Fbuild-a-form","4.examples\u002F3.tasks\u002F4.build-a-form","i-lucide-clipboard-list",{"title":500,"path":501,"stem":502,"icon":503},"Send an email","\u002Fexamples\u002Ftasks\u002Fsend-an-email","4.examples\u002F3.tasks\u002F5.send-an-email","i-lucide-mail",{"title":505,"icon":506,"path":507,"stem":508,"children":509,"page":49},"Contribute","i-lucide-git-pull-request","\u002Fcontribute","5.contribute",[510,513,518,544,549,552,556,571],{"title":173,"path":511,"stem":512,"icon":506},"\u002Fcontribute\u002Foverview","5.contribute\u002F1.overview",{"title":514,"path":515,"stem":516,"icon":517},"Local development","\u002Fcontribute\u002Flocal-development","5.contribute\u002F2.local-development","i-lucide-terminal",{"title":519,"icon":49,"path":520,"stem":521,"children":522,"page":49},"Writing a module","\u002Fcontribute\u002Fwriting-a-module","5.contribute\u002F3.writing-a-module",[523,527,532,536,541],{"title":524,"path":525,"stem":526,"icon":39},"Scaffold a module","\u002Fcontribute\u002Fwriting-a-module\u002Fscaffold","5.contribute\u002F3.writing-a-module\u002F1.scaffold",{"title":528,"path":529,"stem":530,"icon":531},"Setup checklist","\u002Fcontribute\u002Fwriting-a-module\u002Fsetup-checklist","5.contribute\u002F3.writing-a-module\u002F2.setup-checklist","i-lucide-list-checks",{"title":533,"path":534,"stem":535,"icon":44},"Database tables","\u002Fcontribute\u002Fwriting-a-module\u002Fdatabase-tables","5.contribute\u002F3.writing-a-module\u002F3.database-tables",{"title":537,"path":538,"stem":539,"icon":540},"Testing","\u002Fcontribute\u002Fwriting-a-module\u002Ftesting","5.contribute\u002F3.writing-a-module\u002F4.testing","i-lucide-flask-conical",{"title":67,"path":542,"stem":543,"icon":70},"\u002Fcontribute\u002Fwriting-a-module\u002Faccess-control","5.contribute\u002F3.writing-a-module\u002F5.access-control",{"title":545,"path":546,"stem":547,"icon":548},"Publishing","\u002Fcontribute\u002Fpublishing","5.contribute\u002F4.publishing","i-lucide-package-check",{"title":448,"path":550,"stem":551,"icon":6},"\u002Fcontribute\u002Fstarters","5.contribute\u002F5.starters",{"title":553,"path":554,"stem":555,"icon":52},"Documentation","\u002Fcontribute\u002Fdocumentation","5.contribute\u002F6.documentation",{"title":557,"icon":49,"path":558,"stem":559,"children":560,"page":49},"Tooling","\u002Fcontribute\u002Ftooling","5.contribute\u002F7.tooling",[561,566],{"title":562,"path":563,"stem":564,"icon":565},"CLI","\u002Fcontribute\u002Ftooling\u002Fcli","5.contribute\u002F7.tooling\u002F1.cli","i-lucide-square-terminal",{"title":567,"path":568,"stem":569,"icon":570},"ESLint config","\u002Fcontribute\u002Ftooling\u002Feslint-config","5.contribute\u002F7.tooling\u002F2.eslint-config","i-lucide-spell-check",{"title":572,"icon":49,"path":573,"stem":574,"children":575},"Decisions","\u002Fcontribute\u002Fdecisions","5.contribute\u002F8.decisions\u002Findex",[576,578,583],{"title":572,"path":573,"stem":574,"icon":577},"i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":582},"Session lifetimes per OAuth client","\u002Fcontribute\u002Fdecisions\u002Foauth-token-lifetimes","5.contribute\u002F8.decisions\u002F1.oauth-token-lifetimes","i-lucide-timer",{"title":584,"path":585,"stem":586,"icon":70},"One permission model","\u002Fcontribute\u002Fdecisions\u002Fpermission-model","5.contribute\u002F8.decisions\u002F2.permission-model",{"id":588,"title":362,"body":589,"description":4267,"extension":4268,"links":4269,"meta":4270,"navigation":4271,"path":363,"seo":4272,"stem":364,"__hash__":4273},"docs\u002F3.modules\u002F4.interface\u002F5.mobile\u002Findex.md",{"type":590,"value":591,"toc":4244},"minimark",[592,600,625,630,702,706,771,775,1695,1706,1710,1716,2213,2231,2238,2249,2260,2271,2274,2277,2280,2304,2307,2339,2342,2346,2355,2382,2389,2513,2523,2525,2528,2729,2736,2847,2879,2901,2904,2913,3035,3040,3057,3171,3295,3318,3441,3445,3448,3683,3695,3725,3729,3746,3749,3752,3782,3793,3970,3977,3980,3985,4071,4074,4082,4129,4157,4167,4171,4213,4217,4240],[593,594,595,596,599],"p",{},"Mobile turns a Nuxt app into an iOS and Android app. You list your tabs once, and the app gets a native tab bar on\niOS, a web tab bar elsewhere, page titles, safe areas, haptics and deep links. Use it for a Capacitor app that ships\nas a static build, with no server of its own. To start a new app, copy the\n",[597,598,457],"a",{"href":458}," instead of setting this up by hand.",[593,601,602,603,607,608,616,617,620,621,624],{},"The package is ",[604,605,606],"code",{},"@frigear-nu\u002Fmobile",". It builds on ",[597,609,613],{"href":610,"rel":611},"https:\u002F\u002Fgithub.com\u002Fhareland\u002Fnuxt-capacitor",[612],"nofollow",[604,614,615],{},"nuxt-capacitor",",\nwhich writes ",[604,618,619],{},"capacitor.config.json"," from your Nuxt config. Users sign in through\n",[597,622,623],{"href":184},"Auth in client mode",".",[626,627,629],"h2",{"id":628},"what-you-get","What you get",[631,632,633,641,651,667,678,684,693],"ul",{},[634,635,636,640],"li",{},[637,638,639],"strong",{},"Tabs"," (on by default): one tab list for the native iOS tab bar, the web tab bar and the page titles. Other modules\ncan add tabs.",[634,642,643,646,647,650],{},[637,644,645],{},"Layout"," (on by default): the ",[604,648,649],{},"mobile"," layout, with a header, the page and a tab bar.",[634,652,653,655,656,659,660,663,664,624],{},[637,654,344],{}," (on by default): ",[604,657,658],{},"useCapacitor()",", ",[604,661,662],{},"useNative()"," for haptics, sheets, dialogs and\nsharing, and ",[604,665,666],{},"useMobileChrome()",[634,668,669,671,672,675,676,624],{},[637,670,372],{}," (opt-in, ",[604,673,674],{},"splashScreen: true","): from the native launch image to the first page. Replace it with\nyour own component. See ",[597,677,372],{"href":373},[634,679,680,683],{},[637,681,682],{},"Native behaviour"," (on by default): safe areas, the iOS type scale, the Android back button and deep links.",[634,685,686,689,690,624],{},[637,687,688],{},"Sign-in"," (opt-in): through Auth in client mode. See ",[597,691,688],{"href":692},"#sign-in",[634,694,695,697,698,701],{},[637,696,562],{},": ",[604,699,700],{},"frigear-mobile"," adds the iOS and Android projects and checks your plugins.",[703,704],"module-runtime",{":client":705,":mobile":705},"true",[707,708,709,733,746],"note",{},[593,710,711,714,715,659,720,722,723,728,729,732],{},[637,712,713],{},"Installed for you:"," ",[597,716,717],{"href":382},[604,718,719],{},"@frigear-nu\u002Fmodule-kit",[604,721,615],{},", and\n",[597,724,725],{"href":169},[604,726,727],{},"@frigear-nu\u002Fauth"," when ",[604,730,731],{},"authentication"," is configured.",[593,734,735,714,738,741,742,745],{},[637,736,737],{},"You add:",[604,739,740],{},"@nuxt\u002Fui"," (4 or later), ",[604,743,744],{},"@capacitor\u002Fcore"," and the Capacitor plugins your features use.",[593,747,748,714,751,756,757,760,761,766,767,770],{},[637,749,750],{},"Optional:",[597,752,753],{"href":327},[604,754,755],{},"@frigear-nu\u002Fui"," (its ",[604,758,759],{},"useConfirmDialog"," is the browser fallback for native\ndialogs) and ",[597,762,763],{"href":355},[604,764,765],{},"@frigear-nu\u002Fmenu"," (the ",[604,768,769],{},"mobile.tabs"," menu adds tabs).",[626,772,774],{"id":773},"quick-setup","Quick setup",[776,777,778,783,794,914,918,1497,1517,1521,1619,1623,1689],"steps",{},[779,780,782],"h3",{"id":781},"install-mobile-and-capacitor","Install Mobile and Capacitor",[784,785,786,787,793],"warning",{},"Install the plugins in the app itself, not only in a package it depends on. Capacitor links the native code of the\napp's own dependencies only. ",[597,788,790],{"href":789},"\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices#cli",[604,791,792],{},"frigear-mobile doctor"," lists the\nmissing ones.",[795,796,801],"pre",{"className":797,"code":798,"language":799,"meta":800,"style":800},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fmobile @nuxt\u002Fui @capacitor\u002Fcore @capacitor\u002Fapp @capacitor\u002Fios\npnpm add -D @capacitor\u002Fcli\n# optional, for the features that use them:\npnpm add @capgo\u002Fcapacitor-native-navigation @capacitor\u002Fhaptics @capacitor\u002Faction-sheet @capacitor\u002Fdialog \\\n  @capacitor\u002Fshare @capacitor\u002Fstatus-bar @capacitor\u002Fkeyboard @capacitor\u002Fsplash-screen\n# with sign-in, and guards:\npnpm add @frigear-nu\u002Fauthorization @capacitor\u002Fbrowser @capacitor\u002Fpreferences @aparajita\u002Fcapacitor-secure-storage\n","bash","",[604,802,803,831,844,851,874,889,895],{"__ignoreMap":800},[804,805,808,812,816,819,822,825,828],"span",{"class":806,"line":807},"line",1,[804,809,811],{"class":810},"sBMFI","pnpm",[804,813,815],{"class":814},"sfazB"," add",[804,817,818],{"class":814}," @frigear-nu\u002Fmobile",[804,820,821],{"class":814}," @nuxt\u002Fui",[804,823,824],{"class":814}," @capacitor\u002Fcore",[804,826,827],{"class":814}," @capacitor\u002Fapp",[804,829,830],{"class":814}," @capacitor\u002Fios\n",[804,832,834,836,838,841],{"class":806,"line":833},2,[804,835,811],{"class":810},[804,837,815],{"class":814},[804,839,840],{"class":814}," -D",[804,842,843],{"class":814}," @capacitor\u002Fcli\n",[804,845,847],{"class":806,"line":846},3,[804,848,850],{"class":849},"sHwdD","# optional, for the features that use them:\n",[804,852,854,856,858,861,864,867,870],{"class":806,"line":853},4,[804,855,811],{"class":810},[804,857,815],{"class":814},[804,859,860],{"class":814}," @capgo\u002Fcapacitor-native-navigation",[804,862,863],{"class":814}," @capacitor\u002Fhaptics",[804,865,866],{"class":814}," @capacitor\u002Faction-sheet",[804,868,869],{"class":814}," @capacitor\u002Fdialog",[804,871,873],{"class":872},"sTEyZ"," \\\n",[804,875,877,880,883,886],{"class":806,"line":876},5,[804,878,879],{"class":814},"  @capacitor\u002Fshare",[804,881,882],{"class":814}," @capacitor\u002Fstatus-bar",[804,884,885],{"class":814}," @capacitor\u002Fkeyboard",[804,887,888],{"class":814}," @capacitor\u002Fsplash-screen\n",[804,890,892],{"class":806,"line":891},6,[804,893,894],{"class":849},"# with sign-in, and guards:\n",[804,896,898,900,902,905,908,911],{"class":806,"line":897},7,[804,899,811],{"class":810},[804,901,815],{"class":814},[804,903,904],{"class":814}," @frigear-nu\u002Fauthorization",[804,906,907],{"class":814}," @capacitor\u002Fbrowser",[804,909,910],{"class":814}," @capacitor\u002Fpreferences",[804,912,913],{"class":814}," @aparajita\u002Fcapacitor-secure-storage\n",[779,915,917],{"id":916},"add-it-to-nuxtconfigts","Add it to nuxt.config.ts",[795,919,924],{"className":920,"code":921,"filename":922,"language":923,"meta":800,"style":800},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@nuxt\u002Fui', '@frigear-nu\u002Fmobile', '@frigear-nu\u002Fauthorization'],\n  css: ['~\u002Fassets\u002Fcss\u002Fmain.css'],\n  mobile: {\n    appId: 'nu.frigear.bills', \u002F\u002F capacitor appId and, in lowercase, the OAuth redirect scheme\n    appName: 'Bills',\n    tabs: [\n      { id: 'home', to: '\u002F', label: 'Upcoming', icon: 'i-lucide-calendar-clock', sfSymbol: 'calendar.badge.clock' },\n      { id: 'bills', to: '\u002Fbills', label: 'Bills', icon: 'i-lucide-receipt-text', sfSymbol: 'list.bullet.rectangle' },\n      { id: 'account', to: '\u002Faccount', label: 'Account', icon: 'i-lucide-circle-user-round', sfSymbol: 'person.crop.circle', requiresAuth: true },\n    ],\n  },\n  \u002F\u002F Optional sign-in, in client mode. See Sign-in below.\n  authentication: {\n    mode: 'client',\n    client: { issuer: 'https:\u002F\u002Ffrigear.nu', clientId: 'bills', scopes: ['openid', 'profile', 'offline_access'] },\n  },\n  \u002F\u002F Guards are the app's (@frigear-nu\u002Fauthorization): signed in everywhere. The login and callback pages stay open.\n  authorization: { redirectTo: '\u002Flogin' },\n  routeRules: {\n    '\u002F**': { authenticated: true },\n  },\n})\n","nuxt.config.ts","ts",[604,925,926,946,990,1010,1020,1039,1055,1065,1142,1211,1291,1299,1305,1311,1321,1338,1414,1419,1425,1449,1459,1483,1488],{"__ignoreMap":800},[804,927,928,932,935,939,942],{"class":806,"line":807},[804,929,931],{"class":930},"s7zQu","export",[804,933,934],{"class":930}," default",[804,936,938],{"class":937},"s2Zo4"," defineNuxtConfig",[804,940,941],{"class":872},"(",[804,943,945],{"class":944},"sMK4o","{\n",[804,947,948,952,955,958,961,963,965,968,971,973,975,977,979,982,984,987],{"class":806,"line":833},[804,949,951],{"class":950},"swJcz","  modules",[804,953,954],{"class":944},":",[804,956,957],{"class":872}," [",[804,959,960],{"class":944},"'",[804,962,740],{"class":814},[804,964,960],{"class":944},[804,966,967],{"class":944},",",[804,969,970],{"class":944}," '",[804,972,606],{"class":814},[804,974,960],{"class":944},[804,976,967],{"class":944},[804,978,970],{"class":944},[804,980,981],{"class":814},"@frigear-nu\u002Fauthorization",[804,983,960],{"class":944},[804,985,986],{"class":872},"]",[804,988,989],{"class":944},",\n",[804,991,992,995,997,999,1001,1004,1006,1008],{"class":806,"line":846},[804,993,994],{"class":950},"  css",[804,996,954],{"class":944},[804,998,957],{"class":872},[804,1000,960],{"class":944},[804,1002,1003],{"class":814},"~\u002Fassets\u002Fcss\u002Fmain.css",[804,1005,960],{"class":944},[804,1007,986],{"class":872},[804,1009,989],{"class":944},[804,1011,1012,1015,1017],{"class":806,"line":853},[804,1013,1014],{"class":950},"  mobile",[804,1016,954],{"class":944},[804,1018,1019],{"class":944}," {\n",[804,1021,1022,1025,1027,1029,1032,1034,1036],{"class":806,"line":876},[804,1023,1024],{"class":950},"    appId",[804,1026,954],{"class":944},[804,1028,970],{"class":944},[804,1030,1031],{"class":814},"nu.frigear.bills",[804,1033,960],{"class":944},[804,1035,967],{"class":944},[804,1037,1038],{"class":849}," \u002F\u002F capacitor appId and, in lowercase, the OAuth redirect scheme\n",[804,1040,1041,1044,1046,1048,1051,1053],{"class":806,"line":891},[804,1042,1043],{"class":950},"    appName",[804,1045,954],{"class":944},[804,1047,970],{"class":944},[804,1049,1050],{"class":814},"Bills",[804,1052,960],{"class":944},[804,1054,989],{"class":944},[804,1056,1057,1060,1062],{"class":806,"line":897},[804,1058,1059],{"class":950},"    tabs",[804,1061,954],{"class":944},[804,1063,1064],{"class":872}," [\n",[804,1066,1068,1071,1074,1076,1078,1081,1083,1085,1088,1090,1092,1095,1097,1099,1102,1104,1106,1109,1111,1113,1116,1118,1120,1123,1125,1127,1130,1132,1134,1137,1139],{"class":806,"line":1067},8,[804,1069,1070],{"class":944},"      {",[804,1072,1073],{"class":950}," id",[804,1075,954],{"class":944},[804,1077,970],{"class":944},[804,1079,1080],{"class":814},"home",[804,1082,960],{"class":944},[804,1084,967],{"class":944},[804,1086,1087],{"class":950}," to",[804,1089,954],{"class":944},[804,1091,970],{"class":944},[804,1093,1094],{"class":814},"\u002F",[804,1096,960],{"class":944},[804,1098,967],{"class":944},[804,1100,1101],{"class":950}," label",[804,1103,954],{"class":944},[804,1105,970],{"class":944},[804,1107,1108],{"class":814},"Upcoming",[804,1110,960],{"class":944},[804,1112,967],{"class":944},[804,1114,1115],{"class":950}," icon",[804,1117,954],{"class":944},[804,1119,970],{"class":944},[804,1121,1122],{"class":814},"i-lucide-calendar-clock",[804,1124,960],{"class":944},[804,1126,967],{"class":944},[804,1128,1129],{"class":950}," sfSymbol",[804,1131,954],{"class":944},[804,1133,970],{"class":944},[804,1135,1136],{"class":814},"calendar.badge.clock",[804,1138,960],{"class":944},[804,1140,1141],{"class":944}," },\n",[804,1143,1145,1147,1149,1151,1153,1156,1158,1160,1162,1164,1166,1169,1171,1173,1175,1177,1179,1181,1183,1185,1187,1189,1191,1194,1196,1198,1200,1202,1204,1207,1209],{"class":806,"line":1144},9,[804,1146,1070],{"class":944},[804,1148,1073],{"class":950},[804,1150,954],{"class":944},[804,1152,970],{"class":944},[804,1154,1155],{"class":814},"bills",[804,1157,960],{"class":944},[804,1159,967],{"class":944},[804,1161,1087],{"class":950},[804,1163,954],{"class":944},[804,1165,970],{"class":944},[804,1167,1168],{"class":814},"\u002Fbills",[804,1170,960],{"class":944},[804,1172,967],{"class":944},[804,1174,1101],{"class":950},[804,1176,954],{"class":944},[804,1178,970],{"class":944},[804,1180,1050],{"class":814},[804,1182,960],{"class":944},[804,1184,967],{"class":944},[804,1186,1115],{"class":950},[804,1188,954],{"class":944},[804,1190,970],{"class":944},[804,1192,1193],{"class":814},"i-lucide-receipt-text",[804,1195,960],{"class":944},[804,1197,967],{"class":944},[804,1199,1129],{"class":950},[804,1201,954],{"class":944},[804,1203,970],{"class":944},[804,1205,1206],{"class":814},"list.bullet.rectangle",[804,1208,960],{"class":944},[804,1210,1141],{"class":944},[804,1212,1214,1216,1218,1220,1222,1225,1227,1229,1231,1233,1235,1238,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1260,1263,1265,1267,1269,1271,1273,1276,1278,1280,1283,1285,1289],{"class":806,"line":1213},10,[804,1215,1070],{"class":944},[804,1217,1073],{"class":950},[804,1219,954],{"class":944},[804,1221,970],{"class":944},[804,1223,1224],{"class":814},"account",[804,1226,960],{"class":944},[804,1228,967],{"class":944},[804,1230,1087],{"class":950},[804,1232,954],{"class":944},[804,1234,970],{"class":944},[804,1236,1237],{"class":814},"\u002Faccount",[804,1239,960],{"class":944},[804,1241,967],{"class":944},[804,1243,1101],{"class":950},[804,1245,954],{"class":944},[804,1247,970],{"class":944},[804,1249,195],{"class":814},[804,1251,960],{"class":944},[804,1253,967],{"class":944},[804,1255,1115],{"class":950},[804,1257,954],{"class":944},[804,1259,970],{"class":944},[804,1261,1262],{"class":814},"i-lucide-circle-user-round",[804,1264,960],{"class":944},[804,1266,967],{"class":944},[804,1268,1129],{"class":950},[804,1270,954],{"class":944},[804,1272,970],{"class":944},[804,1274,1275],{"class":814},"person.crop.circle",[804,1277,960],{"class":944},[804,1279,967],{"class":944},[804,1281,1282],{"class":950}," requiresAuth",[804,1284,954],{"class":944},[804,1286,1288],{"class":1287},"sfNiH"," true",[804,1290,1141],{"class":944},[804,1292,1294,1297],{"class":806,"line":1293},11,[804,1295,1296],{"class":872},"    ]",[804,1298,989],{"class":944},[804,1300,1302],{"class":806,"line":1301},12,[804,1303,1304],{"class":944},"  },\n",[804,1306,1308],{"class":806,"line":1307},13,[804,1309,1310],{"class":849},"  \u002F\u002F Optional sign-in, in client mode. See Sign-in below.\n",[804,1312,1314,1317,1319],{"class":806,"line":1313},14,[804,1315,1316],{"class":950},"  authentication",[804,1318,954],{"class":944},[804,1320,1019],{"class":944},[804,1322,1324,1327,1329,1331,1334,1336],{"class":806,"line":1323},15,[804,1325,1326],{"class":950},"    mode",[804,1328,954],{"class":944},[804,1330,970],{"class":944},[804,1332,1333],{"class":814},"client",[804,1335,960],{"class":944},[804,1337,989],{"class":944},[804,1339,1341,1344,1346,1349,1352,1354,1356,1359,1361,1363,1366,1368,1370,1372,1374,1376,1379,1381,1383,1385,1388,1390,1392,1394,1397,1399,1401,1403,1406,1408,1411],{"class":806,"line":1340},16,[804,1342,1343],{"class":950},"    client",[804,1345,954],{"class":944},[804,1347,1348],{"class":944}," {",[804,1350,1351],{"class":950}," issuer",[804,1353,954],{"class":944},[804,1355,970],{"class":944},[804,1357,1358],{"class":814},"https:\u002F\u002Ffrigear.nu",[804,1360,960],{"class":944},[804,1362,967],{"class":944},[804,1364,1365],{"class":950}," clientId",[804,1367,954],{"class":944},[804,1369,970],{"class":944},[804,1371,1155],{"class":814},[804,1373,960],{"class":944},[804,1375,967],{"class":944},[804,1377,1378],{"class":950}," scopes",[804,1380,954],{"class":944},[804,1382,957],{"class":872},[804,1384,960],{"class":944},[804,1386,1387],{"class":814},"openid",[804,1389,960],{"class":944},[804,1391,967],{"class":944},[804,1393,970],{"class":944},[804,1395,1396],{"class":814},"profile",[804,1398,960],{"class":944},[804,1400,967],{"class":944},[804,1402,970],{"class":944},[804,1404,1405],{"class":814},"offline_access",[804,1407,960],{"class":944},[804,1409,1410],{"class":872},"] ",[804,1412,1413],{"class":944},"},\n",[804,1415,1417],{"class":806,"line":1416},17,[804,1418,1304],{"class":944},[804,1420,1422],{"class":806,"line":1421},18,[804,1423,1424],{"class":849},"  \u002F\u002F Guards are the app's (@frigear-nu\u002Fauthorization): signed in everywhere. The login and callback pages stay open.\n",[804,1426,1428,1431,1433,1435,1438,1440,1442,1445,1447],{"class":806,"line":1427},19,[804,1429,1430],{"class":950},"  authorization",[804,1432,954],{"class":944},[804,1434,1348],{"class":944},[804,1436,1437],{"class":950}," redirectTo",[804,1439,954],{"class":944},[804,1441,970],{"class":944},[804,1443,1444],{"class":814},"\u002Flogin",[804,1446,960],{"class":944},[804,1448,1141],{"class":944},[804,1450,1452,1455,1457],{"class":806,"line":1451},20,[804,1453,1454],{"class":950},"  routeRules",[804,1456,954],{"class":944},[804,1458,1019],{"class":944},[804,1460,1462,1465,1468,1470,1472,1474,1477,1479,1481],{"class":806,"line":1461},21,[804,1463,1464],{"class":944},"    '",[804,1466,1467],{"class":950},"\u002F**",[804,1469,960],{"class":944},[804,1471,954],{"class":944},[804,1473,1348],{"class":944},[804,1475,1476],{"class":950}," authenticated",[804,1478,954],{"class":944},[804,1480,1288],{"class":1287},[804,1482,1141],{"class":944},[804,1484,1486],{"class":806,"line":1485},22,[804,1487,1304],{"class":944},[804,1489,1491,1494],{"class":806,"line":1490},23,[804,1492,1493],{"class":944},"}",[804,1495,1496],{"class":872},")\n",[593,1498,1499,1500,1502,1503,659,1506,1509,1510,1513,1514,624],{},"The module sets these ",[604,1501,615],{}," defaults, and yours win: ",[604,1504,1505],{},"capacitor.autoSync: false",[604,1507,1508],{},"capacitor.config.appId","\nand ",[604,1511,1512],{},"appName",", and the Keyboard plugin's ",[604,1515,1516],{},"resize: 'native'",[779,1518,1520],{"id":1519},"wrap-the-app","Wrap the app",[795,1522,1527],{"className":1523,"code":1524,"filename":1525,"language":1526,"meta":800,"style":800},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Ctemplate>\n  \u003CUApp :toaster=\"useMobileToaster()\">\n    \u003CNuxtLayout>\n      \u003CNuxtPage \u002F>\n    \u003C\u002FNuxtLayout>\n  \u003C\u002FUApp>\n\u003C\u002Ftemplate>\n","app\u002Fapp.vue","vue",[604,1528,1529,1540,1571,1581,1592,1601,1610],{"__ignoreMap":800},[804,1530,1531,1534,1537],{"class":806,"line":807},[804,1532,1533],{"class":944},"\u003C",[804,1535,1536],{"class":950},"template",[804,1538,1539],{"class":944},">\n",[804,1541,1542,1545,1548,1551,1555,1558,1561,1564,1567,1569],{"class":806,"line":833},[804,1543,1544],{"class":944},"  \u003C",[804,1546,1547],{"class":950},"UApp",[804,1549,1550],{"class":944}," :",[804,1552,1554],{"class":1553},"spNyl","toaster",[804,1556,1557],{"class":944},"=",[804,1559,1560],{"class":944},"\"",[804,1562,1563],{"class":937},"useMobileToaster",[804,1565,1566],{"class":944},"()",[804,1568,1560],{"class":944},[804,1570,1539],{"class":944},[804,1572,1573,1576,1579],{"class":806,"line":846},[804,1574,1575],{"class":944},"    \u003C",[804,1577,1578],{"class":950},"NuxtLayout",[804,1580,1539],{"class":944},[804,1582,1583,1586,1589],{"class":806,"line":853},[804,1584,1585],{"class":944},"      \u003C",[804,1587,1588],{"class":950},"NuxtPage",[804,1590,1591],{"class":944}," \u002F>\n",[804,1593,1594,1597,1599],{"class":806,"line":876},[804,1595,1596],{"class":944},"    \u003C\u002F",[804,1598,1578],{"class":950},[804,1600,1539],{"class":944},[804,1602,1603,1606,1608],{"class":806,"line":891},[804,1604,1605],{"class":944},"  \u003C\u002F",[804,1607,1547],{"class":950},[804,1609,1539],{"class":944},[804,1611,1612,1615,1617],{"class":806,"line":897},[804,1613,1614],{"class":944},"\u003C\u002F",[804,1616,1536],{"class":950},[804,1618,1539],{"class":944},[779,1620,1622],{"id":1621},"build-and-run-it","Build and run it",[795,1624,1626],{"className":797,"code":1625,"language":799,"meta":800,"style":800},"nuxt generate                  # the static SPA in .output\u002Fpublic\nnpx frigear-mobile native      # npx cap add ios \u002F android, URL schemes in Info.plist \u002F AndroidManifest.xml\nnpx frigear-mobile doctor      # lists missing plugins and URL schemes\nnpx cap sync && npx cap run ios\n",[604,1627,1628,1639,1653,1665],{"__ignoreMap":800},[804,1629,1630,1633,1636],{"class":806,"line":807},[804,1631,1632],{"class":810},"nuxt",[804,1634,1635],{"class":814}," generate",[804,1637,1638],{"class":849},"                  # the static SPA in .output\u002Fpublic\n",[804,1640,1641,1644,1647,1650],{"class":806,"line":833},[804,1642,1643],{"class":810},"npx",[804,1645,1646],{"class":814}," frigear-mobile",[804,1648,1649],{"class":814}," native",[804,1651,1652],{"class":849},"      # npx cap add ios \u002F android, URL schemes in Info.plist \u002F AndroidManifest.xml\n",[804,1654,1655,1657,1659,1662],{"class":806,"line":846},[804,1656,1643],{"class":810},[804,1658,1646],{"class":814},[804,1660,1661],{"class":814}," doctor",[804,1663,1664],{"class":849},"      # lists missing plugins and URL schemes\n",[804,1666,1667,1669,1672,1675,1678,1681,1683,1686],{"class":806,"line":853},[804,1668,1643],{"class":810},[804,1670,1671],{"class":814}," cap",[804,1673,1674],{"class":814}," sync",[804,1676,1677],{"class":944}," &&",[804,1679,1680],{"class":810}," npx",[804,1682,1671],{"class":814},[804,1684,1685],{"class":814}," run",[804,1687,1688],{"class":814}," ios\n",[593,1690,1691,1692,624],{},"A script for the loop: ",[604,1693,1694],{},"\"ios:run\": \"frigear-mobile native --if-missing && nuxt generate && cap sync ios && cap run ios\"",[1696,1697,1700,714,1703,1705],"callout",{"color":1698,"icon":1699},"success","i-lucide-check",[637,1701,1702],{},"What you should see:",[604,1704,792],{}," reports no missing plugins, and the app opens in the iOS Simulator.",[626,1707,1709],{"id":1708},"options","Options",[593,1711,1712,1713,1715],{},"Options go under the ",[604,1714,649],{}," key.",[1717,1718,1719,1738],"table",{},[1720,1721,1722],"thead",{},[1723,1724,1725,1729,1732,1735],"tr",{},[1726,1727,1728],"th",{},"Option",[1726,1730,1731],{},"Type",[1726,1733,1734],{},"Default",[1726,1736,1737],{},"Purpose",[1739,1740,1741,1761,1784,1807,1829,1851,1875,1895,1917,1940,1958,1976,1998,2020,2038,2060,2081,2106,2128,2151,2174,2195],"tbody",{},[1723,1742,1743,1749,1754,1758],{},[1744,1745,1746],"td",{},[604,1747,1748],{},"appId",[1744,1750,1751],{},[604,1752,1753],{},"string",[1744,1755,1756],{},[604,1757,1508],{},[1744,1759,1760],{},"The reverse-DNS app id. It also gives the redirect and deep-link scheme.",[1723,1762,1763,1767,1771,1779],{},[1744,1764,1765],{},[604,1766,1512],{},[1744,1768,1769],{},[604,1770,1753],{},[1744,1772,1773,1776,1777],{},[604,1774,1775],{},"capacitor.config.appName",", else ",[604,1778,1748],{},[1744,1780,1781,1783],{},[604,1782,1775],{}," and the fallback page title.",[1723,1785,1786,1791,1796,1801],{},[1744,1787,1788],{},[604,1789,1790],{},"tabs",[1744,1792,1793],{},[604,1794,1795],{},"MobileTabDefinition[]",[1744,1797,1798],{},[604,1799,1800],{},"[]",[1744,1802,1803,1804,624],{},"See ",[597,1805,639],{"href":1806},"#tabs",[1723,1808,1809,1814,1819,1822],{},[1744,1810,1811],{},[604,1812,1813],{},"auth",[1744,1815,1816],{},[604,1817,1818],{},"boolean",[1744,1820,1821],{},"on when Auth runs in client mode",[1744,1823,1824,1825,1828],{},"Tabs with ",[604,1826,1827],{},"requiresAuth"," show only while signed in.",[1723,1830,1831,1836,1840,1844],{},[1744,1832,1833],{},[604,1834,1835],{},"spa",[1744,1837,1838],{},[604,1839,1818],{},[1744,1841,1842],{},[604,1843,705],{},[1744,1845,1846,1847,1850],{},"Sets ",[604,1848,1849],{},"ssr: false",", because Capacitor serves a static build.",[1723,1852,1853,1858,1863,1868],{},[1744,1854,1855],{},[604,1856,1857],{},"layout",[1744,1859,1860],{},[604,1861,1862],{},"string | false",[1744,1864,1865],{},[604,1866,1867],{},"'mobile'",[1744,1869,1870,1871,1874],{},"The name of the shell layout. ",[604,1872,1873],{},"false"," for none.",[1723,1876,1877,1882,1887,1892],{},[1744,1878,1879],{},[604,1880,1881],{},"nativeChrome",[1744,1883,1884],{},[604,1885,1886],{},"'ios' | 'all' | false",[1744,1888,1889],{},[604,1890,1891],{},"'ios'",[1744,1893,1894],{},"Where the navbar and tab bar are native: iOS, all platforms or never.",[1723,1896,1897,1902,1906,1910],{},[1744,1898,1899],{},[604,1900,1901],{},"keepTabsAlive",[1744,1903,1904],{},[604,1905,1818],{},[1744,1907,1908],{},[604,1909,705],{},[1744,1911,1912,1913,624],{},"Each tab's own page stays as it was left between tab switches. See ",[597,1914,1916],{"href":1915},"#tab-switching","Tab switching",[1723,1918,1919,1924,1929,1934],{},[1744,1920,1921],{},[604,1922,1923],{},"tabTransitionDuration",[1744,1925,1926],{},[604,1927,1928],{},"number",[1744,1930,1931],{},[604,1932,1933],{},"180",[1744,1935,1936,1937,1874],{},"The crossfade between tabs with the native tab bar, in ms. ",[604,1938,1939],{},"0",[1723,1941,1942,1947,1951,1955],{},[1744,1943,1944],{},[604,1945,1946],{},"native.statusBar",[1744,1948,1949],{},[604,1950,1818],{},[1744,1952,1953],{},[604,1954,705],{},[1744,1956,1957],{},"The status bar text follows the colour mode.",[1723,1959,1960,1965,1969,1973],{},[1744,1961,1962],{},[604,1963,1964],{},"native.keyboardAccessoryBar",[1744,1966,1967],{},[604,1968,1818],{},[1744,1970,1971],{},[604,1972,705],{},[1744,1974,1975],{},"iOS: the Done bar above the keyboard.",[1723,1977,1978,1983,1987,1991],{},[1744,1979,1980],{},[604,1981,1982],{},"native.switchHaptics",[1744,1984,1985],{},[604,1986,1818],{},[1744,1988,1989],{},[604,1990,705],{},[1744,1992,1993,1994,1997],{},"A tick when a ",[604,1995,1996],{},"role=\"switch\""," is tapped.",[1723,1999,2000,2005,2009,2013],{},[1744,2001,2002],{},[604,2003,2004],{},"native.backButton",[1744,2006,2007],{},[604,2008,1818],{},[1744,2010,2011],{},[604,2012,705],{},[1744,2014,2015,2016,624],{},"Handles the ",[597,2017,2019],{"href":2018},"\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices#android","Android back button",[1723,2021,2022,2027,2031,2035],{},[1744,2023,2024],{},[604,2025,2026],{},"appearance.iosTypeScale",[1744,2028,2029],{},[604,2030,1818],{},[1744,2032,2033],{},[604,2034,705],{},[1744,2036,2037],{},"iOS text sizes (17pt body).",[1723,2039,2040,2045,2049,2053],{},[1744,2041,2042],{},[604,2043,2044],{},"appearance.tapHighlight",[1744,2046,2047],{},[604,2048,1818],{},[1744,2050,2051],{},[604,2052,705],{},[1744,2054,2055,2056,2059],{},"No grey tap flash, and ",[604,2057,2058],{},":active"," states on iOS.",[1723,2061,2062,2067,2071,2075],{},[1744,2063,2064],{},[604,2065,2066],{},"appearance.toasterOffset",[1744,2068,2069],{},[604,2070,1818],{},[1744,2072,2073],{},[604,2074,705],{},[1744,2076,2077,2080],{},[604,2078,2079],{},"useMobileToaster()"," puts toasts at the top, below the navbar.",[1723,2082,2083,2088,2093,2097],{},[1744,2084,2085],{},[604,2086,2087],{},"splashScreen",[1744,2089,2090],{},[604,2091,2092],{},"boolean | string | SplashScreenOptions",[1744,2094,2095],{},[604,2096,1873],{},[1744,2098,2099,2100,697,2103,2105],{},"The opt-in ",[597,2101,2102],{"href":373},"splash screen",[604,2104,705],{},", a component name, or options.",[1723,2107,2108,2113,2118,2123],{},[1744,2109,2110],{},[604,2111,2112],{},"deepLinks.schemes",[1744,2114,2115],{},[604,2116,2117],{},"string[] | false",[1744,2119,2120],{},[604,2121,2122],{},"[appId]",[1744,2124,2125,2126,1874],{},"Custom schemes routed into the app. ",[604,2127,1873],{},[1723,2129,2130,2135,2140,2144],{},[1744,2131,2132],{},[604,2133,2134],{},"deepLinks.hosts",[1744,2136,2137],{},[604,2138,2139],{},"string[]",[1744,2141,2142],{},[604,2143,1800],{},[1744,2145,2146,2147,2150],{},"The ",[604,2148,2149],{},"https"," hosts of universal links and app links.",[1723,2152,2153,2158,2163,2167],{},[1744,2154,2155],{},[604,2156,2157],{},"dev.lanHost",[1744,2159,2160],{},[604,2161,2162],{},"boolean | string",[1744,2164,2165],{},[604,2166,705],{},[1744,2168,2169,2170,2173],{},"For ",[604,2171,2172],{},"MOBILE_LAN"," builds: detect the LAN address, or fix it with a string.",[1723,2175,2176,2181,2185,2189],{},[1744,2177,2178],{},[604,2179,2180],{},"ios.allowLocalNetworking",[1744,2182,2183],{},[604,2184,1818],{},[1744,2186,2187],{},[604,2188,705],{},[1744,2190,1846,2191,2194],{},[604,2192,2193],{},"NSAllowsLocalNetworking"," in Info.plist, for plain http to the LAN.",[1723,2196,2197,2202,2206,2210],{},[1744,2198,2199],{},[604,2200,2201],{},"doctor",[1744,2203,2204],{},[604,2205,1818],{},[1744,2207,2208],{},[604,2209,705],{},[1744,2211,2212],{},"Warns about native projects and missing plugins when dev or build starts.",[593,2214,2215,2219,2220,2223,2224,2227,2228,624],{},[637,2216,2217,624],{},[604,2218,1748],{}," In lowercase, with ",[604,2221,2222],{},"_"," turned into ",[604,2225,2226],{},"-",", it becomes the OAuth redirect and deep-link scheme. Without one,\nthe build warns and uses ",[604,2229,2230],{},"com.example.app",[593,2232,2233,2237],{},[637,2234,2235,624],{},[604,2236,1813],{}," It follows Auth's sign-in state. It does not decide which pages need a user.",[593,2239,2240,2244,2245,2248],{},[637,2241,2242,624],{},[604,2243,1857],{}," The layout is also registered as ",[604,2246,2247],{},"default"," when the app has none. A layout of the app with the same name\nwins.",[593,2250,2251,2255,2256,2259],{},[637,2252,2253,624],{},[604,2254,1881],{}," Native chrome needs ",[604,2257,2258],{},"@capgo\u002Fcapacitor-native-navigation",". Without it, the web chrome is used.",[593,2261,2262,2266,2267,624],{},[637,2263,2264,624],{},[604,2265,2157],{}," See ",[597,2268,2270],{"href":2269},"\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices#device-development","Device development",[626,2272,267],{"id":2273},"app",[593,2275,2276],{},"The app side of Mobile: sign-in, tabs, page titles, and the composables and components.",[779,2278,688],{"id":2279},"sign-in",[593,2281,2282,2283,2285,2286,2289,2290,2292,2293,2295,2296,2299,2300,2303],{},"When the app configures ",[604,2284,731],{},", Mobile installs Auth and fills in ",[604,2287,2288],{},"client.native.scheme"," from ",[604,2291,1748],{},". For\n",[604,2294,2172],{}," builds it also fills in ",[604,2297,2298],{},"client.dev.rewriteLoopback",". It never sets the mode: the app sets\n",[604,2301,2302],{},"authentication.mode: 'client'"," itself.",[784,2305,2306],{},"With Auth in server mode the build fails. A Capacitor app cannot send a same-origin session cookie to the API.",[631,2308,2309,2326],{},[634,2310,2311,2314,2315,2317,2318,2321,2322,2325],{},[637,2312,2313],{},"Nothing is protected by default."," Which pages need a user is the app's choice, with\n",[597,2316,199],{"href":200}," rules such as ",[604,2319,2320],{},"'\u002F**': { authenticated: true }",", or ",[604,2323,2324],{},"'\u002Fstaff\u002F**': { permission: 'bills:manage' }"," for a page that needs a permission. When Auth signs the\napp in but no rule requires a user, the build warns that every page is public.",[634,2327,2328,2330,2331,2334,2335,2338],{},[637,2329,639],{}," default to ",[604,2332,2333],{},"requiresAuth: false",". A tab with ",[604,2336,2337],{},"requiresAuth: true"," is hidden while signed out.",[593,2340,2341],{},"The guards only decide what the app shows. The API decides what is allowed.",[779,2343,2345],{"id":2344},"what-the-user-may-do","What the user may do",[593,2347,2348,2349,2289,2352,2354],{},"The app has no server of its own, so ",[604,2350,2351],{},"useAuthorization()",[597,2353,199],{"href":214},"\nruns in client mode. It loads the user's access from the issuer with the bearer access token:",[2356,2357,2358,2368],"ol",{},[634,2359,2360,2361,2364,2365,2367],{},"It calls ",[604,2362,2363],{},"GET \u002Fapi\u002Fauth\u002Fme\u002Faccess"," on the issuer. The answer lists the user's permissions, scopes and, with the\n",[604,2366,1396],{}," scope, roles.",[634,2369,2370,2371,2374,2375,2378,2379,2381],{},"When the issuer has no such endpoint (a ",[604,2372,2373],{},"404",", or the device is offline), it decodes the ",[604,2376,2377],{},"permissions"," claim of the\naccess token instead. This is the case for an issuer such as ",[604,2380,1358],{},". The claim is read without\nverifying it, so it only drives what the app shows.",[593,2383,2384,2385,2388],{},"The access is kept in ",[604,2386,2387],{},"useState",", and it loads again on sign-in and sign-out. Menus, widgets and tabs filter again\nwhen it does.",[795,2390,2393],{"className":1523,"code":2391,"filename":2392,"language":1526,"meta":800,"style":800},"\u003Cscript setup lang=\"ts\">\nconst { can } = useAuthorization()\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CUButton v-if=\"can('bills:update')\" label=\"Edit bill\" \u002F>\n\u003C\u002Ftemplate>\n","app\u002Fpages\u002Fbills\u002F[id].vue",[604,2394,2395,2418,2439,2447,2453,2461,2505],{"__ignoreMap":800},[804,2396,2397,2399,2402,2405,2408,2410,2412,2414,2416],{"class":806,"line":807},[804,2398,1533],{"class":944},[804,2400,2401],{"class":950},"script",[804,2403,2404],{"class":1553}," setup",[804,2406,2407],{"class":1553}," lang",[804,2409,1557],{"class":944},[804,2411,1560],{"class":944},[804,2413,923],{"class":814},[804,2415,1560],{"class":944},[804,2417,1539],{"class":944},[804,2419,2420,2423,2425,2428,2430,2433,2436],{"class":806,"line":833},[804,2421,2422],{"class":1553},"const",[804,2424,1348],{"class":944},[804,2426,2427],{"class":872}," can ",[804,2429,1493],{"class":944},[804,2431,2432],{"class":944}," =",[804,2434,2435],{"class":937}," useAuthorization",[804,2437,2438],{"class":872},"()\n",[804,2440,2441,2443,2445],{"class":806,"line":846},[804,2442,1614],{"class":944},[804,2444,2401],{"class":950},[804,2446,1539],{"class":944},[804,2448,2449],{"class":806,"line":853},[804,2450,2452],{"emptyLinePlaceholder":2451},true,"\n",[804,2454,2455,2457,2459],{"class":806,"line":876},[804,2456,1533],{"class":944},[804,2458,1536],{"class":950},[804,2460,1539],{"class":944},[804,2462,2463,2465,2468,2471,2473,2475,2478,2480,2482,2485,2487,2490,2492,2494,2496,2498,2501,2503],{"class":806,"line":891},[804,2464,1544],{"class":944},[804,2466,2467],{"class":950},"UButton",[804,2469,2470],{"class":930}," v-if",[804,2472,1557],{"class":944},[804,2474,1560],{"class":944},[804,2476,2477],{"class":937},"can",[804,2479,941],{"class":944},[804,2481,960],{"class":944},[804,2483,2484],{"class":814},"bills:update",[804,2486,960],{"class":944},[804,2488,2489],{"class":944},")",[804,2491,1560],{"class":944},[804,2493,1101],{"class":1553},[804,2495,1557],{"class":944},[804,2497,1560],{"class":944},[804,2499,2500],{"class":814},"Edit bill",[804,2502,1560],{"class":944},[804,2504,1591],{"class":944},[804,2506,2507,2509,2511],{"class":806,"line":897},[804,2508,1614],{"class":944},[804,2510,1536],{"class":950},[804,2512,1539],{"class":944},[593,2514,2515,2518,2519,2522],{},[604,2516,2517],{},"can()"," is synchronous and only decides what to show. The token carries only the permissions its scopes covered when it\nwas issued, so ask for the scopes the app needs in ",[604,2520,2521],{},"client.scopes",". The API still checks every call.",[779,2524,639],{"id":1790},[593,2526,2527],{},"A tab definition feeds the native tab bar, the web tab bar and the navbar title.",[795,2529,2531],{"className":920,"code":2530,"language":923,"meta":800,"style":800},"interface MobileTabDefinition {\n  id: string \u002F\u002F native tab id\n  to: string \u002F\u002F the tab's root page\n  label: string\n  labelKey?: string \u002F\u002F i18n key\n  title?: string \u002F\u002F navbar title, default: label\n  titleKey?: string\n  icon: string \u002F\u002F Nuxt UI icon of the web tab bar\n  activeIcon?: string\n  sfSymbol?: string \u002F\u002F native iOS tab\n  sfSymbolActive?: string\n  androidIcon?: string \u002F\u002F drawable, with nativeChrome: 'all'\n  requiresAuth?: boolean \u002F\u002F default: false (hidden while signed out when true)\n  match?: string | string[] \u002F\u002F default: `to` and `to\u002F**` ('\u002F' matches only itself)\n  largeTitle?: boolean \u002F\u002F default true\n  order?: number \u002F\u002F lower first; tabs without it follow in registration order\n}\n",[604,2532,2533,2543,2556,2568,2578,2591,2603,2612,2624,2633,2645,2654,2666,2679,2699,2711,2724],{"__ignoreMap":800},[804,2534,2535,2538,2541],{"class":806,"line":807},[804,2536,2537],{"class":1553},"interface",[804,2539,2540],{"class":810}," MobileTabDefinition",[804,2542,1019],{"class":944},[804,2544,2545,2548,2550,2553],{"class":806,"line":833},[804,2546,2547],{"class":950},"  id",[804,2549,954],{"class":944},[804,2551,2552],{"class":810}," string",[804,2554,2555],{"class":849}," \u002F\u002F native tab id\n",[804,2557,2558,2561,2563,2565],{"class":806,"line":846},[804,2559,2560],{"class":950},"  to",[804,2562,954],{"class":944},[804,2564,2552],{"class":810},[804,2566,2567],{"class":849}," \u002F\u002F the tab's root page\n",[804,2569,2570,2573,2575],{"class":806,"line":853},[804,2571,2572],{"class":950},"  label",[804,2574,954],{"class":944},[804,2576,2577],{"class":810}," string\n",[804,2579,2580,2583,2586,2588],{"class":806,"line":876},[804,2581,2582],{"class":950},"  labelKey",[804,2584,2585],{"class":944},"?:",[804,2587,2552],{"class":810},[804,2589,2590],{"class":849}," \u002F\u002F i18n key\n",[804,2592,2593,2596,2598,2600],{"class":806,"line":891},[804,2594,2595],{"class":950},"  title",[804,2597,2585],{"class":944},[804,2599,2552],{"class":810},[804,2601,2602],{"class":849}," \u002F\u002F navbar title, default: label\n",[804,2604,2605,2608,2610],{"class":806,"line":897},[804,2606,2607],{"class":950},"  titleKey",[804,2609,2585],{"class":944},[804,2611,2577],{"class":810},[804,2613,2614,2617,2619,2621],{"class":806,"line":1067},[804,2615,2616],{"class":950},"  icon",[804,2618,954],{"class":944},[804,2620,2552],{"class":810},[804,2622,2623],{"class":849}," \u002F\u002F Nuxt UI icon of the web tab bar\n",[804,2625,2626,2629,2631],{"class":806,"line":1144},[804,2627,2628],{"class":950},"  activeIcon",[804,2630,2585],{"class":944},[804,2632,2577],{"class":810},[804,2634,2635,2638,2640,2642],{"class":806,"line":1213},[804,2636,2637],{"class":950},"  sfSymbol",[804,2639,2585],{"class":944},[804,2641,2552],{"class":810},[804,2643,2644],{"class":849}," \u002F\u002F native iOS tab\n",[804,2646,2647,2650,2652],{"class":806,"line":1293},[804,2648,2649],{"class":950},"  sfSymbolActive",[804,2651,2585],{"class":944},[804,2653,2577],{"class":810},[804,2655,2656,2659,2661,2663],{"class":806,"line":1301},[804,2657,2658],{"class":950},"  androidIcon",[804,2660,2585],{"class":944},[804,2662,2552],{"class":810},[804,2664,2665],{"class":849}," \u002F\u002F drawable, with nativeChrome: 'all'\n",[804,2667,2668,2671,2673,2676],{"class":806,"line":1307},[804,2669,2670],{"class":950},"  requiresAuth",[804,2672,2585],{"class":944},[804,2674,2675],{"class":810}," boolean",[804,2677,2678],{"class":849}," \u002F\u002F default: false (hidden while signed out when true)\n",[804,2680,2681,2684,2686,2688,2691,2693,2696],{"class":806,"line":1313},[804,2682,2683],{"class":950},"  match",[804,2685,2585],{"class":944},[804,2687,2552],{"class":810},[804,2689,2690],{"class":944}," |",[804,2692,2552],{"class":810},[804,2694,2695],{"class":872},"[] ",[804,2697,2698],{"class":849},"\u002F\u002F default: `to` and `to\u002F**` ('\u002F' matches only itself)\n",[804,2700,2701,2704,2706,2708],{"class":806,"line":1323},[804,2702,2703],{"class":950},"  largeTitle",[804,2705,2585],{"class":944},[804,2707,2675],{"class":810},[804,2709,2710],{"class":849}," \u002F\u002F default true\n",[804,2712,2713,2716,2718,2721],{"class":806,"line":1340},[804,2714,2715],{"class":950},"  order",[804,2717,2585],{"class":944},[804,2719,2720],{"class":810}," number",[804,2722,2723],{"class":849}," \u002F\u002F lower first; tabs without it follow in registration order\n",[804,2725,2726],{"class":806,"line":1416},[804,2727,2728],{"class":944},"}\n",[593,2730,2731,2732,2735],{},"A module adds its tabs from ",[604,2733,2734],{},"setup()",". A later tab with the same id replaces its fields, so a host can relabel one:",[795,2737,2739],{"className":920,"code":2738,"language":923,"meta":800,"style":800},"import { extendMobileTabs } from '@frigear-nu\u002Fmobile\u002Futils'\n\nextendMobileTabs(nuxt, { id: 'events', to: '\u002Fevents', label: 'Events', icon: 'i-lucide-calendar', sfSymbol: 'calendar' })\n",[604,2740,2741,2765,2769],{"__ignoreMap":800},[804,2742,2743,2746,2748,2751,2754,2757,2759,2762],{"class":806,"line":807},[804,2744,2745],{"class":930},"import",[804,2747,1348],{"class":944},[804,2749,2750],{"class":872}," extendMobileTabs",[804,2752,2753],{"class":944}," }",[804,2755,2756],{"class":930}," from",[804,2758,970],{"class":944},[804,2760,2761],{"class":814},"@frigear-nu\u002Fmobile\u002Futils",[804,2763,2764],{"class":944},"'\n",[804,2766,2767],{"class":806,"line":833},[804,2768,2452],{"emptyLinePlaceholder":2451},[804,2770,2771,2774,2777,2779,2781,2783,2785,2787,2790,2792,2794,2796,2798,2800,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2828,2830,2832,2834,2836,2838,2841,2843,2845],{"class":806,"line":846},[804,2772,2773],{"class":937},"extendMobileTabs",[804,2775,2776],{"class":872},"(nuxt",[804,2778,967],{"class":944},[804,2780,1348],{"class":944},[804,2782,1073],{"class":950},[804,2784,954],{"class":944},[804,2786,970],{"class":944},[804,2788,2789],{"class":814},"events",[804,2791,960],{"class":944},[804,2793,967],{"class":944},[804,2795,1087],{"class":950},[804,2797,954],{"class":944},[804,2799,970],{"class":944},[804,2801,2802],{"class":814},"\u002Fevents",[804,2804,960],{"class":944},[804,2806,967],{"class":944},[804,2808,1101],{"class":950},[804,2810,954],{"class":944},[804,2812,970],{"class":944},[804,2814,279],{"class":814},[804,2816,960],{"class":944},[804,2818,967],{"class":944},[804,2820,1115],{"class":950},[804,2822,954],{"class":944},[804,2824,970],{"class":944},[804,2826,2827],{"class":814},"i-lucide-calendar",[804,2829,960],{"class":944},[804,2831,967],{"class":944},[804,2833,1129],{"class":950},[804,2835,954],{"class":944},[804,2837,970],{"class":944},[804,2839,2840],{"class":814},"calendar",[804,2842,960],{"class":944},[804,2844,2753],{"class":944},[804,2846,1496],{"class":872},[593,2848,2849,2851,2852,659,2855,659,2858,2861,2862,2865,2866,2868,2869,2871,2872,2875,2876,624],{},[604,2850,2761],{}," also exports ",[604,2853,2854],{},"defineMobileTab",[604,2856,2857],{},"normalizeTabs",[604,2859,2860],{},"findActiveTab"," and ",[604,2863,2864],{},"matchesPath",". With\n",[597,2867,354],{"href":355},", the items of the ",[604,2870,769],{}," menu are added as tabs and replace tabs with the same\nid. Tab fields such as ",[604,2873,2874],{},"sfSymbol"," go in the item's ",[604,2877,2878],{},"meta",[593,2880,2881,2882,659,2885,2888,2889,2892,2893,2895,2896,2898,2899,624],{},"The build fails on an invalid id, or a tab without ",[604,2883,2884],{},"to",[604,2886,2887],{},"label"," or ",[604,2890,2891],{},"icon",". It warns about more than five tabs, two\ntabs with the same ",[604,2894,2884],{},", a ",[604,2897,2884],{}," that is not a page and, with native chrome, a tab without an ",[604,2900,2874],{},[779,2902,101],{"id":2903},"pages",[593,2905,2906,2907,2910,2911,624],{},"A page sets its title and chrome in ",[604,2908,2909],{},"definePageMeta",". The title comes from page meta, else the selected tab, else\n",[604,2912,1512],{},[795,2914,2916],{"className":920,"code":2915,"language":923,"meta":800,"style":800},"definePageMeta({\n  mobile: {\n    title: 'Bill', \u002F\u002F or titleKey\n    largeTitle: false,\n    tabBar: false, \u002F\u002F hide the tab bar here (true: show it on a page outside the tabs)\n    navbar: false, \u002F\u002F no navbar or header\n    tab: 'bills', \u002F\u002F select this tab\n    back: true, \u002F\u002F back button (default: on pages below a tab's root page)\n  },\n})\n",[604,2917,2918,2926,2934,2953,2965,2979,2993,3011,3025,3029],{"__ignoreMap":800},[804,2919,2920,2922,2924],{"class":806,"line":807},[804,2921,2909],{"class":937},[804,2923,941],{"class":872},[804,2925,945],{"class":944},[804,2927,2928,2930,2932],{"class":806,"line":833},[804,2929,1014],{"class":950},[804,2931,954],{"class":944},[804,2933,1019],{"class":944},[804,2935,2936,2939,2941,2943,2946,2948,2950],{"class":806,"line":846},[804,2937,2938],{"class":950},"    title",[804,2940,954],{"class":944},[804,2942,970],{"class":944},[804,2944,2945],{"class":814},"Bill",[804,2947,960],{"class":944},[804,2949,967],{"class":944},[804,2951,2952],{"class":849}," \u002F\u002F or titleKey\n",[804,2954,2955,2958,2960,2963],{"class":806,"line":853},[804,2956,2957],{"class":950},"    largeTitle",[804,2959,954],{"class":944},[804,2961,2962],{"class":1287}," false",[804,2964,989],{"class":944},[804,2966,2967,2970,2972,2974,2976],{"class":806,"line":876},[804,2968,2969],{"class":950},"    tabBar",[804,2971,954],{"class":944},[804,2973,2962],{"class":1287},[804,2975,967],{"class":944},[804,2977,2978],{"class":849}," \u002F\u002F hide the tab bar here (true: show it on a page outside the tabs)\n",[804,2980,2981,2984,2986,2988,2990],{"class":806,"line":891},[804,2982,2983],{"class":950},"    navbar",[804,2985,954],{"class":944},[804,2987,2962],{"class":1287},[804,2989,967],{"class":944},[804,2991,2992],{"class":849}," \u002F\u002F no navbar or header\n",[804,2994,2995,2998,3000,3002,3004,3006,3008],{"class":806,"line":897},[804,2996,2997],{"class":950},"    tab",[804,2999,954],{"class":944},[804,3001,970],{"class":944},[804,3003,1155],{"class":814},[804,3005,960],{"class":944},[804,3007,967],{"class":944},[804,3009,3010],{"class":849}," \u002F\u002F select this tab\n",[804,3012,3013,3016,3018,3020,3022],{"class":806,"line":1067},[804,3014,3015],{"class":950},"    back",[804,3017,954],{"class":944},[804,3019,1288],{"class":1287},[804,3021,967],{"class":944},[804,3023,3024],{"class":849}," \u002F\u002F back button (default: on pages below a tab's root page)\n",[804,3026,3027],{"class":806,"line":1144},[804,3028,1304],{"class":944},[804,3030,3031,3033],{"class":806,"line":1213},[804,3032,1493],{"class":944},[804,3034,1496],{"class":872},[3036,3037,3039],"h4",{"id":3038},"navbar-actions","Navbar actions",[593,3041,3042,3043,3046,3047,3049,3050,3053,3054,3056],{},"A page adds buttons to the navbar with ",[604,3044,3045],{},"actions",", such as a settings gear on the home page. On iOS they are native\nnavbar buttons (",[604,3048,2874],{},"), elsewhere icon buttons in ",[604,3051,3052],{},"MobileHeader"," (",[604,3055,2891],{},"). They show on that page only.",[795,3058,3060],{"className":920,"code":3059,"language":923,"meta":800,"style":800},"definePageMeta({\n  mobile: {\n    actions: [\n      { id: 'settings', label: 'Settings', icon: 'i-lucide-settings', sfSymbol: 'gearshape', to: '\u002Fsettings' },\n    ],\n  },\n})\n",[604,3061,3062,3070,3078,3087,3155,3161,3165],{"__ignoreMap":800},[804,3063,3064,3066,3068],{"class":806,"line":807},[804,3065,2909],{"class":937},[804,3067,941],{"class":872},[804,3069,945],{"class":944},[804,3071,3072,3074,3076],{"class":806,"line":833},[804,3073,1014],{"class":950},[804,3075,954],{"class":944},[804,3077,1019],{"class":944},[804,3079,3080,3083,3085],{"class":806,"line":846},[804,3081,3082],{"class":950},"    actions",[804,3084,954],{"class":944},[804,3086,1064],{"class":872},[804,3088,3089,3091,3093,3095,3097,3100,3102,3104,3106,3108,3110,3113,3115,3117,3119,3121,3123,3125,3127,3129,3131,3133,3135,3138,3140,3142,3144,3146,3148,3151,3153],{"class":806,"line":853},[804,3090,1070],{"class":944},[804,3092,1073],{"class":950},[804,3094,954],{"class":944},[804,3096,970],{"class":944},[804,3098,3099],{"class":814},"settings",[804,3101,960],{"class":944},[804,3103,967],{"class":944},[804,3105,1101],{"class":950},[804,3107,954],{"class":944},[804,3109,970],{"class":944},[804,3111,3112],{"class":814},"Settings",[804,3114,960],{"class":944},[804,3116,967],{"class":944},[804,3118,1115],{"class":950},[804,3120,954],{"class":944},[804,3122,970],{"class":944},[804,3124,29],{"class":814},[804,3126,960],{"class":944},[804,3128,967],{"class":944},[804,3130,1129],{"class":950},[804,3132,954],{"class":944},[804,3134,970],{"class":944},[804,3136,3137],{"class":814},"gearshape",[804,3139,960],{"class":944},[804,3141,967],{"class":944},[804,3143,1087],{"class":950},[804,3145,954],{"class":944},[804,3147,970],{"class":944},[804,3149,3150],{"class":814},"\u002Fsettings",[804,3152,960],{"class":944},[804,3154,1141],{"class":944},[804,3156,3157,3159],{"class":806,"line":876},[804,3158,1296],{"class":872},[804,3160,989],{"class":944},[804,3162,3163],{"class":806,"line":891},[804,3164,1304],{"class":944},[804,3166,3167,3169],{"class":806,"line":897},[804,3168,1493],{"class":944},[804,3170,1496],{"class":872},[1717,3172,3173,3183],{},[1720,3174,3175],{},[1723,3176,3177,3180],{},[1726,3178,3179],{},"Field",[1726,3181,3182],{},"What it is",[1739,3184,3185,3195,3208,3222,3233,3247,3264,3274,3285],{},[1723,3186,3187,3192],{},[1744,3188,3189],{},[604,3190,3191],{},"id",[1744,3193,3194],{},"Stable id.",[1723,3196,3197,3205],{},[1744,3198,3199,3201,3202],{},[604,3200,2887],{}," \u002F ",[604,3203,3204],{},"labelKey",[1744,3206,3207],{},"Accessible name, and the button text when the platform has no icon for it.",[1723,3209,3210,3214],{},[1744,3211,3212],{},[604,3213,2891],{},[1744,3215,3216,3217,3219,3220,624],{},"Nuxt UI icon in ",[604,3218,3052],{},", e.g. ",[604,3221,29],{},[1723,3223,3224,3228],{},[1744,3225,3226],{},[604,3227,2874],{},[1744,3229,3230,3231,624],{},"SF Symbol of the native iOS button, e.g. ",[604,3232,3137],{},[1723,3234,3235,3240],{},[1744,3236,3237],{},[604,3238,3239],{},"androidIcon",[1744,3241,3242,3243,3246],{},"Android drawable of the native button (with ",[604,3244,3245],{},"nativeChrome: 'all'",").",[1723,3248,3249,3254],{},[1744,3250,3251],{},[604,3252,3253],{},"placement",[1744,3255,3256,3259,3260,3263],{},[604,3257,3258],{},"right"," (default) or ",[604,3261,3262],{},"left",". Left actions sit after the back button.",[1723,3265,3266,3271],{},[1744,3267,3268],{},[604,3269,3270],{},"onSelect",[1744,3272,3273],{},"Called on a tap.",[1723,3275,3276,3280],{},[1744,3277,3278],{},[604,3279,2884],{},[1744,3281,3282,3283,624],{},"Navigated to on a tap, after ",[604,3284,3270],{},[1723,3286,3287,3292],{},[1744,3288,3289],{},[604,3290,3291],{},"disabled",[1744,3293,3294],{},"Greyed out and not tappable.",[593,3296,3297,3298,3301,3302,3305,3306,3308,3309,3311,3312,3315,3316,624],{},"For actions that change, or that call into the page, use ",[604,3299,3300],{},"useMobileNavbarActions()"," in the page's ",[604,3303,3304],{},"\u003Cscript setup>","\nwith a ref or a getter. The actions are added in setup and removed on unmount, and while a kept-alive page is in the\nbackground. They follow the ",[604,3307,2909],{}," ones; one with the same ",[604,3310,3191],{}," replaces it. With ",[604,3313,3314],{},"spa: false"," they show\nonce the page is set up in the browser, not in the server HTML: put actions that must be there in ",[604,3317,2909],{},[795,3319,3321],{"className":920,"code":3320,"language":923,"meta":800,"style":800},"const saving = ref(false)\nuseMobileNavbarActions(() => [\n  { id: 'save', label: 'Save', sfSymbol: 'checkmark', icon: 'i-lucide-check', disabled: saving.value, onSelect: save },\n])\n",[604,3322,3323,3341,3355,3436],{"__ignoreMap":800},[804,3324,3325,3327,3330,3332,3335,3337,3339],{"class":806,"line":807},[804,3326,2422],{"class":1553},[804,3328,3329],{"class":872}," saving ",[804,3331,1557],{"class":944},[804,3333,3334],{"class":937}," ref",[804,3336,941],{"class":872},[804,3338,1873],{"class":1287},[804,3340,1496],{"class":872},[804,3342,3343,3346,3348,3350,3353],{"class":806,"line":833},[804,3344,3345],{"class":937},"useMobileNavbarActions",[804,3347,941],{"class":872},[804,3349,1566],{"class":944},[804,3351,3352],{"class":1553}," =>",[804,3354,1064],{"class":872},[804,3356,3357,3360,3362,3364,3366,3369,3371,3373,3375,3377,3379,3382,3384,3386,3388,3390,3392,3395,3397,3399,3401,3403,3405,3407,3409,3411,3414,3416,3419,3421,3424,3426,3429,3431,3434],{"class":806,"line":846},[804,3358,3359],{"class":944},"  {",[804,3361,1073],{"class":950},[804,3363,954],{"class":944},[804,3365,970],{"class":944},[804,3367,3368],{"class":814},"save",[804,3370,960],{"class":944},[804,3372,967],{"class":944},[804,3374,1101],{"class":950},[804,3376,954],{"class":944},[804,3378,970],{"class":944},[804,3380,3381],{"class":814},"Save",[804,3383,960],{"class":944},[804,3385,967],{"class":944},[804,3387,1129],{"class":950},[804,3389,954],{"class":944},[804,3391,970],{"class":944},[804,3393,3394],{"class":814},"checkmark",[804,3396,960],{"class":944},[804,3398,967],{"class":944},[804,3400,1115],{"class":950},[804,3402,954],{"class":944},[804,3404,970],{"class":944},[804,3406,1699],{"class":814},[804,3408,960],{"class":944},[804,3410,967],{"class":944},[804,3412,3413],{"class":950}," disabled",[804,3415,954],{"class":944},[804,3417,3418],{"class":872}," saving",[804,3420,624],{"class":944},[804,3422,3423],{"class":872},"value",[804,3425,967],{"class":944},[804,3427,3428],{"class":950}," onSelect",[804,3430,954],{"class":944},[804,3432,3433],{"class":872}," save ",[804,3435,1413],{"class":944},[804,3437,3438],{"class":806,"line":853},[804,3439,3440],{"class":872},"])\n",[779,3442,3444],{"id":3443},"composables-and-components","Composables and components",[593,3446,3447],{},"The composables and components below are auto-imported.",[1717,3449,3450,3459],{},[1720,3451,3452],{},[1723,3453,3454,3457],{},[1726,3455,3456],{},"Name",[1726,3458,3182],{},[1739,3460,3461,3497,3514,3532,3545,3557,3573,3585,3610,3626,3636,3650,3670],{},[1723,3462,3463,3467],{},[1744,3464,3465],{},[604,3466,658],{},[1744,3468,3469,3053,3472,659,3475,2888,3478,3481,3482,659,3485,659,3488,659,3491,2861,3494,624],{},[604,3470,3471],{},"platform",[604,3473,3474],{},"ios",[604,3476,3477],{},"android",[604,3479,3480],{},"web","), ",[604,3483,3484],{},"isNative",[604,3486,3487],{},"isIos",[604,3489,3490],{},"isAndroid",[604,3492,3493],{},"has(plugin)",[604,3495,3496],{},"load(plugin)",[1723,3498,3499,3504],{},[1744,3500,3501],{},[604,3502,3503],{},"useMobileTabs()",[1744,3505,3506,659,3508,2861,3511,624],{},[604,3507,1790],{},[604,3509,3510],{},"label(tab)",[604,3512,3513],{},"title(tab)",[1723,3515,3516,3520],{},[1744,3517,3518],{},[604,3519,666],{},[1744,3521,3522,659,3525,2861,3528,3531],{},[604,3523,3524],{},"state",[604,3526,3527],{},"native",[604,3529,3530],{},"suppress()",", which hides the tab bar until you call the function it returns.",[1723,3533,3534,3539],{},[1744,3535,3536],{},[604,3537,3538],{},"useMobileNavbarActions(actions)",[1744,3540,3541,3542,624],{},"Navbar buttons of the calling page, from a ref or a getter. See ",[597,3543,3039],{"href":3544},"#navbar-actions",[1723,3546,3547,3551],{},[1744,3548,3549],{},[604,3550,662],{},[1744,3552,1803,3553,624],{},[597,3554,3556],{"href":3555},"#native-features","Native features",[1723,3558,3559,3564],{},[1744,3560,3561],{},[604,3562,3563],{},"onTabEnter(fn)",[1744,3565,3566,3567,3570,3571,624],{},"Runs ",[604,3568,3569],{},"fn"," when the user comes back to a page kept alive. See ",[597,3572,1916],{"href":1915},[1723,3574,3575,3579],{},[1744,3576,3577],{},[604,3578,2079],{},[1744,3580,3581,3582,624],{},"Props for ",[604,3583,3584],{},"\u003CUApp :toaster>",[1723,3586,3587,3592],{},[1744,3588,3589],{},[604,3590,3591],{},"useMobileSplash()",[1744,3593,3594,659,3597,659,3600,2861,3603,3606,3607,624],{},[604,3595,3596],{},"visible",[604,3598,3599],{},"hold()",[604,3601,3602],{},"waitFor(promise)",[604,3604,3605],{},"hide()",": see ",[597,3608,372],{"href":3609},"\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen#keep-it-up",[1723,3611,3612,3616],{},[1744,3613,3614],{},[604,3615,3052],{},[1744,3617,3618,3619,2861,3622,3625],{},"The web header, with the page's navbar actions and ",[604,3620,3621],{},"leading",[604,3623,3624],{},"trailing"," slots.",[1723,3627,3628,3633],{},[1744,3629,3630],{},[604,3631,3632],{},"MobileTabBar",[1744,3634,3635],{},"The web tab bar.",[1723,3637,3638,3643],{},[1744,3639,3640],{},[604,3641,3642],{},"MobileSplashScreen",[1744,3644,3645,3646,3649],{},"The default splash screen. Your own ",[604,3647,3648],{},"components\u002FMobile\u002FSplashScreen.vue"," replaces it.",[1723,3651,3652,3657],{},[1744,3653,3654],{},[604,3655,3656],{},"MobileFab",[1744,3658,3659,3660,659,3662,659,3664,2321,3666,3669],{},"A floating action button: ",[604,3661,2887],{},[604,3663,2891],{},[604,3665,2884],{},[604,3667,3668],{},"items"," for an action sheet on a device.",[1723,3671,3672,3677],{},[1744,3673,3674,3676],{},[604,3675,649],{}," layout",[1744,3678,3679,3680,3649],{},"Header, page and tab bar. Your own ",[604,3681,3682],{},"layouts\u002Fmobile.vue",[593,3684,3685,3686,3688,3689,3691,3692,3694],{},"Nuxt UI dialogs, slideovers and drawers hide the tab bar on their own; ",[604,3687,3530],{}," is for an overlay of your own. In a\nbrowser, ",[604,3690,3656],{}," with ",[604,3693,3668],{}," opens a dropdown instead of an action sheet.",[593,3696,3697,3698,659,3701,2861,3704,3707,3708,3711,3712,659,3715,2888,3718,3721,3722,624],{},"The CSS variables ",[604,3699,3700],{},"--mobile-inset-top",[604,3702,3703],{},"--mobile-inset-bottom",[604,3705,3706],{},"--mobile-tabbar-height"," are the same for native\nand web chrome. ",[604,3709,3710],{},"\u003Chtml>"," gets the classes ",[604,3713,3714],{},"mobile-platform-\u003Cplatform>",[604,3716,3717],{},"mobile-chrome-native",[604,3719,3720],{},"mobile-chrome-web",",\nand ",[604,3723,3724],{},"mobile-has-tabbar",[779,3726,3728],{"id":3727},"native-chrome","Native chrome",[593,3730,3731,3732,3734,3735,2861,3737,3739,3740,3742,3743,3745],{},"On iOS, with ",[604,3733,2258],{}," installed, the navbar and the tab bar are native. In a browser and on\nAndroid the module draws ",[604,3736,3052],{},[604,3738,3632],{}," instead. ",[604,3741,3245],{}," uses the native ones on\nAndroid too, with ",[604,3744,3239],{}," drawables.",[779,3747,1916],{"id":3748},"tab-switching",[593,3750,3751],{},"Switching tabs works like a native tab bar. The page you leave stays as it was, and the page you open appears only once\nit is ready.",[631,3753,3754,3770,3776],{},[634,3755,3756,3759,3760,3762,3763,3721,3766,3769],{},[637,3757,3758],{},"Tab pages stay alive."," A tab's own page (its ",[604,3761,2884],{},") stays mounted, with its scroll position and data, when you\nswitch to another tab. Pages below a tab still remount. A page opts out with ",[604,3764,3765],{},"definePageMeta({ keepalive: false })",[604,3767,3768],{},"keepTabsAlive: false"," turns this off for the app.",[634,3771,3772,3775],{},[637,3773,3774],{},"Tab pages load up front."," The code of every tab's page is preloaded once the app is ready.",[634,3777,3778,3781],{},[637,3779,3780],{},"No half-built pages with native chrome."," A tap in the native tab bar covers the WebView with a snapshot of the old\npage. The new page renders under it, the navbar title changes, and then the snapshot crossfades away.",[593,3783,3784,3785,3788,3789,3792],{},"The crossfade waits for every async ",[604,3786,3787],{},"setup"," of the new page, up to one second. Await a tab page's first request, so the\npage is revealed with its data and not with a skeleton. Then refresh it in the background with ",[604,3790,3791],{},"onTabEnter",", which runs\neach time the user comes back to the page, but not on the first visit:",[795,3794,3796],{"className":1523,"code":3795,"language":1526,"meta":800,"style":800},"\u003Cscript setup lang=\"ts\">\nconst { data: me, status, refresh } = await useApi\u003CMe>('\u002Fapi\u002Fme')\nonTabEnter(() => refresh())\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003C!-- A skeleton only while there is no data yet, not during a background refresh. -->\n  \u003CUSkeleton v-if=\"!me && status === 'pending'\" class=\"h-10 w-full\" \u002F>\n\u003C\u002Ftemplate>\n",[604,3797,3798,3818,3871,3887,3895,3899,3907,3912,3962],{"__ignoreMap":800},[804,3799,3800,3802,3804,3806,3808,3810,3812,3814,3816],{"class":806,"line":807},[804,3801,1533],{"class":944},[804,3803,2401],{"class":950},[804,3805,2404],{"class":1553},[804,3807,2407],{"class":1553},[804,3809,1557],{"class":944},[804,3811,1560],{"class":944},[804,3813,923],{"class":814},[804,3815,1560],{"class":944},[804,3817,1539],{"class":944},[804,3819,3820,3822,3824,3827,3829,3832,3834,3837,3839,3842,3844,3846,3849,3852,3854,3857,3860,3862,3864,3867,3869],{"class":806,"line":833},[804,3821,2422],{"class":1553},[804,3823,1348],{"class":944},[804,3825,3826],{"class":950}," data",[804,3828,954],{"class":944},[804,3830,3831],{"class":872}," me",[804,3833,967],{"class":944},[804,3835,3836],{"class":872}," status",[804,3838,967],{"class":944},[804,3840,3841],{"class":872}," refresh ",[804,3843,1493],{"class":944},[804,3845,2432],{"class":944},[804,3847,3848],{"class":930}," await",[804,3850,3851],{"class":937}," useApi",[804,3853,1533],{"class":944},[804,3855,3856],{"class":810},"Me",[804,3858,3859],{"class":944},">",[804,3861,941],{"class":872},[804,3863,960],{"class":944},[804,3865,3866],{"class":814},"\u002Fapi\u002Fme",[804,3868,960],{"class":944},[804,3870,1496],{"class":872},[804,3872,3873,3875,3877,3879,3881,3884],{"class":806,"line":846},[804,3874,3791],{"class":937},[804,3876,941],{"class":872},[804,3878,1566],{"class":944},[804,3880,3352],{"class":1553},[804,3882,3883],{"class":937}," refresh",[804,3885,3886],{"class":872},"())\n",[804,3888,3889,3891,3893],{"class":806,"line":853},[804,3890,1614],{"class":944},[804,3892,2401],{"class":950},[804,3894,1539],{"class":944},[804,3896,3897],{"class":806,"line":876},[804,3898,2452],{"emptyLinePlaceholder":2451},[804,3900,3901,3903,3905],{"class":806,"line":891},[804,3902,1533],{"class":944},[804,3904,1536],{"class":950},[804,3906,1539],{"class":944},[804,3908,3909],{"class":806,"line":897},[804,3910,3911],{"class":849},"  \u003C!-- A skeleton only while there is no data yet, not during a background refresh. -->\n",[804,3913,3914,3916,3919,3921,3923,3925,3928,3931,3934,3937,3940,3942,3945,3948,3951,3953,3955,3958,3960],{"class":806,"line":1067},[804,3915,1544],{"class":944},[804,3917,3918],{"class":950},"USkeleton",[804,3920,2470],{"class":930},[804,3922,1557],{"class":944},[804,3924,1560],{"class":944},[804,3926,3927],{"class":944},"!",[804,3929,3930],{"class":872},"me",[804,3932,3933],{"class":944}," && ",[804,3935,3936],{"class":872},"status",[804,3938,3939],{"class":944}," === ",[804,3941,960],{"class":944},[804,3943,3944],{"class":814},"pending",[804,3946,3947],{"class":944},"'\"",[804,3949,3950],{"class":1553}," class",[804,3952,1557],{"class":944},[804,3954,1560],{"class":944},[804,3956,3957],{"class":814},"h-10 w-full",[804,3959,1560],{"class":944},[804,3961,1591],{"class":944},[804,3963,3964,3966,3968],{"class":806,"line":1144},[804,3965,1614],{"class":944},[804,3967,1536],{"class":950},[804,3969,1539],{"class":944},[707,3971,3972,3973,3976],{},"The crossfade uses the plugin's ",[604,3974,3975],{},"beginTransition",", which the starters' version (8.16) has. A plugin version without\nit switches tabs without a crossfade.",[779,3978,3556],{"id":3979},"native-features",[593,3981,3982,3984],{},[604,3983,662],{}," wraps Capacitor plugins and falls back in a browser:",[1717,3986,3987,4000],{},[1720,3988,3989],{},[1723,3990,3991,3994,3997],{},[1726,3992,3993],{},"Method",[1726,3995,3996],{},"Plugin",[1726,3998,3999],{},"In a browser",[1739,4001,4002,4017,4036,4056],{},[1723,4003,4004,4009,4014],{},[1744,4005,4006],{},[604,4007,4008],{},"haptic('light' | 'medium' | 'heavy' | 'success' | 'warning' | 'error' | 'selection')",[1744,4010,4011],{},[604,4012,4013],{},"@capacitor\u002Fhaptics",[1744,4015,4016],{},"Does nothing.",[1723,4018,4019,4024,4029],{},[1744,4020,4021],{},[604,4022,4023],{},"actionSheet({ actions })",[1744,4025,4026],{},[604,4027,4028],{},"@capacitor\u002Faction-sheet",[1744,4030,4031,4032,4035],{},"Returns ",[604,4033,4034],{},"null",": show a menu then.",[1723,4037,4038,4043,4048],{},[1744,4039,4040],{},[604,4041,4042],{},"confirm({ title, description, destructive })",[1744,4044,4045],{},[604,4046,4047],{},"@capacitor\u002Fdialog",[1744,4049,4050,4052,4053,4055],{},[604,4051,759],{}," of ",[604,4054,755],{},", or a small modal.",[1723,4057,4058,4063,4068],{},[1744,4059,4060],{},[604,4061,4062],{},"share({ title, text, url })",[1744,4064,4065],{},[604,4066,4067],{},"@capacitor\u002Fshare",[1744,4069,4070],{},"The Web Share API, else the link is copied to the clipboard.",[626,4072,234],{"id":4073},"hooks",[593,4075,4076,4077,3691,4079,624],{},"Your app answers these runtime ",[597,4078,4073],{"href":87},[604,4080,4081],{},"useNuxtApp().hook(...)",[1717,4083,4084,4097],{},[1720,4085,4086],{},[1723,4087,4088,4091,4094],{},[1726,4089,4090],{},"Hook",[1726,4092,4093],{},"Payload",[1726,4095,4096],{},"When",[1739,4098,4099,4114],{},[1723,4100,4101,4106,4111],{},[1744,4102,4103],{},[604,4104,4105],{},"mobile:deep-link",[1744,4107,4108],{},[604,4109,4110],{},"{ url, path, preventDefault }",[1744,4112,4113],{},"A custom scheme or universal link opened the app. OAuth callbacks never reach it.",[1723,4115,4116,4121,4126],{},[1744,4117,4118],{},[604,4119,4120],{},"mobile:back-button",[1744,4122,4123],{},[604,4124,4125],{},"{ canGoBack, preventDefault }",[1744,4127,4128],{},"The Android back button was pressed, before the module acts.",[593,4130,4131,4135,4136,4139,4140,4143,4144,4147,4148,4150,4151,4153,4154,4156],{},[637,4132,4133,624],{},[604,4134,4105],{}," Change ",[604,4137,4138],{},"path"," to route elsewhere, or call ",[604,4141,4142],{},"preventDefault()"," to handle the link yourself. Deep\nlinks need ",[604,4145,4146],{},"@capacitor\u002Fapp"," and a scheme in ",[604,4149,2112],{}," or a host in ",[604,4152,2134],{},". The ",[604,4155,3527],{}," command\nregisters them in the native projects.",[593,4158,4159,4163,4164,4166],{},[637,4160,4161,624],{},[604,4162,4120],{}," Call ",[604,4165,4142],{}," when you handled the button.",[626,4168,4170],{"id":4169},"module-pages","Module pages",[1717,4172,4173,4186],{},[1720,4174,4175],{},[1723,4176,4177,4180,4183],{},[1726,4178,4179],{},"Page",[1726,4181,4182],{},"What it covers",[1726,4184,4185],{},"For",[1739,4187,4188,4202],{},[1723,4189,4190,4194,4199],{},[1744,4191,4192],{},[597,4193,368],{"href":369},[1744,4195,2146,4196,4198],{},[604,4197,700],{}," command, testing on a phone, Android and the release checklist.",[1744,4200,4201],{},"App developers",[1723,4203,4204,4208,4211],{},[1744,4205,4206],{},[597,4207,372],{"href":373},[1744,4209,4210],{},"The opt-in splash screen from the native launch image to the first page: turn it on, replace it, keep it up.",[1744,4212,4201],{},[626,4214,4216],{"id":4215},"next-steps","Next steps",[631,4218,4219,4225,4230,4235],{},[634,4220,4221,4224],{},[597,4222,4223],{"href":369},"Mobile CLI and devices"," – run the app on a phone and prepare a release.",[634,4226,4227,4229],{},[597,4228,131],{"href":132}," – point the app at an issuer you run.",[634,4231,4232,4234],{},[597,4233,199],{"href":200}," – choose which pages need a signed-in user.",[634,4236,4237,4239],{},[597,4238,241],{"href":242}," – let each service the app calls accept its access token.",[4241,4242,4243],"style",{},"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 .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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":800,"searchDepth":833,"depth":833,"links":4245},[4246,4247,4253,4254,4264,4265,4266],{"id":628,"depth":833,"text":629},{"id":773,"depth":833,"text":774,"children":4248},[4249,4250,4251,4252],{"id":781,"depth":846,"text":782},{"id":916,"depth":846,"text":917},{"id":1519,"depth":846,"text":1520},{"id":1621,"depth":846,"text":1622},{"id":1708,"depth":833,"text":1709},{"id":2273,"depth":833,"text":267,"children":4255},[4256,4257,4258,4259,4260,4261,4262,4263],{"id":2279,"depth":846,"text":688},{"id":2344,"depth":846,"text":2345},{"id":1790,"depth":846,"text":639},{"id":2903,"depth":846,"text":101},{"id":3443,"depth":846,"text":3444},{"id":3727,"depth":846,"text":3728},{"id":3748,"depth":846,"text":1916},{"id":3979,"depth":846,"text":3556},{"id":4073,"depth":833,"text":234},{"id":4169,"depth":833,"text":4170},{"id":4215,"depth":833,"text":4216},"Turns a Nuxt app into an iOS and Android app with native tab bars, deep links and sign-in.","md",null,{},{"title":173},{"title":362,"description":4267},"HZ2__iYSkFJSwdrJBL5bCDqdog7QIfrR_7Vq267cfLY",[4275,4277],{"title":358,"path":359,"stem":360,"description":4276,"children":-1},"Lets modules add cards to a dashboard and tabs to a detail page that your app or another module owns.",{"title":368,"path":369,"stem":370,"description":4278,"children":-1},"Add the native projects, test the app on a phone against your own machine and prepare a release.",1794503146920]