[{"data":1,"prerenderedAt":2060},["ShallowReactive",2],{"navigation_docs":3,"-core-concepts-route-protection":152,"-core-concepts-route-protection-surround":2055},[4,42,68,110,131],{"title":5,"path":6,"stem":7,"children":8,"icon":11},"Getting Started","/getting-started","1.getting-started/0.index",[9,12,17,22,27,32,37],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-sparkles",{"title":13,"path":14,"stem":15,"icon":16},"Installation","/getting-started/installation","1.getting-started/1.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Configuration","/getting-started/configuration","1.getting-started/2.configuration","i-lucide-settings",{"title":23,"path":24,"stem":25,"icon":26},"Client Setup","/getting-started/client-setup","1.getting-started/3.client-setup","i-lucide-monitor",{"title":28,"path":29,"stem":30,"icon":31},"Type Augmentation","/getting-started/type-augmentation","1.getting-started/4.type-augmentation","i-lucide-type",{"title":33,"path":34,"stem":35,"icon":36},"Schema Generation (NuxtHub)","/getting-started/schema-generation","1.getting-started/5.schema-generation","i-lucide-database",{"title":38,"path":39,"stem":40,"icon":41},"How It Works","/getting-started/how-it-works","1.getting-started/6.how-it-works","i-lucide-workflow",{"title":43,"path":44,"stem":45,"children":46,"page":67},"Core Concepts","/core-concepts","2.core-concepts",[47,51,55,59,63],{"title":48,"path":49,"stem":50},"serverAuth()","/core-concepts/server-auth","2.core-concepts/1.server-auth",{"title":52,"path":53,"stem":54},"Sessions","/core-concepts/sessions","2.core-concepts/2.sessions",{"title":56,"path":57,"stem":58},"Route Protection","/core-concepts/route-protection","2.core-concepts/3.route-protection",{"title":60,"path":61,"stem":62},"Auto‑Imports and Aliases","/core-concepts/auto-imports-aliases","2.core-concepts/4.auto-imports-aliases",{"title":64,"path":65,"stem":66},"Security & Caveats","/core-concepts/security-caveats","2.core-concepts/5.security-caveats",false,{"title":69,"path":70,"stem":71,"children":72,"page":67},"Guides","/guides","3.guides",[73,77,81,85,89,94,98,102,106],{"title":74,"path":75,"stem":76},"Role‑Based Access","/guides/role-based-access","3.guides/1.role-based-access",{"title":78,"path":79,"stem":80},"OAuth Providers","/guides/oauth-providers","3.guides/2.oauth-providers",{"title":82,"path":83,"stem":84},"Custom Database","/guides/custom-database","3.guides/3.custom-database",{"title":86,"path":87,"stem":88},"Database-less Mode","/guides/database-less-mode","3.guides/4.database-less-mode",{"title":90,"path":91,"stem":92,"icon":93},"External Auth Backend","/guides/external-auth-backend","3.guides/5.external-auth-backend","i-lucide-server",{"title":95,"path":96,"stem":97},"Migrating from nuxt-auth-utils","/guides/migrate-from-nuxt-auth-utils","3.guides/6.migrate-from-nuxt-auth-utils",{"title":99,"path":100,"stem":101},"Two-Factor Authentication (TOTP + Backup Codes)","/guides/two-factor-auth","3.guides/7.two-factor-auth",{"title":103,"path":104,"stem":105},"Testing","/guides/testing","3.guides/8.testing",{"title":107,"path":108,"stem":109},"Production Deployment","/guides/production-deployment","3.guides/9.production-deployment",{"title":111,"path":112,"stem":113,"children":114,"page":67},"Integrations","/integrations","4.integrations",[115,119,123,127],{"title":116,"path":117,"stem":118},"NuxtHub","/integrations/nuxthub","4.integrations/1.nuxthub",{"title":120,"path":121,"stem":122},"DevTools","/integrations/devtools","4.integrations/2.devtools",{"title":124,"path":125,"stem":126},"Convex","/integrations/convex","4.integrations/3.convex",{"title":128,"path":129,"stem":130},"i18n","/integrations/i18n","4.integrations/4.i18n",{"title":132,"path":133,"stem":134,"children":135,"page":67},"API Reference","/api","5.api",[136,140,144,148],{"title":137,"path":138,"stem":139},"Composables","/api/composables","5.api/1.composables",{"title":141,"path":142,"stem":143},"Server Utilities","/api/server-utils","5.api/2.server-utils",{"title":145,"path":146,"stem":147},"Components","/api/components","5.api/3.components",{"title":149,"path":150,"stem":151},"Types","/api/types","5.api/4.types",{"id":153,"title":56,"body":154,"description":2049,"extension":2050,"links":2051,"meta":2052,"navigation":184,"path":57,"seo":2053,"stem":58,"__hash__":2054},"docs/2.core-concepts/3.route-protection.md",{"type":155,"value":156,"toc":2031},"minimark",[157,234,238,243,324,331,336,343,390,405,498,502,516,750,755,893,905,917,940,943,971,975,984,1039,1043,1046,1142,1146,1152,1245,1249,1254,1339,1372,1375,1379,1382,1441,1452,1463,1466,1722,1726,1730,1734,1737,1803,1807,1914,1918,1924,2017,2020,2027],[158,159,160],"code-collapse",{},[161,162,168],"pre",{"className":163,"code":164,"filename":165,"language":166,"meta":167,"style":167},"language-txt shiki shiki-themes one-light synthwave-84 synthwave-84","Protect routes and API endpoints with @onmax/nuxt-better-auth.\n\n- Route Rules in `nuxt.config.ts`: `routeRules: { '/app/**': { auth: { only: 'user', redirectTo: '/login' } } }`\n- Guest-only pages: `{ auth: { only: 'guest', redirectTo: '/app' } }`\n- Role-based: `{ auth: { user: { role: 'admin' } } }` — arrays use OR logic\n- Page Meta: `definePageMeta({ auth: 'user' })` for per-page control\n- Server API: `await requireUserSession(event)` — throws 401 if not authenticated\n- Role + custom rules: `requireUserSession(event, { user: { role: 'admin' }, rule: ({ user }) => user.verified })`\n- Route rules auto-sync to client router for instant redirects\n- Always protect API endpoints with `requireUserSession` — route rules are UX only\n","Prompt","txt","",[169,170,171,179,186,192,198,204,210,216,222,228],"code",{"__ignoreMap":167},[172,173,176],"span",{"class":174,"line":175},"line",1,[172,177,178],{},"Protect routes and API endpoints with @onmax/nuxt-better-auth.\n",[172,180,182],{"class":174,"line":181},2,[172,183,185],{"emptyLinePlaceholder":184},true,"\n",[172,187,189],{"class":174,"line":188},3,[172,190,191],{},"- Route Rules in `nuxt.config.ts`: `routeRules: { '/app/**': { auth: { only: 'user', redirectTo: '/login' } } }`\n",[172,193,195],{"class":174,"line":194},4,[172,196,197],{},"- Guest-only pages: `{ auth: { only: 'guest', redirectTo: '/app' } }`\n",[172,199,201],{"class":174,"line":200},5,[172,202,203],{},"- Role-based: `{ auth: { user: { role: 'admin' } } }` — arrays use OR logic\n",[172,205,207],{"class":174,"line":206},6,[172,208,209],{},"- Page Meta: `definePageMeta({ auth: 'user' })` for per-page control\n",[172,211,213],{"class":174,"line":212},7,[172,214,215],{},"- Server API: `await requireUserSession(event)` — throws 401 if not authenticated\n",[172,217,219],{"class":174,"line":218},8,[172,220,221],{},"- Role + custom rules: `requireUserSession(event, { user: { role: 'admin' }, rule: ({ user }) => user.verified })`\n",[172,223,225],{"class":174,"line":224},9,[172,226,227],{},"- Route rules auto-sync to client router for instant redirects\n",[172,229,231],{"class":174,"line":230},10,[172,232,233],{},"- Always protect API endpoints with `requireUserSession` — route rules are UX only\n",[235,236,237],"p",{},"Use this page when you need to protect Nuxt pages, layouts, and API routes without guessing which layer is responsible for what.",[239,240,242],"h2",{"id":241},"quick-reference","Quick Reference",[244,245,246,263],"table",{},[247,248,249],"thead",{},[250,251,252,257,260],"tr",{},[253,254,256],"th",{"align":255},"left","Method",[253,258,259],{"align":255},"Scope",[253,261,262],{"align":255},"Use Case",[264,265,266,285,298,311],"tbody",{},[250,267,268,275,278],{},[269,270,271],"td",{"align":255},[272,273,274],"strong",{},"Route Rules",[269,276,277],{"align":255},"Global",[269,279,280,281,284],{"align":255},"Protecting whole sections (e.g., ",[169,282,283],{},"/admin/**",").",[250,286,287,292,295],{},[269,288,289],{"align":255},[272,290,291],{},"Page Meta",[269,293,294],{"align":255},"Per-Page",[269,296,297],{"align":255},"Specific logic for a single page.",[250,299,300,305,308],{},[269,301,302],{"align":255},[272,303,304],{},"Middleware",[269,306,307],{"align":255},"Client",[269,309,310],{"align":255},"Complex client-side navigation logic.",[250,312,313,318,321],{},[269,314,315],{"align":255},[272,316,317],{},"Server Utils",[269,319,320],{"align":255},"API",[269,322,323],{"align":255},"Protecting API endpoints.",[235,325,326,327,330],{},"Route rules and page meta handle navigation and UX. Server-side checks with ",[169,328,329],{},"requireUserSession(event)"," remain the actual security boundary for protected data and mutations.",[332,333,335],"h3",{"id":334},"matching-logic","Matching Logic",[235,337,338,339,342],{},"Role arrays use ",[272,340,341],{},"OR"," logic: the user needs any one of the listed values.",[161,344,348],{"className":345,"code":346,"language":347,"meta":167,"style":167},"language-ts shiki shiki-themes one-light synthwave-84 synthwave-84","// User needs role 'admin' OR 'moderator' (not both)\nauth: { user: { role: ['admin', 'moderator'] } }\n","ts",[169,349,350,356],{"__ignoreMap":167},[172,351,352],{"class":174,"line":175},[172,353,355],{"class":354},"st7cf","// User needs role 'admin' OR 'moderator' (not both)\n",[172,357,358,362,366,369,371,374,377,381,384,387],{"class":174,"line":181},[172,359,361],{"class":360},"sivOE","auth",[172,363,365],{"class":364},"s17Py",": { ",[172,367,368],{"class":360},"user",[172,370,365],{"class":364},[172,372,373],{"class":360},"role",[172,375,376],{"class":364},": [",[172,378,380],{"class":379},"sPAZv","'admin'",[172,382,383],{"class":364},", ",[172,385,386],{"class":379},"'moderator'",[172,388,389],{"class":364},"] } }\n",[235,391,392,393,396,397,400,401,404],{},"For ",[272,394,395],{},"AND"," logic (user needs multiple conditions), use ",[169,398,399],{},"requireUserSession"," with a ",[169,402,403],{},"rule"," callback in your server handlers:",[161,406,409],{"className":345,"code":407,"filename":408,"language":347,"meta":167,"style":167},"await requireUserSession(event, {\n  user: { role: 'admin' },\n  rule: ({ user }) => user.verified === true,\n})\n","server/api/admin/report.ts",[169,410,411,431,454,493],{"__ignoreMap":167},[172,412,413,417,421,424,428],{"class":174,"line":175},[172,414,416],{"class":415},"sqe1H","await",[172,418,420],{"class":419},"sfT9l"," requireUserSession",[172,422,423],{"class":364},"(",[172,425,427],{"class":426},"svFNh","event",[172,429,430],{"class":364},", {\n",[172,432,433,437,441,444,446,448,451],{"class":174,"line":181},[172,434,436],{"class":435},"sYvLG","  user",[172,438,440],{"class":439},"sVnqq",":",[172,442,443],{"class":364}," { ",[172,445,373],{"class":435},[172,447,440],{"class":439},[172,449,450],{"class":379}," 'admin'",[172,452,453],{"class":364}," },\n",[172,455,456,459,461,464,467,470,473,476,479,482,486,490],{"class":174,"line":188},[172,457,458],{"class":419},"  rule",[172,460,440],{"class":439},[172,462,463],{"class":364}," ({ ",[172,465,368],{"class":466},"sgisi",[172,468,469],{"class":364}," }) ",[172,471,472],{"class":415},"=>",[172,474,475],{"class":426}," user",[172,477,478],{"class":364},".",[172,480,481],{"class":435},"verified",[172,483,485],{"class":484},"sn-Jc"," ===",[172,487,489],{"class":488},"s3ZNE"," true",[172,491,492],{"class":364},",\n",[172,494,495],{"class":174,"line":194},[172,496,497],{"class":364},"})\n",[239,499,501],{"id":500},"_1-route-rules","1. Route Rules",[235,503,504,505,508,509,512,513,478],{},"The most efficient way to protect your app is using route rules in ",[169,506,507],{},"nuxt.config.ts",". You can define them under ",[169,510,511],{},"routeRules"," or ",[169,514,515],{},"nitro.routeRules",[161,517,519],{"className":345,"code":518,"filename":507,"language":347,"meta":167,"style":167},"export default defineNuxtConfig({\n  routeRules: {\n    // Authenticated users only\n    '/app/**': { auth: { only: 'user', redirectTo: '/login' } },\n    \n    // Guests only (e.g. login page)\n    '/login': { auth: { only: 'guest', redirectTo: '/app' } },\n    \n    // Admin role only\n    '/admin/**': { auth: { user: { role: 'admin' } } },\n    \n    // Admin OR Moderator\n    '/staff/**': { \n      auth: { \n        user: { role: ['admin', 'moderator'] } \n      } \n    }\n  }\n})\n",[169,520,521,536,546,551,587,592,597,630,634,639,669,674,680,691,701,727,733,739,745],{"__ignoreMap":167},[172,522,523,526,530,533],{"class":174,"line":175},[172,524,525],{"class":415},"export",[172,527,529],{"class":528},"sKg8T"," default",[172,531,532],{"class":419}," defineNuxtConfig",[172,534,535],{"class":364},"({\n",[172,537,538,541,543],{"class":174,"line":181},[172,539,540],{"class":435},"  routeRules",[172,542,440],{"class":439},[172,544,545],{"class":364}," {\n",[172,547,548],{"class":174,"line":188},[172,549,550],{"class":354},"    // Authenticated users only\n",[172,552,553,556,558,560,562,564,566,569,571,574,576,579,581,584],{"class":174,"line":194},[172,554,555],{"class":379},"    '/app/**'",[172,557,440],{"class":439},[172,559,443],{"class":364},[172,561,361],{"class":435},[172,563,440],{"class":439},[172,565,443],{"class":364},[172,567,568],{"class":435},"only",[172,570,440],{"class":439},[172,572,573],{"class":379}," 'user'",[172,575,383],{"class":364},[172,577,578],{"class":435},"redirectTo",[172,580,440],{"class":439},[172,582,583],{"class":379}," '/login'",[172,585,586],{"class":364}," } },\n",[172,588,589],{"class":174,"line":200},[172,590,591],{"class":364},"    \n",[172,593,594],{"class":174,"line":206},[172,595,596],{"class":354},"    // Guests only (e.g. login page)\n",[172,598,599,602,604,606,608,610,612,614,616,619,621,623,625,628],{"class":174,"line":212},[172,600,601],{"class":379},"    '/login'",[172,603,440],{"class":439},[172,605,443],{"class":364},[172,607,361],{"class":435},[172,609,440],{"class":439},[172,611,443],{"class":364},[172,613,568],{"class":435},[172,615,440],{"class":439},[172,617,618],{"class":379}," 'guest'",[172,620,383],{"class":364},[172,622,578],{"class":435},[172,624,440],{"class":439},[172,626,627],{"class":379}," '/app'",[172,629,586],{"class":364},[172,631,632],{"class":174,"line":218},[172,633,591],{"class":364},[172,635,636],{"class":174,"line":224},[172,637,638],{"class":354},"    // Admin role only\n",[172,640,641,644,646,648,650,652,654,656,658,660,662,664,666],{"class":174,"line":230},[172,642,643],{"class":379},"    '/admin/**'",[172,645,440],{"class":439},[172,647,443],{"class":364},[172,649,361],{"class":435},[172,651,440],{"class":439},[172,653,443],{"class":364},[172,655,368],{"class":435},[172,657,440],{"class":439},[172,659,443],{"class":364},[172,661,373],{"class":435},[172,663,440],{"class":439},[172,665,450],{"class":379},[172,667,668],{"class":364}," } } },\n",[172,670,672],{"class":174,"line":671},11,[172,673,591],{"class":364},[172,675,677],{"class":174,"line":676},12,[172,678,679],{"class":354},"    // Admin OR Moderator\n",[172,681,683,686,688],{"class":174,"line":682},13,[172,684,685],{"class":379},"    '/staff/**'",[172,687,440],{"class":439},[172,689,690],{"class":364}," { \n",[172,692,694,697,699],{"class":174,"line":693},14,[172,695,696],{"class":435},"      auth",[172,698,440],{"class":439},[172,700,690],{"class":364},[172,702,704,707,709,711,713,715,718,720,722,724],{"class":174,"line":703},15,[172,705,706],{"class":435},"        user",[172,708,440],{"class":439},[172,710,443],{"class":364},[172,712,373],{"class":435},[172,714,440],{"class":439},[172,716,717],{"class":364}," [",[172,719,380],{"class":379},[172,721,383],{"class":364},[172,723,386],{"class":379},[172,725,726],{"class":364},"] } \n",[172,728,730],{"class":174,"line":729},16,[172,731,732],{"class":364},"      } \n",[172,734,736],{"class":174,"line":735},17,[172,737,738],{"class":364},"    }\n",[172,740,742],{"class":174,"line":741},18,[172,743,744],{"class":364},"  }\n",[172,746,748],{"class":174,"line":747},19,[172,749,497],{"class":364},[235,751,752,753,440],{},"The same auth keys work under ",[169,754,515],{},[161,756,758],{"className":345,"code":757,"filename":507,"language":347,"meta":167,"style":167},"export default defineNuxtConfig({\n  nitro: {\n    routeRules: {\n      '/app/**': { auth: { only: 'user', redirectTo: '/login' } },\n      '/login': { auth: { only: 'guest', redirectTo: '/app' } },\n      '/admin/**': { auth: { user: { role: 'admin' } } },\n    },\n  },\n})\n",[169,759,760,770,779,788,819,850,879,884,889],{"__ignoreMap":167},[172,761,762,764,766,768],{"class":174,"line":175},[172,763,525],{"class":415},[172,765,529],{"class":528},[172,767,532],{"class":419},[172,769,535],{"class":364},[172,771,772,775,777],{"class":174,"line":181},[172,773,774],{"class":435},"  nitro",[172,776,440],{"class":439},[172,778,545],{"class":364},[172,780,781,784,786],{"class":174,"line":188},[172,782,783],{"class":435},"    routeRules",[172,785,440],{"class":439},[172,787,545],{"class":364},[172,789,790,793,795,797,799,801,803,805,807,809,811,813,815,817],{"class":174,"line":194},[172,791,792],{"class":379},"      '/app/**'",[172,794,440],{"class":439},[172,796,443],{"class":364},[172,798,361],{"class":435},[172,800,440],{"class":439},[172,802,443],{"class":364},[172,804,568],{"class":435},[172,806,440],{"class":439},[172,808,573],{"class":379},[172,810,383],{"class":364},[172,812,578],{"class":435},[172,814,440],{"class":439},[172,816,583],{"class":379},[172,818,586],{"class":364},[172,820,821,824,826,828,830,832,834,836,838,840,842,844,846,848],{"class":174,"line":200},[172,822,823],{"class":379},"      '/login'",[172,825,440],{"class":439},[172,827,443],{"class":364},[172,829,361],{"class":435},[172,831,440],{"class":439},[172,833,443],{"class":364},[172,835,568],{"class":435},[172,837,440],{"class":439},[172,839,618],{"class":379},[172,841,383],{"class":364},[172,843,578],{"class":435},[172,845,440],{"class":439},[172,847,627],{"class":379},[172,849,586],{"class":364},[172,851,852,855,857,859,861,863,865,867,869,871,873,875,877],{"class":174,"line":206},[172,853,854],{"class":379},"      '/admin/**'",[172,856,440],{"class":439},[172,858,443],{"class":364},[172,860,361],{"class":435},[172,862,440],{"class":439},[172,864,443],{"class":364},[172,866,368],{"class":435},[172,868,440],{"class":439},[172,870,443],{"class":364},[172,872,373],{"class":435},[172,874,440],{"class":439},[172,876,450],{"class":379},[172,878,668],{"class":364},[172,880,881],{"class":174,"line":212},[172,882,883],{"class":364},"    },\n",[172,885,886],{"class":174,"line":218},[172,887,888],{"class":364},"  },\n",[172,890,891],{"class":174,"line":224},[172,892,497],{"class":364},[894,895,896,897,899,900,902,903,478],"note",{},"If both ",[169,898,511],{}," and ",[169,901,515],{}," are present, the module reads ",[169,904,515],{},[235,906,907,908,910,911,383,914,284],{},"If ",[169,909,578],{}," is omitted, shorthand defaults apply (",[169,912,913],{},"'user' -> '/login'",[169,915,916],{},"'guest' -> '/'",[918,919,920,937],"tip",{},[235,921,907,922,925,926,928,929,932,933,936],{},[169,923,924],{},"auth: { user: { ... } }"," complains about missing fields (e.g. ",[169,927,373],{},"), ensure your Better Auth plugin fields are inferred or that you have a working ",[169,930,931],{},"#nuxt-better-auth"," type augmentation in a root ",[169,934,935],{},"*.d.ts"," file.",[938,939],"read-more",{"title":28,"to":29},[894,941,942],{},"These rules are automatically synced to the client-side router, ensuring instant redirects without server roundtrips for navigation.",[894,944,945,946,949,950,383,953,383,956,383,959,962,963,966,967,970],{},"Broad rules such as ",[169,947,948],{},"'/**': { auth: 'user' }"," skip framework and module internals that must stay reachable, including ",[169,951,952],{},"/_nuxt/**",[169,954,955],{},"/_ipx/**",[169,957,958],{},"/api/_nuxt_icon/**",[169,960,961],{},"/api/_better-auth/**",", Better Auth's ",[169,964,965],{},"/api/auth/**",", and development-only module routes. The module still applies broad auth rules to app-owned pages and ",[169,968,969],{},"/api/**"," handlers.",[239,972,974],{"id":973},"_2-page-meta","2. Page Meta",[235,976,977,978,981,982,478],{},"For page-specific control, use ",[169,979,980],{},"definePageMeta"," within your Vue components. This overrides global ",[169,983,511],{},[161,985,990],{"className":986,"code":987,"filename":988,"language":989,"meta":167,"style":167},"language-vue shiki shiki-themes one-light synthwave-84 synthwave-84","\u003Cscript setup>\ndefinePageMeta({\n  auth: 'user'\n})\n\u003C/script>\n","pages/dashboard.vue","vue",[169,991,992,1009,1016,1026,1030],{"__ignoreMap":167},[172,993,994,998,1002,1006],{"class":174,"line":175},[172,995,997],{"class":996},"sL9le","\u003C",[172,999,1001],{"class":1000},"stweg","script",[172,1003,1005],{"class":1004},"s0frj"," setup",[172,1007,1008],{"class":996},">\n",[172,1010,1011,1013],{"class":174,"line":181},[172,1012,980],{"class":419},[172,1014,535],{"class":1015},"sEEOt",[172,1017,1018,1021,1023],{"class":174,"line":188},[172,1019,1020],{"class":435},"  auth",[172,1022,440],{"class":439},[172,1024,1025],{"class":379}," 'user'\n",[172,1027,1028],{"class":174,"line":194},[172,1029,497],{"class":1015},[172,1031,1032,1035,1037],{"class":174,"line":200},[172,1033,1034],{"class":996},"\u003C/",[172,1036,1001],{"class":1000},[172,1038,1008],{"class":996},[332,1040,1042],{"id":1041},"advanced-options","Advanced Options",[235,1044,1045],{},"You can pass an object for granular control:",[161,1047,1049],{"className":345,"code":1048,"language":347,"meta":167,"style":167},"definePageMeta({\n  auth: {\n    // Only allow authenticated users\n    only: 'user',\n    \n    // Redirect blocked users to a specific page\n    redirectTo: '/subscribe',\n    \n    // Match specific user properties\n    user: {\n      verified: true\n    }\n  }\n})\n",[169,1050,1051,1057,1065,1070,1081,1085,1090,1102,1106,1111,1120,1130,1134,1138],{"__ignoreMap":167},[172,1052,1053,1055],{"class":174,"line":175},[172,1054,980],{"class":419},[172,1056,535],{"class":364},[172,1058,1059,1061,1063],{"class":174,"line":181},[172,1060,1020],{"class":435},[172,1062,440],{"class":439},[172,1064,545],{"class":364},[172,1066,1067],{"class":174,"line":188},[172,1068,1069],{"class":354},"    // Only allow authenticated users\n",[172,1071,1072,1075,1077,1079],{"class":174,"line":194},[172,1073,1074],{"class":435},"    only",[172,1076,440],{"class":439},[172,1078,573],{"class":379},[172,1080,492],{"class":364},[172,1082,1083],{"class":174,"line":200},[172,1084,591],{"class":364},[172,1086,1087],{"class":174,"line":206},[172,1088,1089],{"class":354},"    // Redirect blocked users to a specific page\n",[172,1091,1092,1095,1097,1100],{"class":174,"line":212},[172,1093,1094],{"class":435},"    redirectTo",[172,1096,440],{"class":439},[172,1098,1099],{"class":379}," '/subscribe'",[172,1101,492],{"class":364},[172,1103,1104],{"class":174,"line":218},[172,1105,591],{"class":364},[172,1107,1108],{"class":174,"line":224},[172,1109,1110],{"class":354},"    // Match specific user properties\n",[172,1112,1113,1116,1118],{"class":174,"line":230},[172,1114,1115],{"class":435},"    user",[172,1117,440],{"class":439},[172,1119,545],{"class":364},[172,1121,1122,1125,1127],{"class":174,"line":671},[172,1123,1124],{"class":435},"      verified",[172,1126,440],{"class":439},[172,1128,1129],{"class":488}," true\n",[172,1131,1132],{"class":174,"line":676},[172,1133,738],{"class":364},[172,1135,1136],{"class":174,"line":682},[172,1137,744],{"class":364},[172,1139,1140],{"class":174,"line":693},[172,1141,497],{"class":364},[239,1143,1145],{"id":1144},"_3-server-api-protection","3. Server API Protection",[235,1147,1148,1149,1151],{},"Protecting your API endpoints is critical. Use ",[169,1150,399],{}," to enforce authentication on server routes.",[161,1153,1156],{"className":345,"code":1154,"filename":1155,"language":347,"meta":167,"style":167},"export default defineEventHandler(async (event) => {\n  // Throws 401 if not logged in\n  const { user } = await requireUserSession(event)\n  \n  return { secret: 'data' }\n})\n","server/api/secret.get.ts",[169,1157,1158,1184,1189,1218,1223,1241],{"__ignoreMap":167},[172,1159,1160,1162,1164,1167,1169,1172,1175,1177,1180,1182],{"class":174,"line":175},[172,1161,525],{"class":415},[172,1163,529],{"class":528},[172,1165,1166],{"class":419}," defineEventHandler",[172,1168,423],{"class":364},[172,1170,1171],{"class":415},"async",[172,1173,1174],{"class":364}," (",[172,1176,427],{"class":466},[172,1178,1179],{"class":364},") ",[172,1181,472],{"class":415},[172,1183,545],{"class":364},[172,1185,1186],{"class":174,"line":181},[172,1187,1188],{"class":354},"  // Throws 401 if not logged in\n",[172,1190,1191,1194,1196,1199,1202,1206,1209,1211,1213,1215],{"class":174,"line":188},[172,1192,1193],{"class":415},"  const",[172,1195,443],{"class":364},[172,1197,368],{"class":1198},"s6Rhl",[172,1200,1201],{"class":364}," } ",[172,1203,1205],{"class":1204},"sQBpM","=",[172,1207,1208],{"class":415}," await",[172,1210,420],{"class":419},[172,1212,423],{"class":364},[172,1214,427],{"class":435},[172,1216,1217],{"class":364},")\n",[172,1219,1220],{"class":174,"line":194},[172,1221,1222],{"class":364},"  \n",[172,1224,1225,1228,1230,1233,1235,1238],{"class":174,"line":200},[172,1226,1227],{"class":415},"  return",[172,1229,443],{"class":364},[172,1231,1232],{"class":435},"secret",[172,1234,440],{"class":439},[172,1236,1237],{"class":379}," 'data'",[172,1239,1240],{"class":364}," }\n",[172,1242,1243],{"class":174,"line":206},[172,1244,497],{"class":364},[332,1246,1248],{"id":1247},"role-based-access","Role-Based Access",[235,1250,1251,1252,440],{},"You can also pass requirements to ",[169,1253,399],{},[161,1255,1257],{"className":345,"code":1256,"language":347,"meta":167,"style":167},"await requireUserSession(event, {\n  // User must match ALL conditions\n  user: {\n    role: 'admin',\n    verified: true,\n    // OR logic for array values\n    plan: ['pro', 'enterprise']\n  }\n})\n",[169,1258,1259,1271,1276,1284,1295,1306,1311,1331,1335],{"__ignoreMap":167},[172,1260,1261,1263,1265,1267,1269],{"class":174,"line":175},[172,1262,416],{"class":415},[172,1264,420],{"class":419},[172,1266,423],{"class":364},[172,1268,427],{"class":426},[172,1270,430],{"class":364},[172,1272,1273],{"class":174,"line":181},[172,1274,1275],{"class":354},"  // User must match ALL conditions\n",[172,1277,1278,1280,1282],{"class":174,"line":188},[172,1279,436],{"class":435},[172,1281,440],{"class":439},[172,1283,545],{"class":364},[172,1285,1286,1289,1291,1293],{"class":174,"line":194},[172,1287,1288],{"class":435},"    role",[172,1290,440],{"class":439},[172,1292,450],{"class":379},[172,1294,492],{"class":364},[172,1296,1297,1300,1302,1304],{"class":174,"line":200},[172,1298,1299],{"class":435},"    verified",[172,1301,440],{"class":439},[172,1303,489],{"class":488},[172,1305,492],{"class":364},[172,1307,1308],{"class":174,"line":206},[172,1309,1310],{"class":354},"    // OR logic for array values\n",[172,1312,1313,1316,1318,1320,1323,1325,1328],{"class":174,"line":212},[172,1314,1315],{"class":435},"    plan",[172,1317,440],{"class":439},[172,1319,717],{"class":364},[172,1321,1322],{"class":379},"'pro'",[172,1324,383],{"class":364},[172,1326,1327],{"class":379},"'enterprise'",[172,1329,1330],{"class":364},"]\n",[172,1332,1333],{"class":174,"line":218},[172,1334,744],{"class":364},[172,1336,1337],{"class":174,"line":224},[172,1338,497],{"class":364},[161,1340,1342],{"className":345,"code":1341,"language":347,"meta":167,"style":167},"// Custom fields (like 'plan') must be defined in your Better Auth schema\nauth: { user: { plan: ['pro', 'enterprise'] } }\n",[169,1343,1344,1349],{"__ignoreMap":167},[172,1345,1346],{"class":174,"line":175},[172,1347,1348],{"class":354},"// Custom fields (like 'plan') must be defined in your Better Auth schema\n",[172,1350,1351,1353,1355,1357,1359,1362,1364,1366,1368,1370],{"class":174,"line":181},[172,1352,361],{"class":360},[172,1354,365],{"class":364},[172,1356,368],{"class":360},[172,1358,365],{"class":364},[172,1360,1361],{"class":360},"plan",[172,1363,376],{"class":364},[172,1365,1322],{"class":379},[172,1367,383],{"class":364},[172,1369,1327],{"class":379},[172,1371,389],{"class":364},[938,1373],{"title":1374,"to":75},"Role-Based Access guide",[239,1376,1378],{"id":1377},"safe-redirects-after-login","Safe Redirects After Login",[235,1380,1381],{},"When redirecting unauthenticated users to your login page, this module automatically appends a return-to query param by default:",[161,1383,1385],{"className":345,"code":1384,"filename":507,"language":347,"meta":167,"style":167},"export default defineNuxtConfig({\n  auth: {\n    preserveRedirect: true, // default\n    redirectQueryKey: 'redirect', // default\n  },\n})\n",[169,1386,1387,1397,1405,1419,1433,1437],{"__ignoreMap":167},[172,1388,1389,1391,1393,1395],{"class":174,"line":175},[172,1390,525],{"class":415},[172,1392,529],{"class":528},[172,1394,532],{"class":419},[172,1396,535],{"class":364},[172,1398,1399,1401,1403],{"class":174,"line":181},[172,1400,1020],{"class":435},[172,1402,440],{"class":439},[172,1404,545],{"class":364},[172,1406,1407,1410,1412,1414,1416],{"class":174,"line":188},[172,1408,1409],{"class":435},"    preserveRedirect",[172,1411,440],{"class":439},[172,1413,489],{"class":488},[172,1415,383],{"class":364},[172,1417,1418],{"class":354},"// default\n",[172,1420,1421,1424,1426,1429,1431],{"class":174,"line":194},[172,1422,1423],{"class":435},"    redirectQueryKey",[172,1425,440],{"class":439},[172,1427,1428],{"class":379}," 'redirect'",[172,1430,383],{"class":364},[172,1432,1418],{"class":354},[172,1434,1435],{"class":174,"line":200},[172,1436,888],{"class":364},[172,1438,1439],{"class":174,"line":206},[172,1440,497],{"class":364},[235,1442,1443,1444,1447,1448,1451],{},"Your login page can then read ",[169,1445,1446],{},"route.query.redirect"," (or your custom ",[169,1449,1450],{},"auth.redirectQueryKey",") to navigate back after a successful login.",[235,1453,1454,1455,1458,1459,1462],{},"You can also set ",[169,1456,1457],{},"auth.redirects.authenticated"," to define where users land after successful login/sign-up when ",[169,1460,1461],{},"onSuccess"," is not provided in the auth method call.",[235,1464,1465],{},"When preserving the original URL for post-login redirects, validate it to prevent open redirect attacks:",[161,1467,1470],{"className":345,"code":1468,"filename":1469,"language":347,"meta":167,"style":167},"const route = useRoute()\nconst signInEmail = useSignIn('email')\n\nfunction getSafeRedirect() {\n  const redirect = route.query.redirect as string\n  if (!redirect || !redirect.startsWith('/') || redirect.startsWith('//')) {\n    return '/'\n  }\n  return redirect\n}\n\nasync function login(email: string, password: string) {\n  await signInEmail.execute(\n    { email, password },\n    { onSuccess: () => navigateTo(getSafeRedirect()) },\n  )\n}\n","pages/login.vue",[169,1471,1472,1489,1508,1512,1523,1552,1601,1609,1613,1620,1625,1629,1661,1676,1689,1713,1718],{"__ignoreMap":167},[172,1473,1474,1477,1480,1483,1486],{"class":174,"line":175},[172,1475,1476],{"class":415},"const",[172,1478,1479],{"class":1198}," route",[172,1481,1482],{"class":1204}," =",[172,1484,1485],{"class":419}," useRoute",[172,1487,1488],{"class":364},"()\n",[172,1490,1491,1493,1496,1498,1501,1503,1506],{"class":174,"line":181},[172,1492,1476],{"class":415},[172,1494,1495],{"class":1198}," signInEmail",[172,1497,1482],{"class":1204},[172,1499,1500],{"class":419}," useSignIn",[172,1502,423],{"class":364},[172,1504,1505],{"class":379},"'email'",[172,1507,1217],{"class":364},[172,1509,1510],{"class":174,"line":188},[172,1511,185],{"emptyLinePlaceholder":184},[172,1513,1514,1517,1520],{"class":174,"line":194},[172,1515,1516],{"class":415},"function",[172,1518,1519],{"class":419}," getSafeRedirect",[172,1521,1522],{"class":364},"() {\n",[172,1524,1525,1527,1530,1532,1534,1536,1539,1541,1544,1548],{"class":174,"line":200},[172,1526,1193],{"class":415},[172,1528,1529],{"class":1198}," redirect",[172,1531,1482],{"class":1204},[172,1533,1479],{"class":426},[172,1535,478],{"class":364},[172,1537,1538],{"class":435},"query",[172,1540,478],{"class":364},[172,1542,1543],{"class":435},"redirect",[172,1545,1547],{"class":1546},"snT_2"," as",[172,1549,1551],{"class":1550},"sr8De"," string\n",[172,1553,1554,1557,1559,1562,1564,1567,1570,1572,1574,1577,1579,1582,1584,1587,1589,1591,1593,1595,1598],{"class":174,"line":206},[172,1555,1556],{"class":415},"  if",[172,1558,1174],{"class":364},[172,1560,1561],{"class":484},"!",[172,1563,1543],{"class":426},[172,1565,1566],{"class":484}," ||",[172,1568,1569],{"class":484}," !",[172,1571,1543],{"class":426},[172,1573,478],{"class":364},[172,1575,1576],{"class":419},"startsWith",[172,1578,423],{"class":364},[172,1580,1581],{"class":379},"'/'",[172,1583,1179],{"class":364},[172,1585,1586],{"class":484},"||",[172,1588,1529],{"class":426},[172,1590,478],{"class":364},[172,1592,1576],{"class":419},[172,1594,423],{"class":364},[172,1596,1597],{"class":379},"'//'",[172,1599,1600],{"class":364},")) {\n",[172,1602,1603,1606],{"class":174,"line":212},[172,1604,1605],{"class":415},"    return",[172,1607,1608],{"class":379}," '/'\n",[172,1610,1611],{"class":174,"line":218},[172,1612,744],{"class":364},[172,1614,1615,1617],{"class":174,"line":224},[172,1616,1227],{"class":415},[172,1618,1619],{"class":426}," redirect\n",[172,1621,1622],{"class":174,"line":230},[172,1623,1624],{"class":364},"}\n",[172,1626,1627],{"class":174,"line":671},[172,1628,185],{"emptyLinePlaceholder":184},[172,1630,1631,1633,1636,1639,1641,1644,1646,1649,1651,1654,1656,1658],{"class":174,"line":676},[172,1632,1171],{"class":415},[172,1634,1635],{"class":415}," function",[172,1637,1638],{"class":419}," login",[172,1640,423],{"class":364},[172,1642,1643],{"class":466},"email",[172,1645,440],{"class":484},[172,1647,1648],{"class":1550}," string",[172,1650,383],{"class":364},[172,1652,1653],{"class":466},"password",[172,1655,440],{"class":484},[172,1657,1648],{"class":1550},[172,1659,1660],{"class":364},") {\n",[172,1662,1663,1666,1668,1670,1673],{"class":174,"line":682},[172,1664,1665],{"class":415},"  await",[172,1667,1495],{"class":426},[172,1669,478],{"class":364},[172,1671,1672],{"class":419},"execute",[172,1674,1675],{"class":364},"(\n",[172,1677,1678,1681,1683,1685,1687],{"class":174,"line":693},[172,1679,1680],{"class":364},"    { ",[172,1682,1643],{"class":426},[172,1684,383],{"class":364},[172,1686,1653],{"class":426},[172,1688,453],{"class":364},[172,1690,1691,1693,1695,1697,1700,1702,1705,1707,1710],{"class":174,"line":703},[172,1692,1680],{"class":364},[172,1694,1461],{"class":419},[172,1696,440],{"class":439},[172,1698,1699],{"class":364}," () ",[172,1701,472],{"class":415},[172,1703,1704],{"class":419}," navigateTo",[172,1706,423],{"class":364},[172,1708,1709],{"class":419},"getSafeRedirect",[172,1711,1712],{"class":364},"()) },\n",[172,1714,1715],{"class":174,"line":729},[172,1716,1717],{"class":364},"  )\n",[172,1719,1720],{"class":174,"line":735},[172,1721,1624],{"class":364},[1723,1724,1725],"warning",{},"Always validate redirect URLs. Accepting arbitrary URLs allows attackers to redirect users to malicious sites after login.",[239,1727,1729],{"id":1728},"advanced-api-patterns","Advanced API Patterns",[332,1731,1733],{"id":1732},"custom-rule-callback","Custom Rule Callback",[235,1735,1736],{},"For complex authorization logic:",[161,1738,1740],{"className":345,"code":1739,"filename":408,"language":347,"meta":167,"style":167},"const session = await requireUserSession(event, {\n  user: { emailVerified: true },\n  rule: ({ user }) => user.subscriptionActive\n})\n",[169,1741,1742,1761,1778,1799],{"__ignoreMap":167},[172,1743,1744,1746,1749,1751,1753,1755,1757,1759],{"class":174,"line":175},[172,1745,1476],{"class":415},[172,1747,1748],{"class":1198}," session",[172,1750,1482],{"class":1204},[172,1752,1208],{"class":415},[172,1754,420],{"class":419},[172,1756,423],{"class":364},[172,1758,427],{"class":426},[172,1760,430],{"class":364},[172,1762,1763,1765,1767,1769,1772,1774,1776],{"class":174,"line":181},[172,1764,436],{"class":435},[172,1766,440],{"class":439},[172,1768,443],{"class":364},[172,1770,1771],{"class":435},"emailVerified",[172,1773,440],{"class":439},[172,1775,489],{"class":488},[172,1777,453],{"class":364},[172,1779,1780,1782,1784,1786,1788,1790,1792,1794,1796],{"class":174,"line":188},[172,1781,458],{"class":419},[172,1783,440],{"class":439},[172,1785,463],{"class":364},[172,1787,368],{"class":466},[172,1789,469],{"class":364},[172,1791,472],{"class":415},[172,1793,475],{"class":426},[172,1795,478],{"class":364},[172,1797,1798],{"class":435},"subscriptionActive\n",[172,1800,1801],{"class":174,"line":194},[172,1802,497],{"class":364},[332,1804,1806],{"id":1805},"websocket-handlers","WebSocket Handlers",[161,1808,1811],{"className":345,"code":1809,"filename":1810,"language":347,"meta":167,"style":167},"import { defineWebSocketHandler } from 'h3'\n\nexport default defineWebSocketHandler({\n  open: async (peer) => {\n    await requireUserSession(peer.ctx.event, { user: { role: 'member' } })\n  },\n})\n","server/api/ws.ts",[169,1812,1813,1831,1835,1846,1867,1906,1910],{"__ignoreMap":167},[172,1814,1815,1818,1820,1823,1825,1828],{"class":174,"line":175},[172,1816,1817],{"class":415},"import",[172,1819,443],{"class":364},[172,1821,1822],{"class":435},"defineWebSocketHandler",[172,1824,1201],{"class":364},[172,1826,1827],{"class":415},"from",[172,1829,1830],{"class":379}," 'h3'\n",[172,1832,1833],{"class":174,"line":181},[172,1834,185],{"emptyLinePlaceholder":184},[172,1836,1837,1839,1841,1844],{"class":174,"line":188},[172,1838,525],{"class":415},[172,1840,529],{"class":528},[172,1842,1843],{"class":419}," defineWebSocketHandler",[172,1845,535],{"class":364},[172,1847,1848,1851,1853,1856,1858,1861,1863,1865],{"class":174,"line":194},[172,1849,1850],{"class":419},"  open",[172,1852,440],{"class":439},[172,1854,1855],{"class":415}," async",[172,1857,1174],{"class":364},[172,1859,1860],{"class":466},"peer",[172,1862,1179],{"class":364},[172,1864,472],{"class":415},[172,1866,545],{"class":364},[172,1868,1869,1872,1874,1876,1878,1880,1883,1885,1887,1890,1892,1894,1896,1898,1900,1903],{"class":174,"line":200},[172,1870,1871],{"class":415},"    await",[172,1873,420],{"class":419},[172,1875,423],{"class":364},[172,1877,1860],{"class":426},[172,1879,478],{"class":364},[172,1881,1882],{"class":435},"ctx",[172,1884,478],{"class":364},[172,1886,427],{"class":435},[172,1888,1889],{"class":364},", { ",[172,1891,368],{"class":435},[172,1893,440],{"class":439},[172,1895,443],{"class":364},[172,1897,373],{"class":435},[172,1899,440],{"class":439},[172,1901,1902],{"class":379}," 'member'",[172,1904,1905],{"class":364}," } })\n",[172,1907,1908],{"class":174,"line":206},[172,1909,888],{"class":364},[172,1911,1912],{"class":174,"line":212},[172,1913,497],{"class":364},[239,1915,1917],{"id":1916},"csrf-protection","CSRF Protection",[235,1919,1920,1921,440],{},"Better Auth includes CSRF protection by default. Always use the auth client methods instead of raw ",[169,1922,1923],{},"fetch",[161,1925,1927],{"className":345,"code":1926,"language":347,"meta":167,"style":167},"// ✓ Correct: uses auth client\nawait useSignIn('email').execute({ email, password })\n\n// ✗ Incorrect: bypasses CSRF protection\nawait fetch('/api/auth/sign-in/email', { method: 'POST', body: JSON.stringify({ email, password }) })\n",[169,1928,1929,1934,1960,1964,1969],{"__ignoreMap":167},[172,1930,1931],{"class":174,"line":175},[172,1932,1933],{"class":354},"// ✓ Correct: uses auth client\n",[172,1935,1936,1938,1940,1942,1944,1946,1948,1951,1953,1955,1957],{"class":174,"line":181},[172,1937,416],{"class":415},[172,1939,1500],{"class":419},[172,1941,423],{"class":364},[172,1943,1505],{"class":379},[172,1945,284],{"class":364},[172,1947,1672],{"class":419},[172,1949,1950],{"class":364},"({ ",[172,1952,1643],{"class":426},[172,1954,383],{"class":364},[172,1956,1653],{"class":426},[172,1958,1959],{"class":364}," })\n",[172,1961,1962],{"class":174,"line":188},[172,1963,185],{"emptyLinePlaceholder":184},[172,1965,1966],{"class":174,"line":194},[172,1967,1968],{"class":354},"// ✗ Incorrect: bypasses CSRF protection\n",[172,1970,1971,1973,1976,1978,1981,1983,1986,1988,1991,1993,1996,1998,2001,2003,2006,2008,2010,2012,2014],{"class":174,"line":200},[172,1972,416],{"class":415},[172,1974,1975],{"class":419}," fetch",[172,1977,423],{"class":364},[172,1979,1980],{"class":379},"'/api/auth/sign-in/email'",[172,1982,1889],{"class":364},[172,1984,1985],{"class":435},"method",[172,1987,440],{"class":439},[172,1989,1990],{"class":379}," 'POST'",[172,1992,383],{"class":364},[172,1994,1995],{"class":435},"body",[172,1997,440],{"class":439},[172,1999,2000],{"class":1198}," JSON",[172,2002,478],{"class":364},[172,2004,2005],{"class":419},"stringify",[172,2007,1950],{"class":364},[172,2009,1643],{"class":426},[172,2011,383],{"class":364},[172,2013,1653],{"class":426},[172,2015,2016],{"class":364}," }) })\n",[938,2018],{"title":2019,"to":65},"Security Caveats",[2021,2022,2023,2024,2026],"important",{},"Route Rules and Page Meta are primarily for UX (redirects). Always protect your API endpoints with ",[169,2025,399],{}," to ensure real security.",[2028,2029,2030],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .st7cf, html code.shiki .st7cf{--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-default:#848BBD;--shiki-default-font-style:italic;--shiki-dark:#848BBD;--shiki-dark-font-style:italic}html pre.shiki code .sivOE, html code.shiki .sivOE{--shiki-light:#383A42;--shiki-default:#FE4450;--shiki-dark:#FE4450}html pre.shiki code .s17Py, html code.shiki .s17Py{--shiki-light:#383A42;--shiki-default:#BBBBBB;--shiki-dark:#BBBBBB}html pre.shiki code .sPAZv, html code.shiki .sPAZv{--shiki-light:#50A14F;--shiki-default:#FF8B39;--shiki-dark:#FF8B39}html pre.shiki code .sqe1H, html code.shiki .sqe1H{--shiki-light:#A626A4;--shiki-default:#FEDE5D;--shiki-dark:#FEDE5D}html pre.shiki code .sfT9l, html code.shiki .sfT9l{--shiki-light:#4078F2;--shiki-default:#36F9F6;--shiki-dark:#36F9F6}html pre.shiki code .svFNh, html code.shiki .svFNh{--shiki-light:#383A42;--shiki-default:#FF7EDB;--shiki-dark:#FF7EDB}html pre.shiki code .sYvLG, html code.shiki .sYvLG{--shiki-light:#E45649;--shiki-default:#FF7EDB;--shiki-dark:#FF7EDB}html pre.shiki code .sVnqq, html code.shiki .sVnqq{--shiki-light:#0184BC;--shiki-default:#B6B1B1;--shiki-dark:#B6B1B1}html pre.shiki code .sgisi, html code.shiki .sgisi{--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-default:#FF7EDB;--shiki-default-font-style:italic;--shiki-dark:#FF7EDB;--shiki-dark-font-style:italic}html pre.shiki code .sn-Jc, html code.shiki .sn-Jc{--shiki-light:#0184BC;--shiki-default:#FEDE5D;--shiki-dark:#FEDE5D}html pre.shiki code .s3ZNE, html code.shiki .s3ZNE{--shiki-light:#986801;--shiki-default:#F97E72;--shiki-dark:#F97E72}html pre.shiki code .sKg8T, html code.shiki .sKg8T{--shiki-light:#E45649;--shiki-default:#FEDE5D;--shiki-dark:#FEDE5D}html pre.shiki code .sL9le, html code.shiki .sL9le{--shiki-light:#383A42;--shiki-default:#36F9F6;--shiki-dark:#36F9F6}html pre.shiki code .stweg, html code.shiki .stweg{--shiki-light:#E45649;--shiki-default:#72F1B8;--shiki-dark:#72F1B8}html pre.shiki code .s0frj, html code.shiki .s0frj{--shiki-light:#986801;--shiki-light-font-style:inherit;--shiki-default:#FEDE5D;--shiki-default-font-style:italic;--shiki-dark:#FEDE5D;--shiki-dark-font-style:italic}html pre.shiki code .sEEOt, html code.shiki .sEEOt{--shiki-light:#383A42;--shiki-default:#FFFFFFEE;--shiki-dark:#FFFFFFEE}html pre.shiki code .s6Rhl, html code.shiki .s6Rhl{--shiki-light:#986801;--shiki-default:#FF7EDB;--shiki-dark:#FF7EDB}html pre.shiki code .sQBpM, html code.shiki .sQBpM{--shiki-light:#0184BC;--shiki-default:#FFFFFFEE;--shiki-dark:#FFFFFFEE}html pre.shiki code .snT_2, html code.shiki .snT_2{--shiki-light:#383A42;--shiki-default:#FEDE5D;--shiki-dark:#FEDE5D}html pre.shiki code .sr8De, html code.shiki .sr8De{--shiki-light:#0184BC;--shiki-default:#FE4450;--shiki-dark:#FE4450}",{"title":167,"searchDepth":181,"depth":181,"links":2032},[2033,2036,2037,2040,2043,2044,2048],{"id":241,"depth":181,"text":242,"children":2034},[2035],{"id":334,"depth":188,"text":335},{"id":500,"depth":181,"text":501},{"id":973,"depth":181,"text":974,"children":2038},[2039],{"id":1041,"depth":188,"text":1042},{"id":1144,"depth":181,"text":1145,"children":2041},[2042],{"id":1247,"depth":188,"text":1248},{"id":1377,"depth":181,"text":1378},{"id":1728,"depth":181,"text":1729,"children":2045},[2046,2047],{"id":1732,"depth":188,"text":1733},{"id":1805,"depth":188,"text":1806},{"id":1916,"depth":181,"text":1917},"Learn how to protect your pages and API routes using a layered approach.","md",null,{},{"title":56,"description":2049},"C8USIBEfR7j1HSoaCxcM831QbA1aiSUv4gfkYFzuPvc",[2056,2058],{"title":52,"path":53,"stem":54,"description":2057,"children":-1},"Access reactive session state with SSR support using `useUserSession()`.",{"title":60,"path":61,"stem":62,"description":2059,"children":-1},"What the module registers for you.",1782807285763]