[{"data":1,"prerenderedAt":934},["ShallowReactive",2],{"navigation_docs":3,"-gotrue-deployment":172,"-gotrue-deployment-surround":929},[4,26,67,98,124,140,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core","i-lucide-box","\u002Fcore","2.core",[32,37,42,47,52,57,62],{"title":33,"path":34,"stem":35,"icon":36},"Routing","\u002Fcore\u002Frouting","2.core\u002F1.routing","i-lucide-route",{"title":38,"path":39,"stem":40,"icon":41},"Handlers","\u002Fcore\u002Fhandlers","2.core\u002F2.handlers","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Request Binding","\u002Fcore\u002Frequest-binding","2.core\u002F3.request-binding","i-lucide-tags",{"title":48,"path":49,"stem":50,"icon":51},"Validation","\u002Fcore\u002Fvalidation","2.core\u002F4.validation","i-lucide-check-check",{"title":53,"path":54,"stem":55,"icon":56},"Context","\u002Fcore\u002Fcontext","2.core\u002F5.context","i-lucide-file-input",{"title":58,"path":59,"stem":60,"icon":61},"Errors","\u002Fcore\u002Ferrors","2.core\u002F6.errors","i-lucide-triangle-alert",{"title":63,"path":64,"stem":65,"icon":66},"Middleware","\u002Fcore\u002Fmiddleware","2.core\u002F7.middleware","i-lucide-layers",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":25},"Auth","i-lucide-shield-check","\u002Fauth","3.auth",[73,78,83,88,93],{"title":74,"path":75,"stem":76,"icon":77},"Overview","\u002Fauth\u002Foverview","3.auth\u002F1.overview","i-lucide-shield",{"title":79,"path":80,"stem":81,"icon":82},"Auth Rules","\u002Fauth\u002Fauth-rules","3.auth\u002F2.auth-rules","i-lucide-lock",{"title":84,"path":85,"stem":86,"icon":87},"JWT Providers","\u002Fauth\u002Fjwt-providers","3.auth\u002F3.jwt-providers","i-lucide-key",{"title":89,"path":90,"stem":91,"icon":92},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F4.roles-and-permissions","i-lucide-users",{"title":94,"path":95,"stem":96,"icon":97},"Audit Logging","\u002Fauth\u002Faudit-logging","3.auth\u002F5.audit-logging","i-lucide-scroll-text",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":25},"GoTrue","i-lucide-key-round","\u002Fgotrue","4.gotrue",[104,109,114,119],{"title":105,"path":106,"stem":107,"icon":108},"Proxy","\u002Fgotrue\u002Fproxy","4.gotrue\u002F1.proxy","i-lucide-shuffle",{"title":110,"path":111,"stem":112,"icon":113},"Endpoints","\u002Fgotrue\u002Fendpoints","4.gotrue\u002F2.endpoints","i-lucide-list",{"title":115,"path":116,"stem":117,"icon":118},"Client IP & Rate Limits","\u002Fgotrue\u002Fclient-ip-and-rate-limits","4.gotrue\u002F3.client-ip-and-rate-limits","i-lucide-network",{"title":120,"path":121,"stem":122,"icon":123},"Deployment","\u002Fgotrue\u002Fdeployment","4.gotrue\u002F4.deployment","i-lucide-server",{"title":125,"icon":126,"path":127,"stem":128,"children":129,"page":25},"API Docs","i-lucide-file-text","\u002Fapi-docs","5.api-docs",[130,135],{"title":131,"path":132,"stem":133,"icon":134},"OpenAPI","\u002Fapi-docs\u002Fopenapi","5.api-docs\u002F1.openapi","i-lucide-file-json",{"title":136,"path":137,"stem":138,"icon":139},"Scalar UI","\u002Fapi-docs\u002Fscalar","5.api-docs\u002F2.scalar","i-lucide-book-open-text",{"title":141,"icon":142,"path":143,"stem":144,"children":145,"page":25},"Guides","i-lucide-compass","\u002Fguides","6.guides",[146,151,156],{"title":147,"path":148,"stem":149,"icon":150},"Testing","\u002Fguides\u002Ftesting","6.guides\u002F1.testing","i-lucide-flask-conical",{"title":152,"path":153,"stem":154,"icon":155},"Performance","\u002Fguides\u002Fperformance","6.guides\u002F2.performance","i-lucide-gauge",{"title":157,"path":158,"stem":159,"icon":160},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":162,"icon":163,"path":164,"stem":165,"children":166,"page":25},"Reference","i-lucide-code","\u002Freference","7.reference",[167],{"title":168,"path":169,"stem":170,"icon":171},"API Reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"id":173,"title":120,"body":174,"description":922,"extension":923,"links":924,"meta":925,"navigation":926,"path":121,"seo":927,"stem":122,"__hash__":928},"docs\u002F4.gotrue\u002F4.deployment.md",{"type":175,"value":176,"toc":905},"minimark",[177,181,186,299,302,355,358,362,369,382,385,389,400,438,456,459,484,579,583,590,729,732,735,772,782,797,801,884,888,901],[178,179,180],"p",{},"Once ezz is the public entry point, GoTrue has to be told about it. GoTrue builds email links, OAuth metadata, and WebAuthn challenges from its own configuration, and those have to point at your service rather than at GoTrue.",[182,183,185],"h2",{"id":184},"settings-that-have-to-match","Settings that have to match",[187,188,189,205],"table",{},[190,191,192],"thead",{},[193,194,195,199,202],"tr",{},[196,197,198],"th",{},"Setting",[196,200,201],{},"Value",[196,203,204],{},"Why",[206,207,208,226,242,257,273,286],"tbody",{},[193,209,210,217,223],{},[211,212,213],"td",{},[214,215,216],"code",{},"GOTRUE_JWT_SECRET",[211,218,219,220],{},"Same string as ",[214,221,222],{},"GoTrueConfig.JWTSecret",[211,224,225],{},"ezz validates the tokens GoTrue signs",[193,227,228,233,239],{},[211,229,230],{},[214,231,232],{},"API_EXTERNAL_URL",[211,234,235,236],{},"Public base URL plus mount prefix, for example ",[214,237,238],{},"https:\u002F\u002Fapi.example.com\u002Fauth",[211,240,241],{},"Email links, OAuth metadata, and the issuer resolve back through ezz",[193,243,244,249,254],{},[211,245,246],{},[214,247,248],{},"GOTRUE_SECURITY_SB_FORWARDED_FOR_ENABLED",[211,250,251],{},[214,252,253],{},"true",[211,255,256],{},"GoTrue reads the forwarded client IP instead of your service's address",[193,258,259,264,270],{},[211,260,261],{},[214,262,263],{},"GOTRUE_WEBAUTHN_RP_ORIGINS",[211,265,266,267],{},"Public ezz origin, for example ",[214,268,269],{},"https:\u002F\u002Fapi.example.com",[211,271,272],{},"The browser performs WebAuthn against your domain",[193,274,275,280,283],{},[211,276,277],{},[214,278,279],{},"GOTRUE_WEBAUTHN_RP_ID",[211,281,282],{},"Public hostname",[211,284,285],{},"Must match the origin the browser sees",[193,287,288,293,296],{},[211,289,290],{},[214,291,292],{},"GOTRUE_SITE_URL",[211,294,295],{},"Your frontend URL",[211,297,298],{},"Where users land after clicking an email link",[178,300,301],{},"Feature switches worth being deliberate about:",[187,303,304,313],{},[190,305,306],{},[193,307,308,310],{},[196,309,198],{},[196,311,312],{},"Effect",[206,314,315,325,335,345],{},[193,316,317,322],{},[211,318,319],{},[214,320,321],{},"GOTRUE_OAUTH_SERVER_ENABLED",[211,323,324],{},"Turns the OAuth2 server endpoints on",[193,326,327,332],{},[211,328,329],{},[214,330,331],{},"GOTRUE_OAUTH_SERVER_ALLOW_DYNAMIC_REGISTRATION",[211,333,334],{},"Lets anyone register an OAuth client; leave off unless you need it",[193,336,337,342],{},[211,338,339],{},[214,340,341],{},"GOTRUE_PASSKEY_ENABLED",[211,343,344],{},"Turns passkey endpoints on",[193,346,347,352],{},[211,348,349],{},[214,350,351],{},"GOTRUE_MAILER_AUTOCONFIRM",[211,353,354],{},"Skips email confirmation; development only",[178,356,357],{},"The proxy mounts OAuth and passkey routes whether or not the features are enabled. GoTrue is the source of truth and answers with its own error when something is off, so there is no second switch to keep in sync.",[182,359,361],{"id":360},"keep-gotrue-off-the-internet","Keep GoTrue off the internet",[178,363,364,365,368],{},"The point of the proxy is that ",[214,366,367],{},"InternalURL"," is unreachable from outside. In practice that means one of:",[370,371,372,376,379],"ul",{},[373,374,375],"li",{},"A private network or VPC with no public ingress to the GoTrue service.",[373,377,378],{},"A Docker or Kubernetes network where only your service can resolve the hostname.",[373,380,381],{},"A firewall rule limiting GoTrue's port to your service's address.",[178,383,384],{},"If GoTrue is still publicly reachable, clients can bypass your rate limits, your audit trail, and any policy you add in front of the proxied routes.",[182,386,388],{"id":387},"run-it-locally","Run it locally",[178,390,391,392,395,396,399],{},"The repository has a working Compose setup in ",[214,393,394],{},"examples\u002Fgotrue"," with Postgres and ",[214,397,398],{},"supabase\u002Fgotrue",", and Make targets to drive it:",[401,402,408],"pre",{"className":403,"code":404,"filename":405,"language":406,"meta":407,"style":407},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","make gotrue-up      # start Postgres and GoTrue, wait for both to report healthy\nmake gotrue-down    # stop them and remove volumes\n","Terminal","bash","",[214,409,410,427],{"__ignoreMap":407},[411,412,415,419,423],"span",{"class":413,"line":414},"line",1,[411,416,418],{"class":417},"sBMFI","make",[411,420,422],{"class":421},"sfazB"," gotrue-up",[411,424,426],{"class":425},"sHwdD","      # start Postgres and GoTrue, wait for both to report healthy\n",[411,428,430,432,435],{"class":413,"line":429},2,[411,431,418],{"class":417},[411,433,434],{"class":421}," gotrue-down",[411,436,437],{"class":425},"    # stop them and remove volumes\n",[178,439,440,443,444,447,448,451,452,455],{},[214,441,442],{},"gotrue-up"," runs ",[214,445,446],{},"docker compose"," against ",[214,449,450],{},"examples\u002Fgotrue\u002Fdocker-compose.yml"," with ",[214,453,454],{},"examples\u002Fgotrue\u002F.env",", so put your local values there. The example environment enables the OAuth2 server, dynamic registration, passkeys, forwarded-for support, and mailer autoconfirm, which is a reasonable development posture and not one to copy to production.",[178,457,458],{},"With the services up, run the example app:",[401,460,462],{"className":403,"code":461,"filename":405,"language":406,"meta":407,"style":407},"cd examples\u002Fgotrue\ngo run main.go\n",[214,463,464,473],{"__ignoreMap":407},[411,465,466,470],{"class":413,"line":414},[411,467,469],{"class":468},"s2Zo4","cd",[411,471,472],{"class":421}," examples\u002Fgotrue\n",[411,474,475,478,481],{"class":413,"line":429},[411,476,477],{"class":417},"go",[411,479,480],{"class":421}," run",[411,482,483],{"class":421}," main.go\n",[401,485,487],{"className":403,"code":486,"filename":405,"language":406,"meta":407,"style":407},"# sign up through the proxy, not through GoTrue\ncurl -s localhost:8080\u002Fauth\u002Fsignup \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"email\":\"ada@example.com\",\"password\":\"password123\"}'\n\n# call a protected route with the resulting token\ncurl -s localhost:8080\u002Fdashboard -H \"Authorization: Bearer $TOKEN\"\n",[214,488,489,494,509,527,541,548,554],{"__ignoreMap":407},[411,490,491],{"class":413,"line":414},[411,492,493],{"class":425},"# sign up through the proxy, not through GoTrue\n",[411,495,496,499,502,505],{"class":413,"line":429},[411,497,498],{"class":417},"curl",[411,500,501],{"class":421}," -s",[411,503,504],{"class":421}," localhost:8080\u002Fauth\u002Fsignup",[411,506,508],{"class":507},"sTEyZ"," \\\n",[411,510,512,515,519,522,525],{"class":413,"line":511},3,[411,513,514],{"class":421},"  -H",[411,516,518],{"class":517},"sMK4o"," '",[411,520,521],{"class":421},"Content-Type: application\u002Fjson",[411,523,524],{"class":517},"'",[411,526,508],{"class":507},[411,528,530,533,535,538],{"class":413,"line":529},4,[411,531,532],{"class":421},"  -d",[411,534,518],{"class":517},[411,536,537],{"class":421},"{\"email\":\"ada@example.com\",\"password\":\"password123\"}",[411,539,540],{"class":517},"'\n",[411,542,544],{"class":413,"line":543},5,[411,545,547],{"emptyLinePlaceholder":546},true,"\n",[411,549,551],{"class":413,"line":550},6,[411,552,553],{"class":425},"# call a protected route with the resulting token\n",[411,555,557,559,561,564,567,570,573,576],{"class":413,"line":556},7,[411,558,498],{"class":417},[411,560,501],{"class":421},[411,562,563],{"class":421}," localhost:8080\u002Fdashboard",[411,565,566],{"class":421}," -H",[411,568,569],{"class":517}," \"",[411,571,572],{"class":421},"Authorization: Bearer ",[411,574,575],{"class":507},"$TOKEN",[411,577,578],{"class":517},"\"\n",[182,580,582],{"id":581},"refresh-the-golden-fixtures","Refresh the golden fixtures",[178,584,585,586,589],{},"The typed request and response structs are written against captured GoTrue responses, stored as JSON envelopes in ",[214,587,588],{},"auth\u002Ftestdata\u002Fgotrue",":",[401,591,595],{"className":592,"code":593,"language":594,"meta":407,"style":407},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"request\": { \"email\": \"capture@example.com\", \"password\": \"...\" },\n  \"status\": 200,\n  \"response\": { \"access_token\": \"...\", \"token_type\": \"bearer\" }\n}\n","json",[214,596,597,602,657,675,724],{"__ignoreMap":407},[411,598,599],{"class":413,"line":414},[411,600,601],{"class":517},"{\n",[411,603,604,607,611,614,616,619,621,624,626,628,630,633,635,638,640,643,645,647,649,652,654],{"class":413,"line":429},[411,605,606],{"class":517},"  \"",[411,608,610],{"class":609},"spNyl","request",[411,612,613],{"class":517},"\"",[411,615,589],{"class":517},[411,617,618],{"class":517}," {",[411,620,569],{"class":517},[411,622,623],{"class":417},"email",[411,625,613],{"class":517},[411,627,589],{"class":517},[411,629,569],{"class":517},[411,631,632],{"class":421},"capture@example.com",[411,634,613],{"class":517},[411,636,637],{"class":517},",",[411,639,569],{"class":517},[411,641,642],{"class":417},"password",[411,644,613],{"class":517},[411,646,589],{"class":517},[411,648,569],{"class":517},[411,650,651],{"class":421},"...",[411,653,613],{"class":517},[411,655,656],{"class":517}," },\n",[411,658,659,661,664,666,668,672],{"class":413,"line":511},[411,660,606],{"class":517},[411,662,663],{"class":609},"status",[411,665,613],{"class":517},[411,667,589],{"class":517},[411,669,671],{"class":670},"sbssI"," 200",[411,673,674],{"class":517},",\n",[411,676,677,679,682,684,686,688,690,693,695,697,699,701,703,705,707,710,712,714,716,719,721],{"class":413,"line":529},[411,678,606],{"class":517},[411,680,681],{"class":609},"response",[411,683,613],{"class":517},[411,685,589],{"class":517},[411,687,618],{"class":517},[411,689,569],{"class":517},[411,691,692],{"class":417},"access_token",[411,694,613],{"class":517},[411,696,589],{"class":517},[411,698,569],{"class":517},[411,700,651],{"class":421},[411,702,613],{"class":517},[411,704,637],{"class":517},[411,706,569],{"class":517},[411,708,709],{"class":417},"token_type",[411,711,613],{"class":517},[411,713,589],{"class":517},[411,715,569],{"class":517},[411,717,718],{"class":421},"bearer",[411,720,613],{"class":517},[411,722,723],{"class":517}," }\n",[411,725,726],{"class":413,"line":543},[411,727,728],{"class":517},"}\n",[178,730,731],{},"Tests read these instead of talking to a live server, so the suite runs offline and a GoTrue upgrade shows up as a diff in the fixtures.",[178,733,734],{},"To re-capture against a newer GoTrue:",[401,736,738],{"className":403,"code":737,"filename":405,"language":406,"meta":407,"style":407},"make gotrue-up\nmake gotrue-capture\nmake gotrue-down\ngit diff auth\u002Ftestdata\u002Fgotrue\n",[214,739,740,747,754,761],{"__ignoreMap":407},[411,741,742,744],{"class":413,"line":414},[411,743,418],{"class":417},[411,745,746],{"class":421}," gotrue-up\n",[411,748,749,751],{"class":413,"line":429},[411,750,418],{"class":417},[411,752,753],{"class":421}," gotrue-capture\n",[411,755,756,758],{"class":413,"line":511},[411,757,418],{"class":417},[411,759,760],{"class":421}," gotrue-down\n",[411,762,763,766,769],{"class":413,"line":529},[411,764,765],{"class":417},"git",[411,767,768],{"class":421}," diff",[411,770,771],{"class":421}," auth\u002Ftestdata\u002Fgotrue\n",[178,773,774,777,778,781],{},[214,775,776],{},"gotrue-capture"," runs a build-tagged harness (",[214,779,780],{},"go run -tags capture .\u002Fauth\u002Finternal\u002Fgotruecapture\u002F",") that waits for GoTrue's health endpoint, exercises sign-up, token, user, OTP, recovery, logout, OAuth metadata, JWKS, client registration, and passkey options, and writes one file per endpoint. A failed call is written as an error envelope rather than silently skipped, so a broken capture is visible in the diff.",[178,783,784,785,788,789,792,793,796],{},"If a fixture diff shows a new field, add it to the matching struct in ",[214,786,787],{},"auth\u002Fgotrue_endpoints.go",", ",[214,790,791],{},"auth\u002Fgotrue_oauth.go",", or ",[214,794,795],{},"auth\u002Fgotrue_passkey.go",". Existing clients keep working either way, because response bodies are passed through unchanged and the structs only shape the documentation.",[182,798,800],{"id":799},"production-checklist","Production checklist",[802,803,805,810,818,825,832,836,851,855,858,862,868,872,877,881],"steps",{"level":804},"3",[806,807,809],"h3",{"id":808},"share-the-jwt-secret","Share the JWT secret",[178,811,812,814,815,817],{},[214,813,216],{}," and ",[214,816,222],{}," come from the same secret store. Rotating it invalidates every issued token.",[806,819,821,822,824],{"id":820},"point-api_external_url-at-your-prefix","Point ",[214,823,232],{}," at your prefix",[178,826,827,828,831],{},"Public base URL plus the prefix you passed to ",[214,829,830],{},"Mount",". Getting this wrong produces email links and OAuth metadata that bypass or break your proxy.",[806,833,835],{"id":834},"list-your-load-balancer-ranges","List your load balancer ranges",[178,837,838,839,842,843,845,846,850],{},"Set ",[214,840,841],{},"TrustedProxies"," so the client IP is real, and enable ",[214,844,248],{}," in GoTrue. See ",[847,848,849],"a",{"href":116},"Client IP and rate limits",".",[806,852,854],{"id":853},"add-a-rate-limiter","Add a rate limiter",[178,856,857],{},"Sign-in and sign-up are the endpoints attackers care about. A shared Redis limiter covers all replicas.",[806,859,861],{"id":860},"turn-on-audit-logging","Turn on audit logging",[178,863,838,864,867],{},[214,865,866],{},"AuditLogger"," on both the proxy config and the auth provider so proxied calls and token failures land in the same stream.",[806,869,871],{"id":870},"close-what-you-do-not-use","Close what you do not use",[178,873,874,875,850],{},"Disable dynamic client registration, disable passkeys or the OAuth server if unused, and turn off ",[214,876,351],{},[806,878,880],{"id":879},"size-the-http-client","Size the HTTP client",[178,882,883],{},"The default has a 30 second timeout and no tuned connection pool. Give it a transport that matches your traffic.",[182,885,887],{"id":886},"next-steps","Next steps",[370,889,890,896],{},[373,891,892,895],{},[847,893,894],{"href":90},"Roles and permissions"," for authorization once GoTrue has identified the user.",[373,897,898,900],{},[847,899,131],{"href":132}," for how proxied routes appear in your documentation.",[902,903,904],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .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 .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":407,"searchDepth":429,"depth":429,"links":906},[907,908,909,910,911,921],{"id":184,"depth":429,"text":185},{"id":360,"depth":429,"text":361},{"id":387,"depth":429,"text":388},{"id":581,"depth":429,"text":582},{"id":799,"depth":429,"text":800,"children":912},[913,914,916,917,918,919,920],{"id":808,"depth":511,"text":809},{"id":820,"depth":511,"text":915},"Point API_EXTERNAL_URL at your prefix",{"id":834,"depth":511,"text":835},{"id":853,"depth":511,"text":854},{"id":860,"depth":511,"text":861},{"id":870,"depth":511,"text":871},{"id":879,"depth":511,"text":880},{"id":886,"depth":429,"text":887},"Configure GoTrue to sit behind ezz, run it locally with Docker, and refresh the golden fixtures.","md",null,{},{"icon":123},{"title":120,"description":922},"Fanry-8GBXh02wp9SWNxwF0j6wSnsPqxPKZpw-RMROg",[930,932],{"title":115,"path":116,"stem":117,"description":931,"icon":118,"children":-1},"Recover the real client IP behind a load balancer and throttle sensitive auth endpoints with Redis.",{"title":131,"path":132,"stem":133,"description":933,"icon":134,"children":-1},"Generate an OpenAPI 3 document from your handler types and struct tags.",1784970048461]