[{"data":1,"prerenderedAt":1089},["ShallowReactive",2],{"navigation:en":3,"\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts\u002Fsst:en":311},[4],{"title":5,"path":6,"stem":7,"children":8,"icon":10},"Nuxfire Docs","\u002Fdocs","docs\u002F0.index",[9,11,152],{"title":5,"path":6,"stem":7,"icon":10},"i-lucide-layout-grid",{"title":12,"path":13,"stem":14,"children":15,"icon":151},"SaaS Starter Kit","\u002Fdocs\u002Fsaas-starter-kit","docs\u002F1.saas-starter-kit\u002F0.index",[16,19,63,129],{"title":17,"path":13,"stem":14,"icon":18},"What is the SaaS Starter Kit?","i-lucide-info",{"title":20,"icon":21,"hide":22,"path":23,"stem":24,"children":25,"page":62},"Getting Started","i-lucide-play",true,"\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started","docs\u002F1.saas-starter-kit\u002F1.getting-started",[26,30,34,38,42,46,50,54,58],{"title":27,"path":28,"stem":29},"Quick Start","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fquick-start","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F0.quick-start",{"title":31,"path":32,"stem":33},"Installation","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Finstallation","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F1.installation",{"title":35,"path":36,"stem":37},"Cloudflare Access","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fcloudflare-access","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F2.cloudflare-access",{"title":39,"path":40,"stem":41},"Configuration","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fconfiguration","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F3.configuration",{"title":43,"path":44,"stem":45},"Secrets","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fsecrets","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F4.secrets",{"title":47,"path":48,"stem":49},"Environment Variables","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fenvironment-variables","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F5.environment-variables",{"title":51,"path":52,"stem":53},"Deploy","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fdeploy","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F6.deploy",{"title":55,"path":56,"stem":57},"Local Development","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Flocal-development","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F7.local-development",{"title":59,"path":60,"stem":61},"Project Structure","\u002Fdocs\u002Fsaas-starter-kit\u002Fgetting-started\u002Fproject-structure","docs\u002F1.saas-starter-kit\u002F1.getting-started\u002F8.project-structure",false,{"title":64,"icon":65,"hide":22,"path":66,"stem":67,"children":68,"page":62},"Features","i-lucide-box","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures","docs\u002F1.saas-starter-kit\u002F2.features",[69,73,77,81,85,89,93,97,101,105,109,113,117,121,125],{"title":70,"path":71,"stem":72},"Authentication","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fauth","docs\u002F1.saas-starter-kit\u002F2.features\u002F1.auth",{"title":74,"path":75,"stem":76},"Rate Limiting","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Frate-limiting","docs\u002F1.saas-starter-kit\u002F2.features\u002F10.rate-limiting",{"title":78,"path":79,"stem":80},"WebSockets","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fwebsockets","docs\u002F1.saas-starter-kit\u002F2.features\u002F11.websockets",{"title":82,"path":83,"stem":84},"Blog","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fblog","docs\u002F1.saas-starter-kit\u002F2.features\u002F14.blog",{"title":86,"path":87,"stem":88},"Documentation","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fdocumentation","docs\u002F1.saas-starter-kit\u002F2.features\u002F15.documentation",{"title":90,"path":91,"stem":92},"Analytics","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fanalytics","docs\u002F1.saas-starter-kit\u002F2.features\u002F16.analytics",{"title":94,"path":95,"stem":96},"Platform Admin Console","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fplatform-admin","docs\u002F1.saas-starter-kit\u002F2.features\u002F17.platform-admin",{"title":98,"path":99,"stem":100},"Database","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fdatabase","docs\u002F1.saas-starter-kit\u002F2.features\u002F2.database",{"title":102,"path":103,"stem":104},"Payments & Billing","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fpayments","docs\u002F1.saas-starter-kit\u002F2.features\u002F3.payments",{"title":106,"path":107,"stem":108},"Emails","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Femails","docs\u002F1.saas-starter-kit\u002F2.features\u002F4.emails",{"title":110,"path":111,"stem":112},"Notifications","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fnotifications","docs\u002F1.saas-starter-kit\u002F2.features\u002F5.notifications",{"title":114,"path":115,"stem":116},"Role-Based Access Control","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Frbac","docs\u002F1.saas-starter-kit\u002F2.features\u002F6.rbac",{"title":118,"path":119,"stem":120},"Async Jobs","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fasync-jobs","docs\u002F1.saas-starter-kit\u002F2.features\u002F7.async-jobs",{"title":122,"path":123,"stem":124},"Storage","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Fstorage","docs\u002F1.saas-starter-kit\u002F2.features\u002F8.storage",{"title":126,"path":127,"stem":128},"Internationalization","\u002Fdocs\u002Fsaas-starter-kit\u002Ffeatures\u002Finternationalization","docs\u002F1.saas-starter-kit\u002F2.features\u002F9.internationalization",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":62},"Concepts","i-lucide-graduation-cap","\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts","docs\u002F1.saas-starter-kit\u002F3.concepts",[135,139,143,147],{"title":136,"path":137,"stem":138},"Technology Stack","\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts\u002Ftech-stack","docs\u002F1.saas-starter-kit\u002F3.concepts\u002F0.tech-stack",{"title":140,"path":141,"stem":142},"SST.dev","\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts\u002Fsst","docs\u002F1.saas-starter-kit\u002F3.concepts\u002F1.sst",{"title":144,"path":145,"stem":146},"NuxtHub","\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts\u002Fnuxt-hub","docs\u002F1.saas-starter-kit\u002F3.concepts\u002F2.nuxt-hub",{"title":148,"path":149,"stem":150},"Design System & Branding","\u002Fdocs\u002Fsaas-starter-kit\u002Fconcepts\u002Fdesign-system","docs\u002F1.saas-starter-kit\u002F3.concepts\u002F3.design-system","i-lucide-zap",{"title":153,"path":154,"stem":155,"children":156,"icon":159},"Fireskills","\u002Fdocs\u002Ffireskills","docs\u002F2.fireskills\u002F0.index",[157,160,219,249,275,293],{"title":158,"path":154,"stem":155,"icon":159},"What is Fireskills?","i-lucide-flame",{"title":20,"icon":21,"hide":22,"path":161,"stem":162,"children":163,"page":62},"\u002Fdocs\u002Ffireskills\u002Fgetting-started","docs\u002F2.fireskills\u002F1.getting-started",[164,167,171,175,179,183,187,191,195,199,203,207,211,215],{"title":27,"path":165,"stem":166},"\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fquick-start","docs\u002F2.fireskills\u002F1.getting-started\u002F00.quick-start",{"title":168,"path":169,"stem":170},"Workflow & Governance","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fworkflow","docs\u002F2.fireskills\u002F1.getting-started\u002F01.workflow",{"title":172,"path":173,"stem":174},"Project Context","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fproject-context","docs\u002F2.fireskills\u002F1.getting-started\u002F02.project-context",{"title":176,"path":177,"stem":178},"Step 0: Setup","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-setup","docs\u002F2.fireskills\u002F1.getting-started\u002F03.step-setup",{"title":180,"path":181,"stem":182},"Step 1: Inbox","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-inbox","docs\u002F2.fireskills\u002F1.getting-started\u002F04.step-inbox",{"title":184,"path":185,"stem":186},"Step 2: Backlog","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-backlog","docs\u002F2.fireskills\u002F1.getting-started\u002F05.step-backlog",{"title":188,"path":189,"stem":190},"Step 3: Specify","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-specify","docs\u002F2.fireskills\u002F1.getting-started\u002F06.step-specify",{"title":192,"path":193,"stem":194},"Step 4: Validate","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-validate","docs\u002F2.fireskills\u002F1.getting-started\u002F07.step-validate",{"title":196,"path":197,"stem":198},"Step 5: Tasks","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-tasks","docs\u002F2.fireskills\u002F1.getting-started\u002F08.step-tasks",{"title":200,"path":201,"stem":202},"Step 6: TDD\u002FBDD","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-tdd-bdd","docs\u002F2.fireskills\u002F1.getting-started\u002F09.step-tdd-bdd",{"title":204,"path":205,"stem":206},"Step 7: Implement","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-implement","docs\u002F2.fireskills\u002F1.getting-started\u002F10.step-implement",{"title":208,"path":209,"stem":210},"Step 8: Documentator","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fstep-documentator","docs\u002F2.fireskills\u002F1.getting-started\u002F11.step-documentator",{"title":212,"path":213,"stem":214},"Late Changes","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Flate-changes","docs\u002F2.fireskills\u002F1.getting-started\u002F12.late-changes",{"title":216,"path":217,"stem":218},"Other Entry Points","\u002Fdocs\u002Ffireskills\u002Fgetting-started\u002Fother-entry-points","docs\u002F2.fireskills\u002F1.getting-started\u002F13.other-entry-points",{"title":220,"icon":221,"hide":22,"path":222,"stem":223,"children":224,"page":62},"Methodology","i-lucide-git-branch","\u002Fdocs\u002Ffireskills\u002Fmethodology","docs\u002F2.fireskills\u002F2.methodology",[225,229,233,237,241,245],{"title":226,"path":227,"stem":228},"The Three Acts","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Fthree-acts","docs\u002F2.fireskills\u002F2.methodology\u002F0.three-acts",{"title":230,"path":231,"stem":232},"The Three Gates","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Fthree-gates","docs\u002F2.fireskills\u002F2.methodology\u002F1.three-gates",{"title":234,"path":235,"stem":236},"The Canonical Spec","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Fcanonical-spec","docs\u002F2.fireskills\u002F2.methodology\u002F2.canonical-spec",{"title":238,"path":239,"stem":240},"Lifecycle States","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Flifecycle-states","docs\u002F2.fireskills\u002F2.methodology\u002F3.lifecycle-states",{"title":242,"path":243,"stem":244},"Effort Scale","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Feffort-scale","docs\u002F2.fireskills\u002F2.methodology\u002F4.effort-scale",{"title":246,"path":247,"stem":248},"Milestones & Governance","\u002Fdocs\u002Ffireskills\u002Fmethodology\u002Fgovernance-and-milestones","docs\u002F2.fireskills\u002F2.methodology\u002F5.governance-and-milestones",{"title":250,"icon":251,"hide":22,"path":252,"stem":253,"children":254,"page":62},"Skills","i-lucide-layers","\u002Fdocs\u002Ffireskills\u002Fskills","docs\u002F2.fireskills\u002F3.skills",[255,259,263,267,271],{"title":256,"path":257,"stem":258},"Catalog","\u002Fdocs\u002Ffireskills\u002Fskills\u002Fcatalog","docs\u002F2.fireskills\u002F3.skills\u002F0.catalog",{"title":260,"path":261,"stem":262},"Act I: Define","\u002Fdocs\u002Ffireskills\u002Fskills\u002Fact-1-define","docs\u002F2.fireskills\u002F3.skills\u002F1.act-1-define",{"title":264,"path":265,"stem":266},"Act II: Design & Prove","\u002Fdocs\u002Ffireskills\u002Fskills\u002Fact-2-design-prove","docs\u002F2.fireskills\u002F3.skills\u002F2.act-2-design-prove",{"title":268,"path":269,"stem":270},"Act III: Deliver","\u002Fdocs\u002Ffireskills\u002Fskills\u002Fact-3-deliver","docs\u002F2.fireskills\u002F3.skills\u002F3.act-3-deliver",{"title":272,"path":273,"stem":274},"Governance & Decisions","\u002Fdocs\u002Ffireskills\u002Fskills\u002Fgovernance-and-decisions","docs\u002F2.fireskills\u002F3.skills\u002F4.governance-and-decisions",{"title":276,"icon":277,"hide":22,"path":278,"stem":279,"children":280,"page":62},"Specialists","i-lucide-sparkles","\u002Fdocs\u002Ffireskills\u002Fspecialists","docs\u002F2.fireskills\u002F4.specialists",[281,285,289],{"title":282,"path":283,"stem":284},"Overview","\u002Fdocs\u002Ffireskills\u002Fspecialists\u002Foverview","docs\u002F2.fireskills\u002F4.specialists\u002F0.overview",{"title":286,"path":287,"stem":288},"Nuxfire Stack","\u002Fdocs\u002Ffireskills\u002Fspecialists\u002Fnuxfire-stack","docs\u002F2.fireskills\u002F4.specialists\u002F1.nuxfire-stack",{"title":290,"path":291,"stem":292},"Engineering Specialists","\u002Fdocs\u002Ffireskills\u002Fspecialists\u002Fengineering-specialists","docs\u002F2.fireskills\u002F4.specialists\u002F2.engineering-specialists",{"title":294,"icon":295,"hide":22,"path":296,"stem":297,"children":298,"page":62},"CLI & Tooling","i-lucide-terminal","\u002Fdocs\u002Ffireskills\u002Fcli","docs\u002F2.fireskills\u002F5.cli",[299,303,307],{"title":300,"path":301,"stem":302},"CLI Overview","\u002Fdocs\u002Ffireskills\u002Fcli\u002Foverview","docs\u002F2.fireskills\u002F5.cli\u002F0.overview",{"title":304,"path":305,"stem":306},"Commands","\u002Fdocs\u002Ffireskills\u002Fcli\u002Fcommands","docs\u002F2.fireskills\u002F5.cli\u002F1.commands",{"title":308,"path":309,"stem":310},"Safety Scripts","\u002Fdocs\u002Ffireskills\u002Fcli\u002Fgovernance-scripts","docs\u002F2.fireskills\u002F5.cli\u002F2.governance-scripts",{"id":312,"title":140,"body":313,"description":1084,"extension":1085,"meta":1086,"navigation":22,"path":141,"seo":1087,"stem":142,"__hash__":1088},"docs\u002Fdocs\u002F1.saas-starter-kit\u002F3.concepts\u002F1.sst.md",{"type":314,"value":315,"toc":1078},"minimark",[316,352,357,378,604,640,646,650,661,758,787,831,839,926,936,939,973,977,1039,1074],[317,318,319,326,327,331,332,335,336,339,340,343,344,347,348,351],"p",{},[320,321,325],"a",{"href":322,"rel":323},"https:\u002F\u002Fsst.dev",[324],"nofollow","SST"," is the infrastructure-as-code layer Nuxfire is built on. Every Cloudflare resource — Workers, Hyperdrive, KV, R2, D1, Queues, Durable Objects, Cron, DNS — is a ",[328,329,330],"code",{},"sst.cloudflare.*"," (or plain ",[328,333,334],{},"sst.*",") resource declared in TypeScript under ",[328,337,338],{},"infra\u002F",", never a hand-written ",[328,341,342],{},"wrangler.toml","\u002F",[328,345,346],{},"wrangler.json"," and never a ",[328,349,350],{},"wrangler deploy"," called outside SST.",[353,354,356],"h2",{"id":355},"how-the-pieces-load","How the pieces load",[317,358,359,362,363,366,367,370,371,373,374,377],{},[328,360,361],{},"sst.config.ts"," is the entry point. Its ",[328,364,365],{},"run()"," doesn't list resources itself — it reads every ",[328,368,369],{},".ts"," file in ",[328,372,338],{}," and imports it, merging each file's ",[328,375,376],{},"outputs"," export into the stack's outputs:",[379,380,385],"pre",{"className":381,"code":382,"filename":361,"language":383,"meta":384,"style":384},"language-typescript shiki shiki-themes material-theme-lighter github-light github-dark monokai","async run() {\n  const outputs = {};\n  for (const value of readdirSync(\".\u002Finfra\u002F\").filter((x) => x.endsWith(\".ts\"))) {\n    const result = await import(\".\u002Finfra\u002F\" + value);\n    if (result.outputs) Object.assign(outputs, result.outputs);\n  }\n  return outputs;\n},\n","typescript","",[328,386,387,407,425,504,539,582,588,598],{"__ignoreMap":384},[388,389,392,396,400,403],"span",{"class":390,"line":391},"line",1,[388,393,395],{"class":394},"ss--_","async ",[388,397,399],{"class":398},"sD0ED","run",[388,401,402],{"class":394},"() ",[388,404,406],{"class":405},"swvn1","{\n",[388,408,410,414,418,422],{"class":390,"line":409},2,[388,411,413],{"class":412},"srJo8","  const",[388,415,417],{"class":416},"s91G_"," outputs",[388,419,421],{"class":420},"sGXK2"," =",[388,423,424],{"class":405}," {};\n",[388,426,428,432,436,439,442,445,448,451,455,459,461,464,467,470,472,474,478,480,483,486,488,491,493,495,497,499,502],{"class":390,"line":427},3,[388,429,431],{"class":430},"sRxSC","  for",[388,433,435],{"class":434},"squCx"," (",[388,437,438],{"class":412},"const",[388,440,441],{"class":416}," value",[388,443,444],{"class":420}," of",[388,446,447],{"class":398}," readdirSync",[388,449,450],{"class":434},"(",[388,452,454],{"class":453},"siCPE","\"",[388,456,458],{"class":457},"sLACW",".\u002Finfra\u002F",[388,460,454],{"class":453},[388,462,463],{"class":434},")",[388,465,466],{"class":405},".",[388,468,469],{"class":398},"filter",[388,471,450],{"class":434},[388,473,450],{"class":405},[388,475,477],{"class":476},"sQgqH","x",[388,479,463],{"class":405},[388,481,482],{"class":412}," =>",[388,484,485],{"class":394}," x",[388,487,466],{"class":405},[388,489,490],{"class":398},"endsWith",[388,492,450],{"class":434},[388,494,454],{"class":453},[388,496,369],{"class":457},[388,498,454],{"class":453},[388,500,501],{"class":434},"))) ",[388,503,406],{"class":405},[388,505,507,510,513,515,518,521,523,525,527,529,532,534,536],{"class":390,"line":506},4,[388,508,509],{"class":412},"    const",[388,511,512],{"class":416}," result",[388,514,421],{"class":420},[388,516,517],{"class":430}," await",[388,519,520],{"class":420}," import",[388,522,450],{"class":434},[388,524,454],{"class":453},[388,526,458],{"class":457},[388,528,454],{"class":453},[388,530,531],{"class":420}," +",[388,533,441],{"class":394},[388,535,463],{"class":434},[388,537,538],{"class":405},";\n",[388,540,542,545,547,550,552,554,557,560,562,565,567,569,572,574,576,578,580],{"class":390,"line":541},5,[388,543,544],{"class":430},"    if",[388,546,435],{"class":434},[388,548,549],{"class":394},"result",[388,551,466],{"class":405},[388,553,376],{"class":394},[388,555,556],{"class":434},") ",[388,558,559],{"class":394},"Object",[388,561,466],{"class":405},[388,563,564],{"class":398},"assign",[388,566,450],{"class":434},[388,568,376],{"class":394},[388,570,571],{"class":405},",",[388,573,512],{"class":394},[388,575,466],{"class":405},[388,577,376],{"class":394},[388,579,463],{"class":434},[388,581,538],{"class":405},[388,583,585],{"class":390,"line":584},6,[388,586,587],{"class":405},"  }\n",[388,589,591,594,596],{"class":390,"line":590},7,[388,592,593],{"class":430},"  return",[388,595,417],{"class":394},[388,597,538],{"class":405},[388,599,601],{"class":390,"line":600},8,[388,602,603],{"class":405},"},\n",[317,605,606,607,610,611,610,614,610,617,610,620,610,623,610,626,610,629,610,632,635,636,639],{},"So ",[328,608,609],{},"infra\u002Fdatabase.ts",", ",[328,612,613],{},"infra\u002Fauth.ts",[328,615,616],{},"infra\u002Fapp.ts",[328,618,619],{},"infra\u002Fjobs.ts",[328,621,622],{},"infra\u002Fwebsockets.ts",[328,624,625],{},"infra\u002Fcron.ts",[328,627,628],{},"infra\u002Fweb.ts",[328,630,631],{},"infra\u002Femails.ts",[328,633,634],{},"infra\u002Fdns.ts",", and ",[328,637,638],{},"infra\u002Fsecret.ts"," are each just a module that declares its own resources — there's no central \"stack\" file to keep in sync.",[317,641,642,645],{},[328,643,644],{},"home: \"cloudflare\""," in the same config means SST's own state (what's deployed, resource IDs) is stored in your Cloudflare account, not AWS — no separate AWS account is needed anywhere in this setup.",[353,647,649],{"id":648},"stages","Stages",[317,651,652,653,657,658,660],{},"A ",[654,655,656],"strong",{},"stage"," is an isolated, named deployment — its own Workers, its own database connection, its own secrets. ",[328,659,634],{}," is what turns a stage name into a domain:",[379,662,664],{"className":381,"code":663,"filename":634,"language":383,"meta":384,"style":384},"export const domain =\n  $app.stage === \"production\"\n    ? branding.domain\n    : `${$app.stage}.dev.${branding.domain}`;\n",[328,665,666,680,702,715],{"__ignoreMap":384},[388,667,668,671,674,677],{"class":390,"line":391},[388,669,670],{"class":430},"export",[388,672,673],{"class":412}," const",[388,675,676],{"class":416}," domain",[388,678,679],{"class":420}," =\n",[388,681,682,685,687,690,693,696,699],{"class":390,"line":409},[388,683,684],{"class":394},"  $app",[388,686,466],{"class":405},[388,688,689],{"class":394},"stage ",[388,691,692],{"class":420},"===",[388,694,695],{"class":453}," \"",[388,697,698],{"class":457},"production",[388,700,701],{"class":453},"\"\n",[388,703,704,707,710,712],{"class":390,"line":427},[388,705,706],{"class":420},"    ?",[388,708,709],{"class":394}," branding",[388,711,466],{"class":405},[388,713,714],{"class":394},"domain\n",[388,716,717,720,723,727,730,733,735,738,741,743,746,748,751,753,756],{"class":390,"line":506},[388,718,719],{"class":420},"    :",[388,721,722],{"class":453}," `",[388,724,726],{"class":725},"slF1C","${",[388,728,729],{"class":394},"$app",[388,731,466],{"class":732},"s00De",[388,734,656],{"class":394},[388,736,737],{"class":725},"}",[388,739,740],{"class":457},".dev.",[388,742,726],{"class":725},[388,744,745],{"class":394},"branding",[388,747,466],{"class":732},[388,749,750],{"class":394},"domain",[388,752,737],{"class":725},[388,754,755],{"class":453},"`",[388,757,538],{"class":405},[317,759,760,761,763,764,767,768,771,772,775,776,779,780,783,784,466],{},"The stage named ",[328,762,698],{}," maps to your ",[328,765,766],{},"BRAND_DOMAIN"," (the Branding section of the stage's env file, read by ",[328,769,770],{},"scripts\u002Fbranding.ts","); every other stage name maps to ",[328,773,774],{},"\u003Cstage>.dev.\u003CBRAND_DOMAIN>"," — which is why ",[328,777,778],{},"bun run deploy"," with no flags, run by a developer named ",[328,781,782],{},"alex",", deploys to ",[328,785,786],{},"alex.dev.yourdomain.com",[317,788,789,790,792,793,796,797,800,801,803,804,807,808,811,812,815,816,819,820,823,824,826,827,830],{},"Only ",[328,791,698],{}," also serves ",[328,794,795],{},"www.\u003CBRAND_DOMAIN>",": ",[328,798,799],{},"webAliases"," in ",[328,802,634],{}," attaches it to the ",[328,805,806],{},"Web"," Worker as a second Workers Custom Domain, so visitors stay on ",[328,809,810],{},"www"," while the site's canonical, ",[328,813,814],{},"og:url"," and ",[328,817,818],{},"hreflang"," tags (built from ",[328,821,822],{},"SITE_URL",") point at the apex. It is deliberately not a 301: SST's redirect option relies on Page Rules, which Cloudflare's API does not accept for Account API Tokens. Before the first deploy, ",[328,825,810],{}," (and the apex) must have no existing A, AAAA or CNAME record in the zone — Cloudflare rejects a Workers Custom Domain on a hostname that already has one (error ",[328,828,829],{},"100117",").",[317,832,833,835,836,838],{},[328,834,361],{}," also treats ",[328,837,698],{}," differently on purpose:",[379,840,842],{"className":381,"code":841,"filename":361,"language":383,"meta":384,"style":384},"removal: input?.stage === \"production\" ? \"retain\" : \"remove\",\nprotect: [\"production\"].includes(input?.stage),\n",[328,843,844,892],{"__ignoreMap":384},[388,845,846,850,853,856,859,861,863,865,867,869,872,874,877,879,882,884,887,889],{"class":390,"line":391},[388,847,849],{"class":848},"sQqfL","removal",[388,851,852],{"class":405},":",[388,854,855],{"class":394}," input",[388,857,858],{"class":405},"?.",[388,860,689],{"class":394},[388,862,692],{"class":420},[388,864,695],{"class":453},[388,866,698],{"class":457},[388,868,454],{"class":453},[388,870,871],{"class":420}," ?",[388,873,695],{"class":453},[388,875,876],{"class":457},"retain",[388,878,454],{"class":453},[388,880,881],{"class":420}," :",[388,883,695],{"class":453},[388,885,886],{"class":457},"remove",[388,888,454],{"class":453},[388,890,891],{"class":405},",\n",[388,893,894,897,899,902,904,906,908,911,913,916,919,921,924],{"class":390,"line":409},[388,895,896],{"class":848},"protect",[388,898,852],{"class":405},[388,900,901],{"class":394}," [",[388,903,454],{"class":453},[388,905,698],{"class":457},[388,907,454],{"class":453},[388,909,910],{"class":394},"]",[388,912,466],{"class":405},[388,914,915],{"class":398},"includes",[388,917,918],{"class":394},"(input",[388,920,858],{"class":405},[388,922,923],{"class":394},"stage)",[388,925,891],{"class":405},[317,927,928,929,932,933,935],{},"Every other stage's resources are torn down on ",[328,930,931],{},"sst remove","; ",[328,934,698],{},"'s are retained and protected from accidental removal.",[353,937,43],{"id":938},"secrets",[317,940,941,942,945,946,948,949,952,953,955,956,958,959,962,963,343,966,969,970,972],{},"Every ",[328,943,944],{},"sst.Secret"," Nuxfire declares lives in ",[328,947,638],{},", scoped ",[654,950,951],{},"per stage"," — loading a value into your personal dev stage never touches ",[328,954,698],{},"'s vault, and vice versa. See ",[320,957,43],{"href":44}," for the exact ",[328,960,961],{},"sst secret load"," workflow, and note the one exception: ",[328,964,965],{},"CLOUDFLARE_API_TOKEN",[328,967,968],{},"CLOUDFLARE_ACCOUNT_ID"," are never ",[328,971,944],{},"s — SST needs them as real shell environment variables before it can even authenticate to read the vault.",[353,974,976],{"id":975},"deploying","Deploying",[379,978,982],{"className":979,"code":980,"language":981,"meta":384,"style":384},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark monokai","bun run deploy                          # your personal dev stage\nbun run deploy -- --stage production    # production\nbun run deploy -- --stage custom-name   # any other named stage\n","bash",[328,983,984,1000,1021],{"__ignoreMap":384},[388,985,986,990,993,996],{"class":390,"line":391},[388,987,989],{"class":988},"sR7ES","bun",[388,991,992],{"class":457}," run",[388,994,995],{"class":457}," deploy",[388,997,999],{"class":998},"ss7Ak","                          # your personal dev stage\n",[388,1001,1002,1004,1006,1008,1012,1015,1018],{"class":390,"line":409},[388,1003,989],{"class":988},[388,1005,992],{"class":457},[388,1007,995],{"class":457},[388,1009,1011],{"class":1010},"sFhLe"," --",[388,1013,1014],{"class":1010}," --stage",[388,1016,1017],{"class":457}," production",[388,1019,1020],{"class":998},"    # production\n",[388,1022,1023,1025,1027,1029,1031,1033,1036],{"class":390,"line":427},[388,1024,989],{"class":988},[388,1026,992],{"class":457},[388,1028,995],{"class":457},[388,1030,1011],{"class":1010},[388,1032,1014],{"class":1010},[388,1034,1035],{"class":457}," custom-name",[388,1037,1038],{"class":998},"   # any other named stage\n",[317,1040,1041,435,1043,1046,1047,1050,1051,1054,1055,1058,1059,1062,1063,1066,1067,1070,1071,1073],{},[328,1042,778],{},[328,1044,1045],{},"scripts\u002Fdeploy.ts",") runs the preflight check (",[328,1048,1049],{},"scripts\u002Fdoctor.ts",", also available alone as ",[328,1052,1053],{},"bun run doctor",") and then ",[328,1056,1057],{},"sst deploy",", passing the same arguments to both; the ",[328,1060,1061],{},"--"," is required for the ",[328,1064,1065],{},"--stage"," flag to reach them rather than being swallowed by ",[328,1068,1069],{},"bun run",". Calling ",[328,1072,1057],{}," directly works too, but skips the preflight.",[1075,1076,1077],"style",{},"html pre.shiki code .ss--_, html code.shiki .ss--_{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .sD0ED, html code.shiki .sD0ED{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .swvn1, html code.shiki .swvn1{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .srJo8, html code.shiki .srJo8{--shiki-light:#9C3EDA;--shiki-light-font-style:inherit;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#66D9EF;--shiki-sepia-font-style:italic}html pre.shiki code .s91G_, html code.shiki .s91G_{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#F8F8F2}html pre.shiki code .sGXK2, html code.shiki .sGXK2{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .sRxSC, html code.shiki .sRxSC{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit;--shiki-sepia:#F92672;--shiki-sepia-font-style:inherit}html pre.shiki code .squCx, html code.shiki .squCx{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .siCPE, html code.shiki .siCPE{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sLACW, html code.shiki .sLACW{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sQgqH, html code.shiki .sQgqH{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit;--shiki-sepia:#FD971F;--shiki-sepia-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 .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .slF1C, html code.shiki .slF1C{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#F92672}html pre.shiki code .s00De, html code.shiki .s00De{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#F8F8F2}html pre.shiki code .sQqfL, html code.shiki .sQqfL{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#F8F8F2}html pre.shiki code .sR7ES, html code.shiki .sR7ES{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .ss7Ak, html code.shiki .ss7Ak{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit;--shiki-sepia:#88846F;--shiki-sepia-font-style:inherit}html pre.shiki code .sFhLe, html code.shiki .sFhLe{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":384,"searchDepth":409,"depth":409,"links":1079},[1080,1081,1082,1083],{"id":355,"depth":409,"text":356},{"id":648,"depth":409,"text":649},{"id":938,"depth":409,"text":43},{"id":975,"depth":409,"text":976},"How Nuxfire uses SST to define its Cloudflare infrastructure as code, and what a stage actually is.","md",{},{"title":140,"description":1084},"seF-7IaxytT0Ju3zHCRWY9gyX8Tju42mxG610rqs7_4",1790707485288]