[{"data":1,"prerenderedAt":1900},["ShallowReactive",2],{"navigation_docs":3,"-modules-features-forms":587,"-modules-features-forms-surround":1895},[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":294,"body":589,"description":1888,"extension":1889,"links":1890,"meta":1891,"navigation":1892,"path":295,"seo":1893,"stem":296,"__hash__":1894},"docs\u002F3.modules\u002F3.features\u002F2.forms\u002Findex.md",{"type":590,"value":591,"toc":1873},"minimark",[592,604,612,617,697,701,741,745,1139,1154,1158,1165,1493,1505,1515,1532,1543,1547,1627,1630,1639,1730,1774,1781,1785,1848,1852,1869],[593,594,595,596,600,601,603],"p",{},"Forms lets you publish contact forms, sign-ups and applications without building a page for each one.\n",[597,598,599],"a",{"href":87},"Staff"," build a form in the admin area, or you define it in code. Every submission is stored,\nemailed or passed to your own code. Use it when visitors or users should send you structured answers. For settings a\nuser keeps on their own account, use ",[597,602,221],{"href":222}," instead.",[593,605,606,607,611],{},"The package is ",[608,609,610],"code",{},"@frigear-nu\u002Fforms",". Each form is a definition stored in the database.",[613,614,616],"h2",{"id":615},"what-you-get","What you get",[618,619,620,635,648,670,679,688],"ul",{},[621,622,623,626,627,630,631,634],"li",{},[624,625,101],"strong",{}," (opt-in): a public page per form at ",[608,628,629],{},"\u002Fforms\u002F:slug",". ",[608,632,633],{},"\u003CFormRenderer>"," and a Markdown embed place a form on\nany other page.",[621,636,637,640,641,643,644,647],{},[624,638,639],{},"Admin area"," (opt-in, with ",[597,642,217],{"href":351},"): the form list at ",[608,645,646],{},"\u002Fadmin\u002Fforms",", a visual builder for\neach form, and its submissions.",[621,649,650,653,654,657,658,661,665,666,669],{},[624,651,652],{},"Server routes"," (on by default): read and submit a published form, and a staff API for forms, submissions and\naccess. The staff API is guarded by the ",[608,655,656],{},"forms:manage"," and ",[608,659,660],{},"forms:credentials",[597,662,664],{"href":663},"#permissions","permissions",", which the ",[608,667,668],{},"admin"," role holds.",[621,671,672,674,675,678],{},[624,673,344],{}," (on by default): ",[608,676,677],{},"defineForm()"," to write a form in code, and a hook that receives every\nsubmission.",[621,680,681,684,685,687],{},[624,682,683],{},"MCP tools"," (opt-in): list and submit forms, and manage them as staff, through ",[597,686,317],{"href":318},".",[621,689,690,693,694,696],{},[624,691,692],{},"Emails"," (opt-in per form): each submission is emailed through ",[597,695,403],{"href":404}," to the recipients\nthe form names. Your app picks the Notify driver; until it does, emails are not sent.",[698,699],"module-runtime",{":client":700,":server":700},"true",[702,703,704,707,708,710,711,713,714,710,716,710,718,720,721,707,724,727,728,731,732,707,735,737,738,740],"note",{},[624,705,706],{},"Installed for you:"," ",[597,709,403],{"href":404},", ",[597,712,168],{"href":169},",\n",[597,715,191],{"href":192},[597,717,317],{"href":318},[597,719,326],{"href":327}," and Module Kit.\n",[624,722,723],{},"You add:",[608,725,726],{},"@nuxthub\u002Fcore"," (Forms turns on its key-value storage for rate limiting and blob storage for uploads), and\n",[608,729,730],{},"@nuxt\u002Fui"," for the pages.\n",[624,733,734],{},"Optional:",[597,736,217],{"href":351}," for the admin pages, and ",[597,739,354],{"href":355}," for the admin\nsidebar item.",[613,742,744],{"id":743},"quick-setup","Quick setup",[746,747,748,753,781,785,950,954,962,965,977,981,993,1012],"steps",{},[749,750,752],"h3",{"id":751},"install-forms","Install Forms",[754,755,760],"pre",{"className":756,"code":757,"language":758,"meta":759,"style":759},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fforms @nuxthub\u002Fcore\n","bash","",[608,761,762],{"__ignoreMap":759},[763,764,767,771,775,778],"span",{"class":765,"line":766},"line",1,[763,768,770],{"class":769},"sBMFI","pnpm",[763,772,774],{"class":773},"sfazB"," add",[763,776,777],{"class":773}," @frigear-nu\u002Fforms",[763,779,780],{"class":773}," @nuxthub\u002Fcore\n",[749,782,784],{"id":783},"add-it-to-nuxtconfigts","Add it to nuxt.config.ts",[754,786,791],{"className":787,"code":788,"filename":789,"language":790,"meta":759,"style":759},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore', '@frigear-nu\u002Fforms'],\n  forms: {\n    settings: {\n      pages: { form: true, admin: true, adminForm: true, adminSubmissions: true, adminSubmission: true },\n    },\n  },\n})\n","nuxt.config.ts","ts",[608,792,793,814,849,860,870,929,935,941],{"__ignoreMap":759},[763,794,795,799,802,806,810],{"class":765,"line":766},[763,796,798],{"class":797},"s7zQu","export",[763,800,801],{"class":797}," default",[763,803,805],{"class":804},"s2Zo4"," defineNuxtConfig",[763,807,809],{"class":808},"sTEyZ","(",[763,811,813],{"class":812},"sMK4o","{\n",[763,815,817,821,824,827,830,832,834,837,840,842,844,847],{"class":765,"line":816},2,[763,818,820],{"class":819},"swJcz","  modules",[763,822,823],{"class":812},":",[763,825,826],{"class":808}," [",[763,828,829],{"class":812},"'",[763,831,726],{"class":773},[763,833,829],{"class":812},[763,835,836],{"class":812},",",[763,838,839],{"class":812}," '",[763,841,610],{"class":773},[763,843,829],{"class":812},[763,845,846],{"class":808},"]",[763,848,713],{"class":812},[763,850,852,855,857],{"class":765,"line":851},3,[763,853,854],{"class":819},"  forms",[763,856,823],{"class":812},[763,858,859],{"class":812}," {\n",[763,861,863,866,868],{"class":765,"line":862},4,[763,864,865],{"class":819},"    settings",[763,867,823],{"class":812},[763,869,859],{"class":812},[763,871,873,876,878,881,884,886,890,892,895,897,899,901,904,906,908,910,913,915,917,919,922,924,926],{"class":765,"line":872},5,[763,874,875],{"class":819},"      pages",[763,877,823],{"class":812},[763,879,880],{"class":812}," {",[763,882,883],{"class":819}," form",[763,885,823],{"class":812},[763,887,889],{"class":888},"sfNiH"," true",[763,891,836],{"class":812},[763,893,894],{"class":819}," admin",[763,896,823],{"class":812},[763,898,889],{"class":888},[763,900,836],{"class":812},[763,902,903],{"class":819}," adminForm",[763,905,823],{"class":812},[763,907,889],{"class":888},[763,909,836],{"class":812},[763,911,912],{"class":819}," adminSubmissions",[763,914,823],{"class":812},[763,916,889],{"class":888},[763,918,836],{"class":812},[763,920,921],{"class":819}," adminSubmission",[763,923,823],{"class":812},[763,925,889],{"class":888},[763,927,928],{"class":812}," },\n",[763,930,932],{"class":765,"line":931},6,[763,933,934],{"class":812},"    },\n",[763,936,938],{"class":765,"line":937},7,[763,939,940],{"class":812},"  },\n",[763,942,944,947],{"class":765,"line":943},8,[763,945,946],{"class":812},"}",[763,948,949],{"class":808},")\n",[749,951,953],{"id":952},"generate-the-migration","Generate the migration",[955,956,957,958,961],"warning",{},"Without a ",[597,959,960],{"href":87},"migration"," the form tables do not exist, and creating or submitting a form fails.",[593,963,964],{},"Forms adds six tables. Generate the migration and commit it:",[754,966,968],{"className":756,"code":967,"language":758,"meta":759,"style":759},"pnpm db:generate\n",[608,969,970],{"__ignoreMap":759},[763,971,972,974],{"class":765,"line":766},[763,973,770],{"class":769},[763,975,976],{"class":773}," db:generate\n",[749,978,980],{"id":979},"decide-who-manages-forms","Decide who manages forms",[955,982,983,984,986,987,989,990,992],{},"Staff routes check permissions through ",[597,985,199],{"href":200},". Without a role that holds\n",[608,988,656],{},", nobody can manage forms. The ",[608,991,668],{}," role holds it by default.",[593,994,995,996,999,1000,713,1002,657,1004,1007,1008,1011],{},"To let another role manage forms, grant the permissions in your config. ",[608,997,998],{},"forms:*"," covers ",[608,1001,656],{},[608,1003,660],{},[608,1005,1006],{},"forms:submit",", but not ",[608,1009,1010],{},"forms:pii",", which you grant by name:",[754,1013,1015],{"className":787,"code":1014,"filename":789,"language":790,"meta":759,"style":759},"export default defineNuxtConfig({\n  authorization: {\n    roles: {\n      manager: { label: 'Coordinator', grant: ['forms:*', 'users:read', 'users:list'], inherit: ['user'] },\n    },\n  },\n})\n",[608,1016,1017,1029,1038,1047,1125,1129,1133],{"__ignoreMap":759},[763,1018,1019,1021,1023,1025,1027],{"class":765,"line":766},[763,1020,798],{"class":797},[763,1022,801],{"class":797},[763,1024,805],{"class":804},[763,1026,809],{"class":808},[763,1028,813],{"class":812},[763,1030,1031,1034,1036],{"class":765,"line":816},[763,1032,1033],{"class":819},"  authorization",[763,1035,823],{"class":812},[763,1037,859],{"class":812},[763,1039,1040,1043,1045],{"class":765,"line":851},[763,1041,1042],{"class":819},"    roles",[763,1044,823],{"class":812},[763,1046,859],{"class":812},[763,1048,1049,1052,1054,1056,1059,1061,1063,1066,1068,1070,1073,1075,1077,1079,1081,1083,1085,1087,1090,1092,1094,1096,1099,1101,1103,1105,1108,1110,1112,1114,1117,1119,1122],{"class":765,"line":862},[763,1050,1051],{"class":819},"      manager",[763,1053,823],{"class":812},[763,1055,880],{"class":812},[763,1057,1058],{"class":819}," label",[763,1060,823],{"class":812},[763,1062,839],{"class":812},[763,1064,1065],{"class":773},"Coordinator",[763,1067,829],{"class":812},[763,1069,836],{"class":812},[763,1071,1072],{"class":819}," grant",[763,1074,823],{"class":812},[763,1076,826],{"class":808},[763,1078,829],{"class":812},[763,1080,998],{"class":773},[763,1082,829],{"class":812},[763,1084,836],{"class":812},[763,1086,839],{"class":812},[763,1088,1089],{"class":773},"users:read",[763,1091,829],{"class":812},[763,1093,836],{"class":812},[763,1095,839],{"class":812},[763,1097,1098],{"class":773},"users:list",[763,1100,829],{"class":812},[763,1102,846],{"class":808},[763,1104,836],{"class":812},[763,1106,1107],{"class":819}," inherit",[763,1109,823],{"class":812},[763,1111,826],{"class":808},[763,1113,829],{"class":812},[763,1115,1116],{"class":773},"user",[763,1118,829],{"class":812},[763,1120,1121],{"class":808},"] ",[763,1123,1124],{"class":812},"},\n",[763,1126,1127],{"class":765,"line":872},[763,1128,934],{"class":812},[763,1130,1131],{"class":765,"line":931},[763,1132,940],{"class":812},[763,1134,1135,1137],{"class":765,"line":937},[763,1136,946],{"class":812},[763,1138,949],{"class":808},[1140,1141,1144,1147,1148,1150,1151,687],"callout",{"color":1142,"icon":1143},"success","i-lucide-check",[624,1145,1146],{},"What you should see:"," signed in as staff, ",[608,1149,646],{}," lists your forms. A published form answers at\n",[608,1152,1153],{},"\u002Fforms\u002F\u003Cslug>",[613,1155,1157],{"id":1156},"options","Options",[593,1159,1160,1161,1164],{},"Options go under the ",[608,1162,1163],{},"forms"," key.",[1166,1167,1168,1187],"table",{},[1169,1170,1171],"thead",{},[1172,1173,1174,1178,1181,1184],"tr",{},[1175,1176,1177],"th",{},"Option",[1175,1179,1180],{},"Type",[1175,1182,1183],{},"Default",[1175,1185,1186],{},"Purpose",[1188,1189,1190,1214,1234,1255,1276,1297,1321,1340,1363,1385,1413,1433,1451,1471],"tbody",{},[1172,1191,1192,1198,1203,1206],{},[1193,1194,1195],"td",{},[608,1196,1197],{},"settings.pages.form",[1193,1199,1200],{},[608,1201,1202],{},"string | boolean",[1193,1204,1205],{},"off",[1193,1207,1208,1209,1211,1212,687],{},"The public form page. ",[608,1210,700],{}," is ",[608,1213,629],{},[1172,1215,1216,1221,1225,1227],{},[1193,1217,1218],{},[608,1219,1220],{},"settings.pages.admin",[1193,1222,1223],{},[608,1224,1202],{},[1193,1226,1205],{},[1193,1228,1229,1230,1211,1232,687],{},"The admin form list. ",[608,1231,700],{},[608,1233,646],{},[1172,1235,1236,1241,1245,1247],{},[1193,1237,1238],{},[608,1239,1240],{},"settings.pages.adminForm",[1193,1242,1243],{},[608,1244,1202],{},[1193,1246,1205],{},[1193,1248,1249,1250,1211,1252,687],{},"The builder. ",[608,1251,700],{},[608,1253,1254],{},"\u002Fadmin\u002Fforms\u002F:id",[1172,1256,1257,1262,1266,1268],{},[1193,1258,1259],{},[608,1260,1261],{},"settings.pages.adminSubmissions",[1193,1263,1264],{},[608,1265,1202],{},[1193,1267,1205],{},[1193,1269,1270,1271,1211,1273,687],{},"A form's submissions. ",[608,1272,700],{},[608,1274,1275],{},"\u002Fadmin\u002Fforms\u002F:id\u002Fsubmissions",[1172,1277,1278,1283,1287,1289],{},[1193,1279,1280],{},[608,1281,1282],{},"settings.pages.adminSubmission",[1193,1284,1285],{},[608,1286,1202],{},[1193,1288,1205],{},[1193,1290,1291,1292,1211,1294,687],{},"One submission. ",[608,1293,700],{},[608,1295,1296],{},"\u002Fadmin\u002Fforms\u002F:id\u002Fsubmissions\u002F:submissionId",[1172,1298,1299,1304,1309,1314],{},[1193,1300,1301],{},[608,1302,1303],{},"settings.rateLimit",[1193,1305,1306],{},[608,1307,1308],{},"number",[1193,1310,1311],{},[608,1312,1313],{},"10",[1193,1315,1316,1317,1320],{},"Submissions per client and form in one window. ",[608,1318,1319],{},"0"," turns rate limiting off.",[1172,1322,1323,1328,1332,1337],{},[1193,1324,1325],{},[608,1326,1327],{},"settings.rateLimitWindowSeconds",[1193,1329,1330],{},[608,1331,1308],{},[1193,1333,1334],{},[608,1335,1336],{},"600",[1193,1338,1339],{},"The length of the window.",[1172,1341,1342,1347,1352,1357],{},[1193,1343,1344],{},[608,1345,1346],{},"settings.mcp",[1193,1348,1349],{},[608,1350,1351],{},"boolean",[1193,1353,1354],{},[608,1355,1356],{},"false",[1193,1358,1359,1360,687],{},"Adds the module's ",[597,1361,683],{"href":1362},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver#mcp-tools",[1172,1364,1365,1370,1374,1378],{},[1193,1366,1367],{},[608,1368,1369],{},"seed.enabled",[1193,1371,1372],{},[608,1373,1351],{},[1193,1375,1376],{},[608,1377,1356],{},[1193,1379,1380,1381,1384],{},"Inserts ",[608,1382,1383],{},"seed.forms"," at startup.",[1172,1386,1387,1391,1396,1401],{},[1193,1388,1389],{},[608,1390,1383],{},[1193,1392,1393],{},[608,1394,1395],{},"SeedForm[]",[1193,1397,1398],{},[608,1399,1400],{},"[]",[1193,1402,1403,630,1406,1409,1410,687],{},[608,1404,1405],{},"{ slug, name, status?, definition }",[608,1407,1408],{},"status"," defaults to ",[608,1411,1412],{},"draft",[1172,1414,1415,1420,1425,1430],{},[1193,1416,1417],{},[608,1418,1419],{},"captcha.\u003Cprovider>.siteKey",[1193,1421,1422],{},[608,1423,1424],{},"string",[1193,1426,1427],{},[608,1428,1429],{},"''",[1193,1431,1432],{},"The public site key.",[1172,1434,1435,1440,1444,1448],{},[1193,1436,1437],{},[608,1438,1439],{},"captcha.\u003Cprovider>.secretKey",[1193,1441,1442],{},[608,1443,1424],{},[1193,1445,1446],{},[608,1447,1429],{},[1193,1449,1450],{},"The secret key, used only on the server.",[1172,1452,1453,1458,1463,1468],{},[1193,1454,1455],{},[608,1456,1457],{},"captcha.defaultProvider",[1193,1459,1460],{},[608,1461,1462],{},"CaptchaProvider",[1193,1464,1465],{},[608,1466,1467],{},"'turnstile'",[1193,1469,1470],{},"The provider of a captcha field that names none.",[1172,1472,1473,1478,1482,1486],{},[1193,1474,1475],{},[608,1476,1477],{},"encryptionKey",[1193,1479,1480],{},[608,1481,1424],{},[1193,1483,1484],{},[608,1485,1429],{},[1193,1487,1488,1489,687],{},"The key that encrypts ",[597,1490,1492],{"href":1491},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver#per-form-secrets","per-form secrets",[593,1494,1495,1500,1501,1504],{},[624,1496,1497],{},[608,1498,1499],{},"settings.pages.*"," paths keep the parameters of the default, such as ",[608,1502,1503],{},":slug",". Admin pages need Admin.",[593,1506,1507,1511,1512,1514],{},[624,1508,1509],{},[608,1510,1303],{}," also caps wrong password attempts, on a separate counter with the same window. ",[608,1513,1319],{}," turns both\noff.",[593,1516,1517,1211,1522,710,1525,1528,1529,687],{},[624,1518,1519],{},[608,1520,1521],{},"captcha.\u003Cprovider>",[608,1523,1524],{},"turnstile",[608,1526,1527],{},"recaptcha"," or ",[608,1530,1531],{},"hcaptcha",[593,1533,1534,1538,1539,1542],{},[624,1535,1536],{},[608,1537,1477],{}," falls back to ",[608,1540,1541],{},"NUXT_ENCRYPTION_KEY",", then to the session password.",[749,1544,1546],{"id":1545},"runtime-config","Runtime config",[1166,1548,1549,1558],{},[1169,1550,1551],{},[1172,1552,1553,1556],{},[1175,1554,1555],{},"Env var",[1175,1557,1177],{},[1188,1559,1560,1571,1588,1605,1616],{},[1172,1561,1562,1567],{},[1193,1563,1564],{},[608,1565,1566],{},"NUXT_FORMS_SEED_ENABLED",[1193,1568,1569],{},[608,1570,1369],{},[1172,1572,1573,1584],{},[1193,1574,1575,710,1578,710,1581],{},[608,1576,1577],{},"NUXT_PUBLIC_FORMS_CAPTCHA_TURNSTILE_SITE_KEY",[608,1579,1580],{},"…_RECAPTCHA_SITE_KEY",[608,1582,1583],{},"…_HCAPTCHA_SITE_KEY",[1193,1585,1586],{},[608,1587,1419],{},[1172,1589,1590,1601],{},[1193,1591,1592,710,1595,710,1598],{},[608,1593,1594],{},"NUXT_FORMS_CAPTCHA_TURNSTILE_SECRET_KEY",[608,1596,1597],{},"…_RECAPTCHA_SECRET_KEY",[608,1599,1600],{},"…_HCAPTCHA_SECRET_KEY",[1193,1602,1603],{},[608,1604,1439],{},[1172,1606,1607,1612],{},[1193,1608,1609],{},[608,1610,1611],{},"NUXT_PUBLIC_FORMS_CAPTCHA_DEFAULT_PROVIDER",[1193,1613,1614],{},[608,1615,1457],{},[1172,1617,1618,1623],{},[1193,1619,1620],{},[608,1621,1622],{},"NUXT_FORMS_ENCRYPTION_KEY",[1193,1624,1625],{},[608,1626,1477],{},[613,1628,1629],{"id":664},"Permissions",[593,1631,1632,1633,1635,1636,687],{},"Forms registers these permissions with ",[597,1634,199],{"href":200},". A staff route calls\n",[608,1637,1638],{},"authorize(event, 'forms:manage')",[1166,1640,1641,1657],{},[1169,1642,1643],{},[1172,1644,1645,1648,1651,1654],{},[1175,1646,1647],{},"Permission",[1175,1649,1650],{},"Flags",[1175,1652,1653],{},"Held by default",[1175,1655,1656],{},"What it allows",[1188,1658,1659,1674,1690,1715],{},[1172,1660,1661,1665,1667,1671],{},[1193,1662,1663],{},[608,1664,656],{},[1193,1666],{},[1193,1668,1669],{},[608,1670,668],{},[1193,1672,1673],{},"Create and edit forms, read their submissions and files, and deliver them again.",[1172,1675,1676,1680,1683,1687],{},[1193,1677,1678],{},[608,1679,660],{},[1193,1681,1682],{},"sessionOnly",[1193,1684,1685],{},[608,1686,668],{},[1193,1688,1689],{},"Create and remove form access tokens, passwords and secrets. Cookie sessions only.",[1172,1691,1692,1696,1699,1703],{},[1193,1693,1694],{},[608,1695,1010],{},[1193,1697,1698],{},"sensitive",[1193,1700,1701],{},[608,1702,668],{},[1193,1704,1705,1706,1708,1709,1528,1712,1714],{},"Sensitive (MCP only): gates submission answers and file names in MCP tool output. The admin HTTP API, submissions included, is gated by ",[608,1707,656],{},". A ",[608,1710,1711],{},"*",[608,1713,998],{}," grant never covers it.",[1172,1716,1717,1721,1724,1727],{},[1193,1718,1719],{},[608,1720,1006],{},[1193,1722,1723],{},"implicit",[1193,1725,1726],{},"every signed-in user",[1193,1728,1729],{},"Submit forms as you, and read forms that need a signed-in user.",[618,1731,1732,1743,1759],{},[621,1733,1734,707,1737,1739,1740,1742],{},[624,1735,1736],{},"Scope:",[608,1738,1163],{}," (label \"Submit forms\") expands to ",[608,1741,1006],{},". A token or OAuth client with it can submit as the\nuser, and nothing else.",[621,1744,1745,1748,1749,1751,1752,1754,1755,1758],{},[624,1746,1747],{},"Roles, requirements and policies:"," the module ships none. The ",[608,1750,668],{}," role receives the staff permissions through\nthe module's default grants. If you replace the ",[608,1753,668],{}," role with ",[608,1756,1757],{},"replace: true",", grant them again yourself.",[621,1760,1761,1767,1768,1770,1771,1773],{},[624,1762,1763,1764,1766],{},"Why ",[608,1765,660],{}," is separate:"," minting or removing a way into a form is a credential change, so it is session\nonly. A role that grants ",[608,1769,656],{}," by name must grant ",[608,1772,660],{}," too.",[593,1775,1776,1777,1780],{},"See ",[597,1778,1779],{"href":206},"roles and requirements"," for how roles are built and merged.",[613,1782,1784],{"id":1783},"module-pages","Module pages",[1166,1786,1787,1800],{},[1169,1788,1789],{},[1172,1790,1791,1794,1797],{},[1175,1792,1793],{},"Page",[1175,1795,1796],{},"What it covers",[1175,1798,1799],{},"For",[1188,1801,1802,1814,1826,1837],{},[1172,1803,1804,1808,1811],{},[1193,1805,1806],{},[597,1807,300],{"href":301},[1193,1809,1810],{},"What a form is made of: fields, conditions, phone fields, open periods, the email, captcha and the builder.",[1193,1812,1813],{},"App developers",[1172,1815,1816,1820,1823],{},[1193,1817,1818],{},[597,1819,175],{"href":304},[1193,1821,1822],{},"Submitting, who may submit, rate limits, secrets, seeding, staff access and MCP tools.",[1193,1824,1825],{},"App developers and module authors",[1172,1827,1828,1832,1835],{},[1193,1829,1830],{},[597,1831,267],{"href":307},[1193,1833,1834],{},"Pages, components, the Markdown embed, composables and utils.",[1193,1836,1813],{},[1172,1838,1839,1843,1846],{},[1193,1840,1841],{},[597,1842,179],{"href":310},[1193,1844,1845],{},"Hooks, routes, tables and translations.",[1193,1847,1813],{},[613,1849,1851],{"id":1850},"next-steps","Next steps",[618,1853,1854,1859,1864],{},[621,1855,1856,1858],{},[597,1857,495],{"href":496}," – define a contact form in code, seed it and receive it by email.",[621,1860,1861,1863],{},[597,1862,300],{"href":301}," – add steps, conditional fields, uploads and an open period.",[621,1865,1866,1868],{},[597,1867,500],{"href":501}," – pick the Notify driver that delivers form emails.",[1870,1871,1872],"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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":759,"searchDepth":816,"depth":816,"links":1874},[1875,1876,1882,1885,1886,1887],{"id":615,"depth":816,"text":616},{"id":743,"depth":816,"text":744,"children":1877},[1878,1879,1880,1881],{"id":751,"depth":851,"text":752},{"id":783,"depth":851,"text":784},{"id":952,"depth":851,"text":953},{"id":979,"depth":851,"text":980},{"id":1156,"depth":816,"text":1157,"children":1883},[1884],{"id":1545,"depth":851,"text":1546},{"id":664,"depth":816,"text":1629},{"id":1783,"depth":816,"text":1784},{"id":1850,"depth":816,"text":1851},"Publish forms your staff edit without a deploy, and store, email or forward every submission.","md",null,{},{"title":173},{"title":294,"description":1888},"WUPYrOQwfiMtA_u95chJ_ZaSaeoomnlf8wOujQlGz2k",[1896,1898],{"title":179,"path":291,"stem":292,"description":1897,"children":-1},"Look up the hooks, HTTP routes, database tables and translation keys of Events.",{"title":300,"path":301,"stem":302,"description":1899,"children":-1},"What a form is made of, from fields and conditions to open periods, the email it sends and captcha.",1794503149833]