[{"data":1,"prerenderedAt":3220},["ShallowReactive",2],{"navigation_docs":3,"-modules-interface-menu":587,"-modules-interface-menu-surround":3215},[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":354,"body":589,"description":3209,"extension":3210,"links":3211,"meta":3212,"navigation":900,"path":355,"seo":3213,"stem":356,"__hash__":3214},"docs\u002F3.modules\u002F4.interface\u002F3.menu.md",{"type":590,"value":591,"toc":3189},"minimark",[592,596,617,622,669,673,705,709,712,1023,1039,1043,1050,1094,1125,1230,1246,1250,1256,1346,1349,1387,1390,1394,1409,1574,1596,1603,1606,1802,1882,1890,1894,1908,2011,2015,2021,2033,2204,2214,2405,2616,2636,2650,2654,2659,2766,2782,2785,2790,2893,2898,2902,2922,3009,3012,3153,3156,3164,3168,3185],[593,594,595],"p",{},"Menu lets any module add a link to your app's navigation. Install Events and its pages appear in the admin sidebar.\nInstall Auth and a sign-out item appears in the account menu. Neither module imports the other. Use it for\nheaders, sidebars and account menus that modules should be able to fill. For a list of links only your app sets, a\nplain array in a component is enough.",[593,597,598,599,603,604,607,608,611,612,616],{},"The package is ",[600,601,602],"code",{},"@frigear-nu\u002Fmenu",". Each menu has a name, such as ",[600,605,606],{},"main"," or ",[600,609,610],{},"admin.nav",". Items come from modules, from\nNuxt Content or from both, and your app reads the merged list. Menu is one of the\n",[613,614,615],"a",{"href":87},"registries"," modules add to. It only returns data, so your app draws the menu its own way.",[618,619,621],"h2",{"id":620},"what-you-get","What you get",[623,624,625,640,653,659],"ul",{},[626,627,628,631,632,635,636,639],"li",{},[629,630,344],"strong",{}," (on by default): ",[600,633,634],{},"useMenu('main')"," in the app and ",[600,637,638],{},"useMenu(event, 'main')"," on the server\nreturn the merged, sorted items.",[626,641,642,631,645,648,649,652],{},[629,643,644],{},"Module helpers",[600,646,647],{},"extendMenu"," and ",[600,650,651],{},"registerMenuSource"," add items from a module.",[626,654,655,658],{},[629,656,657],{},"Content menus"," (opt-in): items read from a Nuxt Content collection, such as the website's navigation.",[626,660,661,664,665,668],{},[629,662,663],{},"Translated labels"," (opt-in, with ",[600,666,667],{},"@nuxtjs\u002Fi18n","): items carry i18n keys.",[670,671],"module-runtime",{":client":672,":server":672},"true",[674,675,676,688,694],"note",{},[593,677,678,681,682,687],{},[629,679,680],{},"Installed for you:"," ",[613,683,684],{"href":382},[600,685,686],{},"@frigear-nu\u002Fmodule-kit",".",[593,689,690,693],{},[629,691,692],{},"You add:"," nothing else.",[593,695,696,681,699,702,703,687],{},[629,697,698],{},"Optional:",[600,700,701],{},"@nuxt\u002Fcontent"," (required for a menu that reads content) and ",[600,704,667],{},[618,706,708],{"id":707},"quick-setup","Quick setup",[593,710,711],{},"Most modules declare Menu as an optional dependency; Admin installs it. Install it when your app should draw their\nitems.",[713,714,715,720,745,749,813,817],"steps",{},[716,717,719],"h3",{"id":718},"install-menu","Install Menu",[721,722,727],"pre",{"className":723,"code":724,"language":725,"meta":726,"style":726},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fmenu\n","bash","",[600,728,729],{"__ignoreMap":726},[730,731,734,738,742],"span",{"class":732,"line":733},"line",1,[730,735,737],{"class":736},"sBMFI","pnpm",[730,739,741],{"class":740},"sfazB"," add",[730,743,744],{"class":740}," @frigear-nu\u002Fmenu\n",[716,746,748],{"id":747},"add-it-to-nuxtconfigts","Add it to nuxt.config.ts",[721,750,755],{"className":751,"code":752,"filename":753,"language":754,"meta":726,"style":726},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@frigear-nu\u002Fmenu'],\n})\n","nuxt.config.ts","ts",[600,756,757,778,804],{"__ignoreMap":726},[730,758,759,763,766,770,774],{"class":732,"line":733},[730,760,762],{"class":761},"s7zQu","export",[730,764,765],{"class":761}," default",[730,767,769],{"class":768},"s2Zo4"," defineNuxtConfig",[730,771,773],{"class":772},"sTEyZ","(",[730,775,777],{"class":776},"sMK4o","{\n",[730,779,781,785,788,791,794,796,798,801],{"class":732,"line":780},2,[730,782,784],{"class":783},"swJcz","  modules",[730,786,787],{"class":776},":",[730,789,790],{"class":772}," [",[730,792,793],{"class":776},"'",[730,795,602],{"class":740},[730,797,793],{"class":776},[730,799,800],{"class":772},"]",[730,802,803],{"class":776},",\n",[730,805,807,810],{"class":732,"line":806},3,[730,808,809],{"class":776},"}",[730,811,812],{"class":772},")\n",[716,814,816],{"id":815},"draw-a-menu","Draw a menu",[721,818,822],{"className":819,"code":820,"language":821,"meta":726,"style":726},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nconst { data: items } = useMenu('main')\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cnav>\n    \u003CNuxtLink v-for=\"item in items\" :key=\"item.id\" :to=\"item.to\">\n      {{ item.label }}\n    \u003C\u002FNuxtLink>\n  \u003C\u002Fnav>\n\u003C\u002Ftemplate>\n","vue",[600,823,824,852,886,895,902,912,923,988,994,1004,1014],{"__ignoreMap":726},[730,825,826,829,832,836,839,842,845,847,849],{"class":732,"line":733},[730,827,828],{"class":776},"\u003C",[730,830,831],{"class":783},"script",[730,833,835],{"class":834},"spNyl"," setup",[730,837,838],{"class":834}," lang",[730,840,841],{"class":776},"=",[730,843,844],{"class":776},"\"",[730,846,754],{"class":740},[730,848,844],{"class":776},[730,850,851],{"class":776},">\n",[730,853,854,857,860,863,865,868,870,873,876,878,880,882,884],{"class":732,"line":780},[730,855,856],{"class":834},"const",[730,858,859],{"class":776}," {",[730,861,862],{"class":783}," data",[730,864,787],{"class":776},[730,866,867],{"class":772}," items ",[730,869,809],{"class":776},[730,871,872],{"class":776}," =",[730,874,875],{"class":768}," useMenu",[730,877,773],{"class":772},[730,879,793],{"class":776},[730,881,606],{"class":740},[730,883,793],{"class":776},[730,885,812],{"class":772},[730,887,888,891,893],{"class":732,"line":806},[730,889,890],{"class":776},"\u003C\u002F",[730,892,831],{"class":783},[730,894,851],{"class":776},[730,896,898],{"class":732,"line":897},4,[730,899,901],{"emptyLinePlaceholder":900},true,"\n",[730,903,905,907,910],{"class":732,"line":904},5,[730,906,828],{"class":776},[730,908,909],{"class":783},"template",[730,911,851],{"class":776},[730,913,915,918,921],{"class":732,"line":914},6,[730,916,917],{"class":776},"  \u003C",[730,919,920],{"class":783},"nav",[730,922,851],{"class":776},[730,924,926,929,932,935,937,939,942,945,948,950,953,956,958,960,962,964,967,969,971,974,976,978,980,982,984,986],{"class":732,"line":925},7,[730,927,928],{"class":776},"    \u003C",[730,930,931],{"class":783},"NuxtLink",[730,933,934],{"class":761}," v-for",[730,936,841],{"class":776},[730,938,844],{"class":776},[730,940,941],{"class":772},"item",[730,943,944],{"class":776}," in ",[730,946,947],{"class":772},"items",[730,949,844],{"class":776},[730,951,952],{"class":776}," :",[730,954,955],{"class":834},"key",[730,957,841],{"class":776},[730,959,844],{"class":776},[730,961,941],{"class":772},[730,963,687],{"class":776},[730,965,966],{"class":772},"id",[730,968,844],{"class":776},[730,970,952],{"class":776},[730,972,973],{"class":834},"to",[730,975,841],{"class":776},[730,977,844],{"class":776},[730,979,941],{"class":772},[730,981,687],{"class":776},[730,983,973],{"class":772},[730,985,844],{"class":776},[730,987,851],{"class":776},[730,989,991],{"class":732,"line":990},8,[730,992,993],{"class":772},"      {{ item.label }}\n",[730,995,997,1000,1002],{"class":732,"line":996},9,[730,998,999],{"class":776},"    \u003C\u002F",[730,1001,931],{"class":783},[730,1003,851],{"class":776},[730,1005,1007,1010,1012],{"class":732,"line":1006},10,[730,1008,1009],{"class":776},"  \u003C\u002F",[730,1011,920],{"class":783},[730,1013,851],{"class":776},[730,1015,1017,1019,1021],{"class":732,"line":1016},11,[730,1018,890],{"class":776},[730,1020,909],{"class":783},[730,1022,851],{"class":776},[1024,1025,1028,1031,1032,1035,1036,687],"callout",{"color":1026,"icon":1027},"success","i-lucide-check",[629,1029,1030],{},"What you should see:"," after a module calls ",[600,1033,1034],{},"extendMenu(nuxt, 'main', …)",", its link appears in your ",[600,1037,1038],{},"\u003Cnav>",[618,1040,1042],{"id":1041},"options","Options",[593,1044,1045,1046,1049],{},"Options go under the ",[600,1047,1048],{},"menus"," key.",[1051,1052,1053,1072],"table",{},[1054,1055,1056],"thead",{},[1057,1058,1059,1063,1066,1069],"tr",{},[1060,1061,1062],"th",{},"Option",[1060,1064,1065],{},"Type",[1060,1067,1068],{},"Default",[1060,1070,1071],{},"Purpose",[1073,1074,1075],"tbody",{},[1057,1076,1077,1083,1088,1091],{},[1078,1079,1080],"td",{},[600,1081,1082],{},"content.\u003Cmenu>",[1078,1084,1085],{},[600,1086,1087],{},"boolean | { collection?: string, field?: string }",[1078,1089,1090],{},"none",[1078,1092,1093],{},"Reads that menu's items from Nuxt Content.",[593,1095,1096,681,1100,1102,1103,1106,1107,1110,1111,1114,1115,607,1118,1121,1122,1124],{},[629,1097,1098,687],{},[600,1099,1082],{},[600,1101,672],{}," reads the ",[600,1104,1105],{},"navigation"," field of the ",[600,1108,1109],{},"config"," collection, as the\n",[613,1112,1113],{"href":425},"base layer"," defines it. An object picks another ",[600,1116,1117],{},"collection",[600,1119,1120],{},"field",". Without\n",[600,1123,701],{}," installed, the build fails.",[721,1126,1128],{"className":751,"code":1127,"filename":753,"language":754,"meta":726,"style":726},"export default defineNuxtConfig({\n  menus: {\n    content: {\n      main: true,\n      dashboard: { collection: 'dashboard', field: 'tiles' },\n    },\n  },\n})\n",[600,1129,1130,1142,1152,1161,1174,1214,1219,1224],{"__ignoreMap":726},[730,1131,1132,1134,1136,1138,1140],{"class":732,"line":733},[730,1133,762],{"class":761},[730,1135,765],{"class":761},[730,1137,769],{"class":768},[730,1139,773],{"class":772},[730,1141,777],{"class":776},[730,1143,1144,1147,1149],{"class":732,"line":780},[730,1145,1146],{"class":783},"  menus",[730,1148,787],{"class":776},[730,1150,1151],{"class":776}," {\n",[730,1153,1154,1157,1159],{"class":732,"line":806},[730,1155,1156],{"class":783},"    content",[730,1158,787],{"class":776},[730,1160,1151],{"class":776},[730,1162,1163,1166,1168,1172],{"class":732,"line":897},[730,1164,1165],{"class":783},"      main",[730,1167,787],{"class":776},[730,1169,1171],{"class":1170},"sfNiH"," true",[730,1173,803],{"class":776},[730,1175,1176,1179,1181,1183,1186,1188,1191,1194,1196,1199,1202,1204,1206,1209,1211],{"class":732,"line":904},[730,1177,1178],{"class":783},"      dashboard",[730,1180,787],{"class":776},[730,1182,859],{"class":776},[730,1184,1185],{"class":783}," collection",[730,1187,787],{"class":776},[730,1189,1190],{"class":776}," '",[730,1192,1193],{"class":740},"dashboard",[730,1195,793],{"class":776},[730,1197,1198],{"class":776},",",[730,1200,1201],{"class":783}," field",[730,1203,787],{"class":776},[730,1205,1190],{"class":776},[730,1207,1208],{"class":740},"tiles",[730,1210,793],{"class":776},[730,1212,1213],{"class":776}," },\n",[730,1215,1216],{"class":732,"line":914},[730,1217,1218],{"class":776},"    },\n",[730,1220,1221],{"class":732,"line":925},[730,1222,1223],{"class":776},"  },\n",[730,1225,1226,1228],{"class":732,"line":990},[730,1227,809],{"class":776},[730,1229,812],{"class":772},[593,1231,1232,1233,648,1235,1238,1239,1241,1242,1245],{},"With ",[600,1234,667],{},[600,1236,1237],{},"locales",", content items come from the per-locale collection: ",[600,1240,1109],{}," becomes ",[600,1243,1244],{},"config_en",". The\nbase layer uses the same convention.",[618,1247,1249],{"id":1248},"server","Server",[593,1251,1252,1255],{},[600,1253,1254],{},"useMenu(event, path)"," returns a menu in a server route. It is auto-imported in server code.",[721,1257,1259],{"className":751,"code":1258,"language":754,"meta":726,"style":726},"useMenu(event: H3Event, path: string, options?: { locale?: string }): Promise\u003CMenuItem[]>\n\nexport default defineEventHandler(event => useMenu(event, 'dashboard.*'))\n",[600,1260,1261,1307,1311],{"__ignoreMap":726},[730,1262,1263,1266,1269,1271,1274,1276,1279,1282,1284,1287,1289,1292,1294,1297,1300,1302,1305],{"class":732,"line":733},[730,1264,1265],{"class":768},"useMenu",[730,1267,1268],{"class":772},"(event: H3Event",[730,1270,1198],{"class":776},[730,1272,1273],{"class":772}," path: string",[730,1275,1198],{"class":776},[730,1277,1278],{"class":772}," options",[730,1280,1281],{"class":776},"?:",[730,1283,859],{"class":776},[730,1285,1286],{"class":772}," locale?",[730,1288,787],{"class":776},[730,1290,1291],{"class":772}," string ",[730,1293,809],{"class":776},[730,1295,1296],{"class":772},"): ",[730,1298,1299],{"class":736},"Promise",[730,1301,828],{"class":776},[730,1303,1304],{"class":772},"MenuItem[]",[730,1306,851],{"class":776},[730,1308,1309],{"class":732,"line":780},[730,1310,901],{"emptyLinePlaceholder":900},[730,1312,1313,1315,1317,1320,1322,1326,1329,1331,1334,1336,1338,1341,1343],{"class":732,"line":806},[730,1314,762],{"class":761},[730,1316,765],{"class":761},[730,1318,1319],{"class":768}," defineEventHandler",[730,1321,773],{"class":772},[730,1323,1325],{"class":1324},"sHdIc","event",[730,1327,1328],{"class":834}," =>",[730,1330,875],{"class":768},[730,1332,1333],{"class":772},"(event",[730,1335,1198],{"class":776},[730,1337,1190],{"class":776},[730,1339,1340],{"class":740},"dashboard.*",[730,1342,793],{"class":776},[730,1344,1345],{"class":772},"))\n",[593,1347,1348],{},"It merges the same items as the app composable, and paths work the same way. It differs in three ways:",[623,1350,1351,1364,1373],{},[626,1352,1353,1356,1357,648,1360,1363],{},[629,1354,1355],{},"Labels"," are not translated: ",[600,1358,1359],{},"labelKey",[600,1361,1362],{},"descriptionKey"," are returned untouched.",[626,1365,1366,1369,1370,687],{},[629,1367,1368],{},"Content"," comes from the collection without a locale, unless you pass ",[600,1371,1372],{},"{ locale }",[626,1374,1375,1378,1379,1382,1383,1386],{},[629,1376,1377],{},"Runtime menu files"," run once per server process, not per request. So they should read runtime config, not\nrequest data, and import ",[600,1380,1381],{},"extendMenuItem"," from ",[600,1384,1385],{},"@frigear-nu\u002Fmenu\u002Futils"," explicitly.",[618,1388,267],{"id":1389},"app",[716,1391,1393],{"id":1392},"read-a-menu","Read a menu",[593,1395,1396,1399,1400,1408],{},[600,1397,1398],{},"useMenu(path)"," returns the items of a menu, in the shape of\n",[613,1401,1405],{"href":1402,"rel":1403},"https:\u002F\u002Fnuxt.com\u002Fdocs\u002F4.x\u002Fapi\u002Fcomposables\u002Fuse-async-data",[1404],"nofollow",[600,1406,1407],{},"useAsyncData",". It is auto-imported and re-evaluates when\nthe locale changes.",[721,1410,1412],{"className":751,"code":1411,"language":754,"meta":726,"style":726},"useMenu(path: string): AsyncData\u003CMenuItem[], NuxtError | undefined> \u002F\u002F { data, pending, error, refresh }\n\nconst { data: items } = useMenu('main') \u002F\u002F the root group of `main`\nconst { data: more } = useMenu('dashboard.more') \u002F\u002F group `more` of `dashboard`\nconst { data: all } = useMenu('dashboard.*') \u002F\u002F every group of `dashboard`, flattened\nconst { data: tree } = useMenu('dashboard.account.*') \u002F\u002F `account` and groups nested under it, not siblings\n",[600,1413,1414,1440,1444,1476,1509,1541],{"__ignoreMap":726},[730,1415,1416,1418,1421,1423,1425,1427,1430,1433,1436],{"class":732,"line":733},[730,1417,1265],{"class":768},[730,1419,1420],{"class":772},"(path: string): AsyncData",[730,1422,828],{"class":776},[730,1424,1304],{"class":772},[730,1426,1198],{"class":776},[730,1428,1429],{"class":772}," NuxtError ",[730,1431,1432],{"class":776},"|",[730,1434,1435],{"class":776}," undefined>",[730,1437,1439],{"class":1438},"sHwdD"," \u002F\u002F { data, pending, error, refresh }\n",[730,1441,1442],{"class":732,"line":780},[730,1443,901],{"emptyLinePlaceholder":900},[730,1445,1446,1448,1450,1452,1454,1456,1458,1460,1462,1464,1466,1468,1470,1473],{"class":732,"line":806},[730,1447,856],{"class":834},[730,1449,859],{"class":776},[730,1451,862],{"class":783},[730,1453,787],{"class":776},[730,1455,867],{"class":772},[730,1457,809],{"class":776},[730,1459,872],{"class":776},[730,1461,875],{"class":768},[730,1463,773],{"class":772},[730,1465,793],{"class":776},[730,1467,606],{"class":740},[730,1469,793],{"class":776},[730,1471,1472],{"class":772},") ",[730,1474,1475],{"class":1438},"\u002F\u002F the root group of `main`\n",[730,1477,1478,1480,1482,1484,1486,1489,1491,1493,1495,1497,1499,1502,1504,1506],{"class":732,"line":897},[730,1479,856],{"class":834},[730,1481,859],{"class":776},[730,1483,862],{"class":783},[730,1485,787],{"class":776},[730,1487,1488],{"class":772}," more ",[730,1490,809],{"class":776},[730,1492,872],{"class":776},[730,1494,875],{"class":768},[730,1496,773],{"class":772},[730,1498,793],{"class":776},[730,1500,1501],{"class":740},"dashboard.more",[730,1503,793],{"class":776},[730,1505,1472],{"class":772},[730,1507,1508],{"class":1438},"\u002F\u002F group `more` of `dashboard`\n",[730,1510,1511,1513,1515,1517,1519,1522,1524,1526,1528,1530,1532,1534,1536,1538],{"class":732,"line":904},[730,1512,856],{"class":834},[730,1514,859],{"class":776},[730,1516,862],{"class":783},[730,1518,787],{"class":776},[730,1520,1521],{"class":772}," all ",[730,1523,809],{"class":776},[730,1525,872],{"class":776},[730,1527,875],{"class":768},[730,1529,773],{"class":772},[730,1531,793],{"class":776},[730,1533,1340],{"class":740},[730,1535,793],{"class":776},[730,1537,1472],{"class":772},[730,1539,1540],{"class":1438},"\u002F\u002F every group of `dashboard`, flattened\n",[730,1542,1543,1545,1547,1549,1551,1554,1556,1558,1560,1562,1564,1567,1569,1571],{"class":732,"line":914},[730,1544,856],{"class":834},[730,1546,859],{"class":776},[730,1548,862],{"class":783},[730,1550,787],{"class":776},[730,1552,1553],{"class":772}," tree ",[730,1555,809],{"class":776},[730,1557,872],{"class":776},[730,1559,875],{"class":768},[730,1561,773],{"class":772},[730,1563,793],{"class":776},[730,1565,1566],{"class":740},"dashboard.account.*",[730,1568,793],{"class":776},[730,1570,1472],{"class":772},[730,1572,1573],{"class":1438},"\u002F\u002F `account` and groups nested under it, not siblings\n",[593,1575,1576,1577,1580,1581,1584,1585,1587,1588,1591,1592,1595],{},"A path is split on its ",[629,1578,1579],{},"first dot"," only: ",[600,1582,1583],{},"a.b.c"," is menu ",[600,1586,613],{},", group ",[600,1589,1590],{},"b.c",". A path without a dot is the menu's root\ngroup. A trailing ",[600,1593,1594],{},".*"," is a wildcard, and works only when reading.",[593,1597,1598,1599,1602],{},"Items are sorted by ",[600,1600,1601],{},"order",", lowest first, and items without one come last. Ties keep their order: content items\nfirst, then module items in the order they were added.",[716,1604,1605],{"id":947},"Items",[721,1607,1609],{"className":751,"code":1608,"language":754,"meta":726,"style":726},"type MenuItem = {\n  id?: string \u002F\u002F stable key; default: `to`, else a slug of `label`\n  label: string\n  labelKey?: string \u002F\u002F i18n key; falls back to `label`\n  description?: string\n  descriptionKey?: string\n  icon?: string\n  to?: string\n  external?: boolean\n  method?: 'post' \u002F\u002F an action, not a link: the view posts to `to`, then reloads the home page\n  permission?: string \u002F\u002F `resource:action`: shown only to viewers who hold it\n  tags?: string[]\n  order?: number \u002F\u002F lower first\n  group?: string \u002F\u002F set from the registration path; an explicit value wins\n  meta?: Record\u003Cstring, unknown>\n}\n",[600,1610,1611,1623,1636,1646,1658,1667,1676,1685,1694,1704,1721,1733,1746,1760,1773,1796],{"__ignoreMap":726},[730,1612,1613,1616,1619,1621],{"class":732,"line":733},[730,1614,1615],{"class":834},"type",[730,1617,1618],{"class":736}," MenuItem",[730,1620,872],{"class":776},[730,1622,1151],{"class":776},[730,1624,1625,1628,1630,1633],{"class":732,"line":780},[730,1626,1627],{"class":783},"  id",[730,1629,1281],{"class":776},[730,1631,1632],{"class":736}," string",[730,1634,1635],{"class":1438}," \u002F\u002F stable key; default: `to`, else a slug of `label`\n",[730,1637,1638,1641,1643],{"class":732,"line":806},[730,1639,1640],{"class":783},"  label",[730,1642,787],{"class":776},[730,1644,1645],{"class":736}," string\n",[730,1647,1648,1651,1653,1655],{"class":732,"line":897},[730,1649,1650],{"class":783},"  labelKey",[730,1652,1281],{"class":776},[730,1654,1632],{"class":736},[730,1656,1657],{"class":1438}," \u002F\u002F i18n key; falls back to `label`\n",[730,1659,1660,1663,1665],{"class":732,"line":904},[730,1661,1662],{"class":783},"  description",[730,1664,1281],{"class":776},[730,1666,1645],{"class":736},[730,1668,1669,1672,1674],{"class":732,"line":914},[730,1670,1671],{"class":783},"  descriptionKey",[730,1673,1281],{"class":776},[730,1675,1645],{"class":736},[730,1677,1678,1681,1683],{"class":732,"line":925},[730,1679,1680],{"class":783},"  icon",[730,1682,1281],{"class":776},[730,1684,1645],{"class":736},[730,1686,1687,1690,1692],{"class":732,"line":990},[730,1688,1689],{"class":783},"  to",[730,1691,1281],{"class":776},[730,1693,1645],{"class":736},[730,1695,1696,1699,1701],{"class":732,"line":996},[730,1697,1698],{"class":783},"  external",[730,1700,1281],{"class":776},[730,1702,1703],{"class":736}," boolean\n",[730,1705,1706,1709,1711,1713,1716,1718],{"class":732,"line":1006},[730,1707,1708],{"class":783},"  method",[730,1710,1281],{"class":776},[730,1712,1190],{"class":776},[730,1714,1715],{"class":740},"post",[730,1717,793],{"class":776},[730,1719,1720],{"class":1438}," \u002F\u002F an action, not a link: the view posts to `to`, then reloads the home page\n",[730,1722,1723,1726,1728,1730],{"class":732,"line":1016},[730,1724,1725],{"class":783},"  permission",[730,1727,1281],{"class":776},[730,1729,1632],{"class":736},[730,1731,1732],{"class":1438}," \u002F\u002F `resource:action`: shown only to viewers who hold it\n",[730,1734,1736,1739,1741,1743],{"class":732,"line":1735},12,[730,1737,1738],{"class":783},"  tags",[730,1740,1281],{"class":776},[730,1742,1632],{"class":736},[730,1744,1745],{"class":772},"[]\n",[730,1747,1749,1752,1754,1757],{"class":732,"line":1748},13,[730,1750,1751],{"class":783},"  order",[730,1753,1281],{"class":776},[730,1755,1756],{"class":736}," number",[730,1758,1759],{"class":1438}," \u002F\u002F lower first\n",[730,1761,1763,1766,1768,1770],{"class":732,"line":1762},14,[730,1764,1765],{"class":783},"  group",[730,1767,1281],{"class":776},[730,1769,1632],{"class":736},[730,1771,1772],{"class":1438}," \u002F\u002F set from the registration path; an explicit value wins\n",[730,1774,1776,1779,1781,1784,1786,1789,1791,1794],{"class":732,"line":1775},15,[730,1777,1778],{"class":783},"  meta",[730,1780,1281],{"class":776},[730,1782,1783],{"class":736}," Record",[730,1785,828],{"class":776},[730,1787,1788],{"class":736},"string",[730,1790,1198],{"class":776},[730,1792,1793],{"class":736}," unknown",[730,1795,851],{"class":776},[730,1797,1799],{"class":732,"line":1798},16,[730,1800,1801],{"class":776},"}\n",[1051,1803,1804,1814],{},[1054,1805,1806],{},[1057,1807,1808,1811],{},[1060,1809,1810],{},"Field",[1060,1812,1813],{},"Notes",[1073,1815,1816,1829,1848,1868],{},[1057,1817,1818,1822],{},[1078,1819,1820],{},[600,1821,966],{},[1078,1823,1824,1825,1828],{},"Derived from the untranslated ",[600,1826,1827],{},"label",", so it is the same in every locale. A duplicate in one batch warns in development.",[1057,1830,1831,1839],{},[1078,1832,1833,1835,1836],{},[600,1834,1827],{},", ",[600,1837,1838],{},"description",[1078,1840,1841,1842,1844,1845,1847],{},"The same shape as the ",[600,1843,1105],{}," entries of the base layer's ",[600,1846,1109],{}," collection.",[1057,1849,1850,1855],{},[1078,1851,1852],{},[600,1853,1854],{},"method",[1078,1856,1857,1860,1861,1864,1865,1867],{},[600,1858,1859],{},"AccountMenu"," sends ",[600,1862,1863],{},"POST"," to ",[600,1866,973],{},", then reloads the home page. Auth's sign-out item uses it.",[1057,1869,1870,1876],{},[1078,1871,1872,1835,1874],{},[600,1873,1359],{},[600,1875,1362],{},[1078,1877,1878,1879,1881],{},"Translated in the active locale. Without ",[600,1880,667],{},", or without a message, the plain text is used.",[593,1883,1884,648,1886,1889],{},[600,1885,1838],{},[600,1887,1888],{},"icon"," are optional: your app may draw them or not.",[716,1891,1893],{"id":1892},"translate-items","Translate items",[593,1895,1896,1897,1900,1901,1904,1905,1907],{},"Items from code carry i18n keys. Ship the messages in your module's ",[600,1898,1899],{},"runtime\u002Fi18n\u002Flang\u002F*.json"," and register them with\n",[600,1902,1903],{},"registerLocales"," (see ",[613,1906,381],{"href":396},"). Content items use their per-locale collection\ninstead.",[721,1909,1911],{"className":751,"code":1910,"language":754,"meta":726,"style":726},"extendMenuItem('account.dropdown', {\n  id: 'logout',\n  label: 'Logout',\n  labelKey: 'account.menu.logout.label',\n  description: 'Sign out of your account.',\n  descriptionKey: 'account.menu.logout.description',\n})\n",[600,1912,1913,1930,1945,1960,1975,1990,2005],{"__ignoreMap":726},[730,1914,1915,1917,1919,1921,1924,1926,1928],{"class":732,"line":733},[730,1916,1381],{"class":768},[730,1918,773],{"class":772},[730,1920,793],{"class":776},[730,1922,1923],{"class":740},"account.dropdown",[730,1925,793],{"class":776},[730,1927,1198],{"class":776},[730,1929,1151],{"class":776},[730,1931,1932,1934,1936,1938,1941,1943],{"class":732,"line":780},[730,1933,1627],{"class":783},[730,1935,787],{"class":776},[730,1937,1190],{"class":776},[730,1939,1940],{"class":740},"logout",[730,1942,793],{"class":776},[730,1944,803],{"class":776},[730,1946,1947,1949,1951,1953,1956,1958],{"class":732,"line":806},[730,1948,1640],{"class":783},[730,1950,787],{"class":776},[730,1952,1190],{"class":776},[730,1954,1955],{"class":740},"Logout",[730,1957,793],{"class":776},[730,1959,803],{"class":776},[730,1961,1962,1964,1966,1968,1971,1973],{"class":732,"line":897},[730,1963,1650],{"class":783},[730,1965,787],{"class":776},[730,1967,1190],{"class":776},[730,1969,1970],{"class":740},"account.menu.logout.label",[730,1972,793],{"class":776},[730,1974,803],{"class":776},[730,1976,1977,1979,1981,1983,1986,1988],{"class":732,"line":904},[730,1978,1662],{"class":783},[730,1980,787],{"class":776},[730,1982,1190],{"class":776},[730,1984,1985],{"class":740},"Sign out of your account.",[730,1987,793],{"class":776},[730,1989,803],{"class":776},[730,1991,1992,1994,1996,1998,2001,2003],{"class":732,"line":914},[730,1993,1671],{"class":783},[730,1995,787],{"class":776},[730,1997,1190],{"class":776},[730,1999,2000],{"class":740},"account.menu.logout.description",[730,2002,793],{"class":776},[730,2004,803],{"class":776},[730,2006,2007,2009],{"class":732,"line":925},[730,2008,809],{"class":776},[730,2010,812],{"class":772},[716,2012,2014],{"id":2013},"add-items-from-a-module","Add items from a module",[593,2016,2017,2018,687],{},"A module adds items in one of two ways, and the order between modules does not matter: items are merged once every\nmodule has set up. This is the menu half of the ",[613,2019,2020],{"href":73},"extension points",[593,2022,2023,2026,2027,2029,2030,787],{},[629,2024,2025],{},"Items known at build time."," Call ",[600,2028,647],{}," in the module's ",[600,2031,2032],{},"setup()",[721,2034,2036],{"className":751,"code":2035,"language":754,"meta":726,"style":726},"import { extendMenu } from '@frigear-nu\u002Fmenu\u002Futils'\n\nexport default defineNuxtModule({\n  meta: { name: '@frigear-nu\u002Fexample' },\n  setup(options, nuxt) {\n    extendMenu(nuxt, 'dashboard.more', [\n      { label: 'Billing', description: 'Manage your subscription', to: '\u002Fbilling' },\n    ])\n  },\n})\n",[600,2037,2038,2061,2065,2078,2100,2119,2142,2189,2194,2198],{"__ignoreMap":726},[730,2039,2040,2043,2045,2048,2051,2054,2056,2058],{"class":732,"line":733},[730,2041,2042],{"class":761},"import",[730,2044,859],{"class":776},[730,2046,2047],{"class":772}," extendMenu",[730,2049,2050],{"class":776}," }",[730,2052,2053],{"class":761}," from",[730,2055,1190],{"class":776},[730,2057,1385],{"class":740},[730,2059,2060],{"class":776},"'\n",[730,2062,2063],{"class":732,"line":780},[730,2064,901],{"emptyLinePlaceholder":900},[730,2066,2067,2069,2071,2074,2076],{"class":732,"line":806},[730,2068,762],{"class":761},[730,2070,765],{"class":761},[730,2072,2073],{"class":768}," defineNuxtModule",[730,2075,773],{"class":772},[730,2077,777],{"class":776},[730,2079,2080,2082,2084,2086,2089,2091,2093,2096,2098],{"class":732,"line":897},[730,2081,1778],{"class":783},[730,2083,787],{"class":776},[730,2085,859],{"class":776},[730,2087,2088],{"class":783}," name",[730,2090,787],{"class":776},[730,2092,1190],{"class":776},[730,2094,2095],{"class":740},"@frigear-nu\u002Fexample",[730,2097,793],{"class":776},[730,2099,1213],{"class":776},[730,2101,2102,2105,2107,2109,2111,2114,2117],{"class":732,"line":904},[730,2103,2104],{"class":783},"  setup",[730,2106,773],{"class":776},[730,2108,1041],{"class":1324},[730,2110,1198],{"class":776},[730,2112,2113],{"class":1324}," nuxt",[730,2115,2116],{"class":776},")",[730,2118,1151],{"class":776},[730,2120,2121,2124,2126,2129,2131,2133,2135,2137,2139],{"class":732,"line":914},[730,2122,2123],{"class":768},"    extendMenu",[730,2125,773],{"class":783},[730,2127,2128],{"class":772},"nuxt",[730,2130,1198],{"class":776},[730,2132,1190],{"class":776},[730,2134,1501],{"class":740},[730,2136,793],{"class":776},[730,2138,1198],{"class":776},[730,2140,2141],{"class":783}," [\n",[730,2143,2144,2147,2150,2152,2154,2157,2159,2161,2164,2166,2168,2171,2173,2175,2178,2180,2182,2185,2187],{"class":732,"line":925},[730,2145,2146],{"class":776},"      {",[730,2148,2149],{"class":783}," label",[730,2151,787],{"class":776},[730,2153,1190],{"class":776},[730,2155,2156],{"class":740},"Billing",[730,2158,793],{"class":776},[730,2160,1198],{"class":776},[730,2162,2163],{"class":783}," description",[730,2165,787],{"class":776},[730,2167,1190],{"class":776},[730,2169,2170],{"class":740},"Manage your subscription",[730,2172,793],{"class":776},[730,2174,1198],{"class":776},[730,2176,2177],{"class":783}," to",[730,2179,787],{"class":776},[730,2181,1190],{"class":776},[730,2183,2184],{"class":740},"\u002Fbilling",[730,2186,793],{"class":776},[730,2188,1213],{"class":776},[730,2190,2191],{"class":732,"line":990},[730,2192,2193],{"class":783},"    ])\n",[730,2195,2196],{"class":732,"line":996},[730,2197,1223],{"class":776},[730,2199,2200,2202],{"class":732,"line":1006},[730,2201,809],{"class":776},[730,2203,812],{"class":772},[593,2205,2206,2209,2210,2213],{},[629,2207,2208],{},"Items that need runtime context,"," such as ",[600,2211,2212],{},"useRuntimeConfig",". Register a runtime menu file:",[721,2215,2217],{"className":751,"code":2216,"language":754,"meta":726,"style":726},"import { createResolver, defineNuxtModule } from '@nuxt\u002Fkit'\nimport { registerMenuSource } from '@frigear-nu\u002Fmenu\u002Futils'\n\nexport default defineNuxtModule({\n  meta: { name: '@frigear-nu\u002Fexample' },\n  setup(options, nuxt) {\n    const resolver = createResolver(import.meta.url)\n    registerMenuSource(nuxt, { file: resolver.resolve('.\u002Fruntime\u002Fmenus'), menu: 'dashboard' })\n  },\n})\n",[600,2218,2219,2243,2262,2266,2278,2298,2314,2342,2395,2399],{"__ignoreMap":726},[730,2220,2221,2223,2225,2228,2230,2232,2234,2236,2238,2241],{"class":732,"line":733},[730,2222,2042],{"class":761},[730,2224,859],{"class":776},[730,2226,2227],{"class":772}," createResolver",[730,2229,1198],{"class":776},[730,2231,2073],{"class":772},[730,2233,2050],{"class":776},[730,2235,2053],{"class":761},[730,2237,1190],{"class":776},[730,2239,2240],{"class":740},"@nuxt\u002Fkit",[730,2242,2060],{"class":776},[730,2244,2245,2247,2249,2252,2254,2256,2258,2260],{"class":732,"line":780},[730,2246,2042],{"class":761},[730,2248,859],{"class":776},[730,2250,2251],{"class":772}," registerMenuSource",[730,2253,2050],{"class":776},[730,2255,2053],{"class":761},[730,2257,1190],{"class":776},[730,2259,1385],{"class":740},[730,2261,2060],{"class":776},[730,2263,2264],{"class":732,"line":806},[730,2265,901],{"emptyLinePlaceholder":900},[730,2267,2268,2270,2272,2274,2276],{"class":732,"line":897},[730,2269,762],{"class":761},[730,2271,765],{"class":761},[730,2273,2073],{"class":768},[730,2275,773],{"class":772},[730,2277,777],{"class":776},[730,2279,2280,2282,2284,2286,2288,2290,2292,2294,2296],{"class":732,"line":904},[730,2281,1778],{"class":783},[730,2283,787],{"class":776},[730,2285,859],{"class":776},[730,2287,2088],{"class":783},[730,2289,787],{"class":776},[730,2291,1190],{"class":776},[730,2293,2095],{"class":740},[730,2295,793],{"class":776},[730,2297,1213],{"class":776},[730,2299,2300,2302,2304,2306,2308,2310,2312],{"class":732,"line":914},[730,2301,2104],{"class":783},[730,2303,773],{"class":776},[730,2305,1041],{"class":1324},[730,2307,1198],{"class":776},[730,2309,2113],{"class":1324},[730,2311,2116],{"class":776},[730,2313,1151],{"class":776},[730,2315,2316,2319,2322,2324,2326,2328,2330,2332,2335,2337,2340],{"class":732,"line":925},[730,2317,2318],{"class":834},"    const",[730,2320,2321],{"class":772}," resolver",[730,2323,872],{"class":776},[730,2325,2227],{"class":768},[730,2327,773],{"class":783},[730,2329,2042],{"class":761},[730,2331,687],{"class":776},[730,2333,2334],{"class":772},"meta",[730,2336,687],{"class":776},[730,2338,2339],{"class":772},"url",[730,2341,812],{"class":783},[730,2343,2344,2347,2349,2351,2353,2355,2358,2360,2362,2364,2367,2369,2371,2374,2376,2378,2380,2383,2385,2387,2389,2391,2393],{"class":732,"line":990},[730,2345,2346],{"class":768},"    registerMenuSource",[730,2348,773],{"class":783},[730,2350,2128],{"class":772},[730,2352,1198],{"class":776},[730,2354,859],{"class":776},[730,2356,2357],{"class":783}," file",[730,2359,787],{"class":776},[730,2361,2321],{"class":772},[730,2363,687],{"class":776},[730,2365,2366],{"class":768},"resolve",[730,2368,773],{"class":783},[730,2370,793],{"class":776},[730,2372,2373],{"class":740},".\u002Fruntime\u002Fmenus",[730,2375,793],{"class":776},[730,2377,2116],{"class":783},[730,2379,1198],{"class":776},[730,2381,2382],{"class":783}," menu",[730,2384,787],{"class":776},[730,2386,1190],{"class":776},[730,2388,1193],{"class":740},[730,2390,793],{"class":776},[730,2392,2050],{"class":776},[730,2394,812],{"class":783},[730,2396,2397],{"class":732,"line":996},[730,2398,1223],{"class":776},[730,2400,2401,2403],{"class":732,"line":1006},[730,2402,809],{"class":776},[730,2404,812],{"class":772},[721,2406,2408],{"className":751,"code":2407,"language":754,"meta":726,"style":726},"\u002F\u002F runtime\u002Fmenus.ts\nimport { defineMenuSource, extendMenuItem } from '@frigear-nu\u002Fmenu\u002Futils'\n\nexport default defineMenuSource((items) => {\n  const config = useRuntimeConfig().public.example\n\n  \u002F\u002F Pushed into the `dashboard` menu's root group.\n  if (config?.enabled) items.push({ label: 'Example', to: '\u002Fexample' })\n\n  \u002F\u002F Pushed into a named group instead, created if missing.\n  extendMenuItem('dashboard.more', { label: 'Security', to: '\u002Fsecurity' })\n})\n",[600,2409,2410,2415,2439,2443,2463,2489,2493,2498,2556,2560,2565,2610],{"__ignoreMap":726},[730,2411,2412],{"class":732,"line":733},[730,2413,2414],{"class":1438},"\u002F\u002F runtime\u002Fmenus.ts\n",[730,2416,2417,2419,2421,2424,2426,2429,2431,2433,2435,2437],{"class":732,"line":780},[730,2418,2042],{"class":761},[730,2420,859],{"class":776},[730,2422,2423],{"class":772}," defineMenuSource",[730,2425,1198],{"class":776},[730,2427,2428],{"class":772}," extendMenuItem",[730,2430,2050],{"class":776},[730,2432,2053],{"class":761},[730,2434,1190],{"class":776},[730,2436,1385],{"class":740},[730,2438,2060],{"class":776},[730,2440,2441],{"class":732,"line":806},[730,2442,901],{"emptyLinePlaceholder":900},[730,2444,2445,2447,2449,2451,2453,2455,2457,2459,2461],{"class":732,"line":897},[730,2446,762],{"class":761},[730,2448,765],{"class":761},[730,2450,2423],{"class":768},[730,2452,773],{"class":772},[730,2454,773],{"class":776},[730,2456,947],{"class":1324},[730,2458,2116],{"class":776},[730,2460,1328],{"class":834},[730,2462,1151],{"class":776},[730,2464,2465,2468,2471,2473,2476,2479,2481,2484,2486],{"class":732,"line":904},[730,2466,2467],{"class":834},"  const",[730,2469,2470],{"class":772}," config",[730,2472,872],{"class":776},[730,2474,2475],{"class":768}," useRuntimeConfig",[730,2477,2478],{"class":783},"()",[730,2480,687],{"class":776},[730,2482,2483],{"class":772},"public",[730,2485,687],{"class":776},[730,2487,2488],{"class":772},"example\n",[730,2490,2491],{"class":732,"line":914},[730,2492,901],{"emptyLinePlaceholder":900},[730,2494,2495],{"class":732,"line":925},[730,2496,2497],{"class":1438},"  \u002F\u002F Pushed into the `dashboard` menu's root group.\n",[730,2499,2500,2503,2506,2508,2511,2514,2516,2518,2520,2523,2525,2528,2530,2532,2534,2537,2539,2541,2543,2545,2547,2550,2552,2554],{"class":732,"line":990},[730,2501,2502],{"class":761},"  if",[730,2504,2505],{"class":783}," (",[730,2507,1109],{"class":772},[730,2509,2510],{"class":776},"?.",[730,2512,2513],{"class":772},"enabled",[730,2515,1472],{"class":783},[730,2517,947],{"class":772},[730,2519,687],{"class":776},[730,2521,2522],{"class":768},"push",[730,2524,773],{"class":783},[730,2526,2527],{"class":776},"{",[730,2529,2149],{"class":783},[730,2531,787],{"class":776},[730,2533,1190],{"class":776},[730,2535,2536],{"class":740},"Example",[730,2538,793],{"class":776},[730,2540,1198],{"class":776},[730,2542,2177],{"class":783},[730,2544,787],{"class":776},[730,2546,1190],{"class":776},[730,2548,2549],{"class":740},"\u002Fexample",[730,2551,793],{"class":776},[730,2553,2050],{"class":776},[730,2555,812],{"class":783},[730,2557,2558],{"class":732,"line":996},[730,2559,901],{"emptyLinePlaceholder":900},[730,2561,2562],{"class":732,"line":1006},[730,2563,2564],{"class":1438},"  \u002F\u002F Pushed into a named group instead, created if missing.\n",[730,2566,2567,2570,2572,2574,2576,2578,2580,2582,2584,2586,2588,2591,2593,2595,2597,2599,2601,2604,2606,2608],{"class":732,"line":1016},[730,2568,2569],{"class":768},"  extendMenuItem",[730,2571,773],{"class":783},[730,2573,793],{"class":776},[730,2575,1501],{"class":740},[730,2577,793],{"class":776},[730,2579,1198],{"class":776},[730,2581,859],{"class":776},[730,2583,2149],{"class":783},[730,2585,787],{"class":776},[730,2587,1190],{"class":776},[730,2589,2590],{"class":740},"Security",[730,2592,793],{"class":776},[730,2594,1198],{"class":776},[730,2596,2177],{"class":783},[730,2598,787],{"class":776},[730,2600,1190],{"class":776},[730,2602,2603],{"class":740},"\u002Fsecurity",[730,2605,793],{"class":776},[730,2607,2050],{"class":776},[730,2609,812],{"class":783},[730,2611,2612,2614],{"class":732,"line":1735},[730,2613,809],{"class":776},[730,2615,812],{"class":772},[2617,2618,2619,2620,2622,2623,2626,2627,2629,2630,2632,2633,2635],"warning",{},"Call ",[600,2621,1381],{}," before the first ",[600,2624,2625],{},"await"," of the file. It finds the current app through the Nuxt context, which\nis lost after an ",[600,2628,2625],{},". It does not work in a module's ",[600,2631,2032],{},": use ",[600,2634,647],{}," there.",[593,2637,2638,2639,2642,2643,2645,2646,2649],{},"A module that should not depend on Menu registers its file with ",[600,2640,2641],{},"addOptionalMenuSource"," from\n",[613,2644,381],{"href":382},". It skips the registration when Menu is not installed. ",[600,2647,2648],{},"addMenuSource","\nregisters it always.",[716,2651,2653],{"id":2652},"utils","Utils",[593,2655,2656,2658],{},[600,2657,1385],{}," is framework-agnostic.",[1051,2660,2661,2673],{},[1054,2662,2663],{},[1057,2664,2665,2668,2671],{},[1060,2666,2667],{},"Export",[1060,2669,2670],{},"Where it runs",[1060,2672,1071],{},[1073,2674,2675,2690,2708,2725,2738,2751],{},[1057,2676,2677,2682,2687],{},[1078,2678,2679],{},[600,2680,2681],{},"extendMenu(nuxt, path, items)",[1078,2683,2684,2685],{},"Module ",[600,2686,2032],{},[1078,2688,2689],{},"Adds static items to one exact group.",[1057,2691,2692,2697,2701],{},[1078,2693,2694],{},[600,2695,2696],{},"registerMenuSource(nuxt, { file, menu })",[1078,2698,2684,2699],{},[600,2700,2032],{},[1078,2702,2703,2704,2707],{},"Registers a runtime menu file. ",[600,2705,2706],{},"file"," must be a resolved path.",[1057,2709,2710,2715,2718],{},[1078,2711,2712],{},[600,2713,2714],{},"defineMenuSource(fn)",[1078,2716,2717],{},"Runtime menu file",[1078,2719,2720,2721,2724],{},"A typed helper. ",[600,2722,2723],{},"fn(items)"," receives the menu's root group.",[1057,2726,2727,2732,2735],{},[1078,2728,2729],{},[600,2730,2731],{},"extendMenuItem(path, items)",[1078,2733,2734],{},"Nuxt app (auto-imported)",[1078,2736,2737],{},"Adds items to a group from a runtime menu file or app code.",[1057,2739,2740,2745,2748],{},[1078,2741,2742],{},[600,2743,2744],{},"defineMenuItem(item)",[1078,2746,2747],{},"Anywhere",[1078,2749,2750],{},"A typed helper for an item.",[1057,2752,2753,2761,2763],{},[1078,2754,2755,1835,2758],{},[600,2756,2757],{},"parseMenuPath(path)",[600,2759,2760],{},"deriveMenuItemId(item)",[1078,2762,2747],{},[1078,2764,2765],{},"Path parsing and id derivation.",[593,2767,2768,2769,1835,2772,1835,2775,648,2778,2781],{},"The types ",[600,2770,2771],{},"MenuItem",[600,2773,2774],{},"MenuSource",[600,2776,2777],{},"RegisterMenuSourceOptions",[600,2779,2780],{},"ParsedMenuPath"," come from the same path.",[618,2783,234],{"id":2784},"hooks",[593,2786,2787,2788,687],{},"Module authors and your app can listen to these ",[613,2789,2784],{"href":87},[1051,2791,2792,2808],{},[1054,2793,2794],{},[1057,2795,2796,2799,2802,2805],{},[1060,2797,2798],{},"Hook",[1060,2800,2801],{},"Where",[1060,2803,2804],{},"When",[1060,2806,2807],{},"Payload",[1073,2809,2810,2830,2848,2875],{},[1057,2811,2812,2817,2820,2825],{},[1078,2813,2814],{},[600,2815,2816],{},"menus:extend",[1078,2818,2819],{},"Nuxt (build)",[1078,2821,2822,2824],{},[600,2823,647],{}," adds items",[1078,2826,2827],{},[600,2828,2829],{},"(menu: string, items: MenuItem[])",[1057,2831,2832,2837,2839,2842],{},[1078,2833,2834],{},[600,2835,2836],{},"menus:resolved",[1078,2838,2819],{},[1078,2840,2841],{},"Once, after every module has set up",[1078,2843,2844,2847],{},[600,2845,2846],{},"(menus: Record\u003Cstring, Record\u003Cstring, MenuItem[]>>)",": menu, then group, then items",[1057,2849,2850,2855,2858,2866],{},[1078,2851,2852],{},[600,2853,2854],{},"menus:filter",[1078,2856,2857],{},"Nuxt app",[1078,2859,2860,2862,2863],{},[600,2861,1265],{}," resolved a menu's items, before ",[600,2864,2865],{},"menus:visible",[1078,2867,2868,2871,2872],{},[600,2869,2870],{},"{ menu, path, items: MenuItem[] }","; reassign or filter ",[600,2873,2874],{},"ctx.items",[1057,2876,2877,2881,2883,2888],{},[1078,2878,2879],{},[600,2880,2865],{},[1078,2882,2857],{},[1078,2884,2885,2887],{},[600,2886,1265],{}," resolved a menu's items",[1078,2889,2890],{},[600,2891,2892],{},"(menu: string)",[593,2894,2895,2897],{},[600,2896,2836],{}," holds only the items added at build time. Items from runtime menu files and Nuxt Content resolve\nwhen the page renders.",[618,2899,2901],{"id":2900},"hide-items-per-viewer","Hide items per viewer",[593,2903,2904,2905,2908,2909,2911,2912,2914,2915,2917,2918,2921],{},"An item with a ",[600,2906,2907],{},"permission"," is shown only to viewers who hold it. Menu itself never interprets the field. It calls\n",[600,2910,2854],{}," once per resolved menu, and a listener drops what the viewer should not see. With\n",[613,2913,199],{"href":200}," installed, a listener is already registered: it keeps an item when it\nhas no ",[600,2916,2907],{}," or when ",[600,2919,2920],{},"can(item.permission)"," is true, children included.",[721,2923,2926],{"className":751,"code":2924,"filename":2925,"language":754,"meta":726,"style":726},"extendMenu(nuxt, 'admin.nav', [\n  { label: 'Forms', to: '\u002Fadmin\u002Fforms', icon: 'i-lucide-clipboard-list', permission: 'forms:manage' },\n])\n","module.ts",[600,2927,2928,2947,3004],{"__ignoreMap":726},[730,2929,2930,2932,2935,2937,2939,2941,2943,2945],{"class":732,"line":733},[730,2931,647],{"class":768},[730,2933,2934],{"class":772},"(nuxt",[730,2936,1198],{"class":776},[730,2938,1190],{"class":776},[730,2940,610],{"class":740},[730,2942,793],{"class":776},[730,2944,1198],{"class":776},[730,2946,2141],{"class":772},[730,2948,2949,2952,2954,2956,2958,2960,2962,2964,2966,2968,2970,2973,2975,2977,2980,2982,2984,2986,2988,2990,2993,2995,2997,3000,3002],{"class":732,"line":780},[730,2950,2951],{"class":776},"  {",[730,2953,2149],{"class":783},[730,2955,787],{"class":776},[730,2957,1190],{"class":776},[730,2959,294],{"class":740},[730,2961,793],{"class":776},[730,2963,1198],{"class":776},[730,2965,2177],{"class":783},[730,2967,787],{"class":776},[730,2969,1190],{"class":776},[730,2971,2972],{"class":740},"\u002Fadmin\u002Fforms",[730,2974,793],{"class":776},[730,2976,1198],{"class":776},[730,2978,2979],{"class":783}," icon",[730,2981,787],{"class":776},[730,2983,1190],{"class":776},[730,2985,498],{"class":740},[730,2987,793],{"class":776},[730,2989,1198],{"class":776},[730,2991,2992],{"class":783}," permission",[730,2994,787],{"class":776},[730,2996,1190],{"class":776},[730,2998,2999],{"class":740},"forms:manage",[730,3001,793],{"class":776},[730,3003,1213],{"class":776},[730,3005,3006],{"class":732,"line":806},[730,3007,3008],{"class":772},"])\n",[593,3010,3011],{},"Without a listener, every item is shown. To filter by something else, add your own:",[721,3013,3016],{"className":751,"code":3014,"filename":3015,"language":754,"meta":726,"style":726},"import { filterMenuItems } from '@frigear-nu\u002Fmenu\u002Futils'\n\nexport default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.hook('menus:filter', (ctx) => {\n    ctx.items = filterMenuItems(ctx.items, item => item.meta?.beta !== true)\n  })\n})\n","app\u002Fplugins\u002Fmenu.ts",[600,3017,3018,3037,3041,3063,3094,3140,3147],{"__ignoreMap":726},[730,3019,3020,3022,3024,3027,3029,3031,3033,3035],{"class":732,"line":733},[730,3021,2042],{"class":761},[730,3023,859],{"class":776},[730,3025,3026],{"class":772}," filterMenuItems",[730,3028,2050],{"class":776},[730,3030,2053],{"class":761},[730,3032,1190],{"class":776},[730,3034,1385],{"class":740},[730,3036,2060],{"class":776},[730,3038,3039],{"class":732,"line":780},[730,3040,901],{"emptyLinePlaceholder":900},[730,3042,3043,3045,3047,3050,3052,3054,3057,3059,3061],{"class":732,"line":806},[730,3044,762],{"class":761},[730,3046,765],{"class":761},[730,3048,3049],{"class":768}," defineNuxtPlugin",[730,3051,773],{"class":772},[730,3053,773],{"class":776},[730,3055,3056],{"class":1324},"nuxtApp",[730,3058,2116],{"class":776},[730,3060,1328],{"class":834},[730,3062,1151],{"class":776},[730,3064,3065,3068,3070,3073,3075,3077,3079,3081,3083,3085,3088,3090,3092],{"class":732,"line":897},[730,3066,3067],{"class":772},"  nuxtApp",[730,3069,687],{"class":776},[730,3071,3072],{"class":768},"hook",[730,3074,773],{"class":783},[730,3076,793],{"class":776},[730,3078,2854],{"class":740},[730,3080,793],{"class":776},[730,3082,1198],{"class":776},[730,3084,2505],{"class":776},[730,3086,3087],{"class":1324},"ctx",[730,3089,2116],{"class":776},[730,3091,1328],{"class":834},[730,3093,1151],{"class":776},[730,3095,3096,3099,3101,3103,3105,3107,3109,3111,3113,3115,3117,3120,3122,3124,3126,3128,3130,3133,3136,3138],{"class":732,"line":904},[730,3097,3098],{"class":772},"    ctx",[730,3100,687],{"class":776},[730,3102,947],{"class":772},[730,3104,872],{"class":776},[730,3106,3026],{"class":768},[730,3108,773],{"class":783},[730,3110,3087],{"class":772},[730,3112,687],{"class":776},[730,3114,947],{"class":772},[730,3116,1198],{"class":776},[730,3118,3119],{"class":1324}," item",[730,3121,1328],{"class":834},[730,3123,3119],{"class":772},[730,3125,687],{"class":776},[730,3127,2334],{"class":772},[730,3129,2510],{"class":776},[730,3131,3132],{"class":772},"beta",[730,3134,3135],{"class":776}," !==",[730,3137,1171],{"class":1170},[730,3139,812],{"class":783},[730,3141,3142,3145],{"class":732,"line":914},[730,3143,3144],{"class":776},"  }",[730,3146,812],{"class":783},[730,3148,3149,3151],{"class":732,"line":925},[730,3150,809],{"class":776},[730,3152,812],{"class":772},[593,3154,3155],{},"The resolved menu is cached under a key that includes an access version. Authorization raises the version whenever the\nviewer's access changes (sign-in, sign-out, a role change), so menus filter again without a reload.",[3157,3158,3159,3160,3163],"caution",{},"Filtering only hides links. The route behind an item must still call ",[600,3161,3162],{},"authorize"," on the server.",[618,3165,3167],{"id":3166},"next-steps","Next steps",[623,3169,3170,3175,3180],{},[626,3171,3172,3174],{},[613,3173,486],{"href":487}," – add a page with its entry in the admin sidebar.",[626,3176,3177,3179],{},[613,3178,72],{"href":73}," – how menus, widgets and hooks let modules extend each other.",[626,3181,3182,3184],{},[613,3183,358],{"href":359}," – add components to a page the way Menu adds links.",[3186,3187,3188],"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 .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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}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}",{"title":726,"searchDepth":780,"depth":780,"links":3190},[3191,3192,3197,3198,3199,3206,3207,3208],{"id":620,"depth":780,"text":621},{"id":707,"depth":780,"text":708,"children":3193},[3194,3195,3196],{"id":718,"depth":806,"text":719},{"id":747,"depth":806,"text":748},{"id":815,"depth":806,"text":816},{"id":1041,"depth":780,"text":1042},{"id":1248,"depth":780,"text":1249},{"id":1389,"depth":780,"text":267,"children":3200},[3201,3202,3203,3204,3205],{"id":1392,"depth":806,"text":1393},{"id":947,"depth":806,"text":1605},{"id":1892,"depth":806,"text":1893},{"id":2013,"depth":806,"text":2014},{"id":2652,"depth":806,"text":2653},{"id":2784,"depth":780,"text":234},{"id":2900,"depth":780,"text":2901},{"id":3166,"depth":780,"text":3167},"Lets modules add links to your app's navigation, such as the admin sidebar, without importing each other.","md",null,{},{"title":354,"description":3209},"8K2Y11_TSc2OVy0BM-TqHvoBOTV1XV7WT4Qclo8MMG4",[3216,3218],{"title":217,"path":351,"stem":352,"description":3217,"children":-1},"Gives your staff one guarded admin area, where every installed module adds its own management pages.",{"title":358,"path":359,"stem":360,"description":3219,"children":-1},"Lets modules add cards to a dashboard and tabs to a detail page that your app or another module owns.",1794503149100]