[{"data":1,"prerenderedAt":559},["ShallowReactive",2],{"docs-nav":3,"docs:\u002Fdocs\u002Ftutorials\u002Fnode-fullstack":139},[4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,127,130,133,136],{"path":5,"title":6},"\u002Fdocs\u002Faccess-gating","Protect a local route",{"path":8,"title":9},"\u002Fdocs\u002Farchitecture\u002Fsecurity-and-trust","Security and trust",{"path":11,"title":12},"\u002Fdocs\u002Fconcepts\u002Fbuilds-and-deployments","Build and deploy",{"path":14,"title":15},"\u002Fdocs\u002Fconcepts\u002Fconfiguration-ownership","Where configuration belongs",{"path":17,"title":18},"\u002Fdocs\u002Fconcepts\u002Fenvironments-and-secrets","Environment values and secrets",{"path":20,"title":21},"\u002Fdocs\u002Fconcepts\u002Fmental-model","How projects fit together",{"path":23,"title":24},"\u002Fdocs\u002Fconcepts\u002Fplans-and-apply","Plans and apply",{"path":26,"title":27},"\u002Fdocs\u002Fconcepts\u002Ftargets-and-runtimes","Choose a target and runtime",{"path":29,"title":30},"\u002Fdocs\u002Fcontribute\u002Freleases","Publish a release",{"path":32,"title":33},"\u002Fdocs\u002Fdevelopment-mounts","Development mounts",{"path":35,"title":36},"\u002Fdocs\u002Fgetting-started","Getting started",{"path":38,"title":39},"\u002Fdocs\u002Fhelp\u002Ffaq","FAQ",{"path":41,"title":42},"\u002Fdocs\u002Fhelp\u002Ftroubleshooting","Troubleshooting",{"path":44,"title":45},"\u002Fdocs\u002Fhow-to\u002Fdeploy-production","Prepare a deployment environment",{"path":47,"title":48},"\u002Fdocs\u002Fhow-to\u002Fswarm-cluster","Run on a multi-node Swarm",{"path":50,"title":51},"\u002Fdocs","mm documentation",{"path":53,"title":54},"\u002Fdocs\u002Fjobs-and-schedules","Jobs and schedules",{"path":56,"title":57},"\u002Fdocs\u002Flocal-dashboard","Local dashboard",{"path":59,"title":60},"\u002Fdocs\u002Flocal-https","Local HTTPS",{"path":62,"title":63},"\u002Fdocs\u002Flocal-services","Local services",{"path":65,"title":66},"\u002Fdocs\u002Fmcp","Let an AI agent work on your project",{"path":68,"title":69},"\u002Fdocs\u002Fmulti-project-hosts","Run multiple projects on one host",{"path":71,"title":72},"\u002Fdocs\u002Fonboarding","Set up a project",{"path":74,"title":75},"\u002Fdocs\u002Fopenbao","Use OpenBao",{"path":77,"title":78},"\u002Fdocs\u002Fproject\u002Fcontributing","Contributing",{"path":80,"title":81},"\u002Fdocs\u002Fproject\u002Flicense","License",{"path":83,"title":84},"\u002Fdocs\u002Fproject\u002Fsecurity","Security",{"path":86,"title":87},"\u002Fdocs\u002Freference\u002Fcapability-matrix","Supported features and platforms",{"path":89,"title":90},"\u002Fdocs\u002Freference\u002Fcli","CLI command reference",{"path":92,"title":93},"\u002Fdocs\u002Freference\u002Fconfiguration","Configuration",{"path":95,"title":96},"\u002Fdocs\u002Freference\u002Fenvironment-variables","Environment variables",{"path":98,"title":99},"\u002Fdocs\u002Freference\u002Ferrors-and-exit-codes","Errors and exit codes",{"path":101,"title":102},"\u002Fdocs\u002Freference\u002Fknown-issues","Known limitations",{"path":104,"title":105},"\u002Fdocs\u002Fremote-access","Manage remote access",{"path":107,"title":108},"\u002Fdocs\u002Fremote-daemon","Set up a remote host",{"path":110,"title":111},"\u002Fdocs\u002Fruntime-observability","Status, logs, and commands",{"path":113,"title":114},"\u002Fdocs\u002Fsecret-delivery","Pass secrets to your app",{"path":116,"title":117},"\u002Fdocs\u002Fsecret-providers","Choose a secret store",{"path":119,"title":120},"\u002Fdocs\u002Fstart\u002Finstall","Install mm",{"path":122,"title":123},"\u002Fdocs\u002Fterminal-ui","Terminal UI",{"path":125,"title":126},"\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api",".NET web API example",{"path":128,"title":129},"\u002Fdocs\u002Ftutorials\u002Ffirst-local-app","First local app",{"path":131,"title":132},"\u002Fdocs\u002Ftutorials\u002Flaravel-rust","Laravel and Rust example",{"path":134,"title":135},"\u002Fdocs\u002Ftutorials\u002Fnode-fullstack","Node full stack example",{"path":137,"title":138},"\u002Fdocs\u002Fvault","Use HashiCorp Vault",{"id":140,"title":135,"body":141,"description":552,"extension":553,"meta":554,"navigation":555,"path":134,"seo":556,"stem":557,"__hash__":558},"docs\u002Fdocs\u002Ftutorials\u002Fnode-fullstack.md",{"type":142,"value":143,"toc":546},"minimark",[144,152,162,167,175,179,268,279,282,290,389,392,406,425,429,528,535,542],[145,146,147,151],"p",{},[148,149,150],"code",{},"examples\u002Fnode-fullstack"," contains a frontend, MongoDB-backed API, and MongoDB\nin one stack. It is the smallest complete local-development example.",[153,154,160],"pre",{"className":155,"code":157,"language":158,"meta":159},[156],"language-text","browser -> frontend -> backend -> MongoDB\n                         |\n                         +-> shared Mailpit\n","text","",[148,161,157],{"__ignoreMap":159},[163,164,166],"h2",{"id":165},"before-you-start","Before you start",[145,168,169,170,174],{},"For initial setup, follow ",[171,172,129],"a",{"href":173},".\u002Ffirst-local-app",". It covers\nworkstation requirements, image repositories, secrets, and deployment. This\npage adds source mounts, email, and debugging commands.",[163,176,178],{"id":177},"inspect-the-project","Inspect the project",[153,180,184],{"className":181,"code":182,"language":183,"meta":159,"style":159},"language-sh shiki shiki-themes mm","cd examples\u002Fnode-fullstack\nmm config validate\nmm env review\nmm dev mounts plan frontend\nmm dev mounts plan backend\nmm config ingress explain frontend\n","sh",[148,185,186,199,211,222,239,253],{"__ignoreMap":159},[187,188,191,195],"span",{"class":189,"line":190},"line",1,[187,192,194],{"class":193},"svrjQ","cd",[187,196,198],{"class":197},"sv8ni"," examples\u002Fnode-fullstack\n",[187,200,202,205,208],{"class":189,"line":201},2,[187,203,204],{"class":193},"mm",[187,206,207],{"class":197}," config",[187,209,210],{"class":197}," validate\n",[187,212,214,216,219],{"class":189,"line":213},3,[187,215,204],{"class":193},[187,217,218],{"class":197}," env",[187,220,221],{"class":197}," review\n",[187,223,225,227,230,233,236],{"class":189,"line":224},4,[187,226,204],{"class":193},[187,228,229],{"class":197}," dev",[187,231,232],{"class":197}," mounts",[187,234,235],{"class":197}," plan",[187,237,238],{"class":197}," frontend\n",[187,240,242,244,246,248,250],{"class":189,"line":241},5,[187,243,204],{"class":193},[187,245,229],{"class":197},[187,247,232],{"class":197},[187,249,235],{"class":197},[187,251,252],{"class":197}," backend\n",[187,254,256,258,260,263,266],{"class":189,"line":255},6,[187,257,204],{"class":193},[187,259,207],{"class":197},[187,261,262],{"class":197}," ingress",[187,264,265],{"class":197}," explain",[187,267,238],{"class":197},[145,269,270,271,274,275,278],{},"Mounts expose each source tree at ",[148,272,273],{},"\u002Fapp",", while separate managed volumes\npreserve ",[148,276,277],{},"node_modules",". Environment values come from the project's bindings\nand its encrypted local secret store.",[163,280,12],{"id":281},"build-and-deploy",[145,283,284,285,289],{},"Complete ",[171,286,288],{"href":287},".\u002Ffirst-local-app#set-up-the-workstation","shared workstation setup",",\nreplace both illustrative image repositories, and use a clean full Git clone.",[153,291,293],{"className":181,"code":292,"language":183,"meta":159,"style":159},"mm secret init age\nmm secret generate --missing\nmm build --publish plan\nmm build --publish apply --plan BUILD_PLAN_HASH --yes\nmm deploy plan\nmm deploy apply --plan DEPLOY_PLAN_HASH --yes\nmm service status\n",[148,294,295,308,321,334,354,363,378],{"__ignoreMap":159},[187,296,297,299,302,305],{"class":189,"line":190},[187,298,204],{"class":193},[187,300,301],{"class":197}," secret",[187,303,304],{"class":197}," init",[187,306,307],{"class":197}," age\n",[187,309,310,312,314,317],{"class":189,"line":201},[187,311,204],{"class":193},[187,313,301],{"class":197},[187,315,316],{"class":197}," generate",[187,318,320],{"class":319},"sbRf1"," --missing\n",[187,322,323,325,328,331],{"class":189,"line":213},[187,324,204],{"class":193},[187,326,327],{"class":197}," build",[187,329,330],{"class":319}," --publish",[187,332,333],{"class":197}," plan\n",[187,335,336,338,340,342,345,348,351],{"class":189,"line":224},[187,337,204],{"class":193},[187,339,327],{"class":197},[187,341,330],{"class":319},[187,343,344],{"class":197}," apply",[187,346,347],{"class":319}," --plan",[187,349,350],{"class":197}," BUILD_PLAN_HASH",[187,352,353],{"class":319}," --yes\n",[187,355,356,358,361],{"class":189,"line":241},[187,357,204],{"class":193},[187,359,360],{"class":197}," deploy",[187,362,333],{"class":197},[187,364,365,367,369,371,373,376],{"class":189,"line":255},[187,366,204],{"class":193},[187,368,360],{"class":197},[187,370,344],{"class":197},[187,372,347],{"class":319},[187,374,375],{"class":197}," DEPLOY_PLAN_HASH",[187,377,353],{"class":319},[187,379,381,383,386],{"class":189,"line":380},7,[187,382,204],{"class":193},[187,384,385],{"class":197}," service",[187,387,388],{"class":197}," status\n",[145,390,391],{},"Automatic HTTPS creates:",[393,394,395,401],"ul",{},[396,397,398],"li",{},[148,399,400],{},"https:\u002F\u002Ffrontend.node-fullstack.test",[396,402,403],{},[148,404,405],{},"https:\u002F\u002Fbackend.node-fullstack.test",[145,407,408,409,412,413,416,417,420,421,424],{},"Use ",[148,410,411],{},"https:\u002F\u002Fmm.test"," for installation status and ",[148,414,415],{},"https:\u002F\u002Fmail.mm.test"," for\nMailpit. Follow project dashboard links from the installation dashboard.\nConfigure ",[148,418,419],{},".test"," DNS or use ",[148,422,423],{},"curl --resolve","; certificates alone do not make\nthe names resolve.",[163,426,428],{"id":427},"exercise-the-app","Exercise the app",[153,430,432],{"className":181,"code":431,"language":183,"meta":159,"style":159},"curl --resolve backend.node-fullstack.test:443:127.0.0.1 \\\n  https:\u002F\u002Fbackend.node-fullstack.test\u002Fhealth\ncurl --resolve backend.node-fullstack.test:443:127.0.0.1 \\\n  -H 'content-type: application\u002Fjson' \\\n  -d '{\"to\":\"developer@example.test\"}' \\\n  https:\u002F\u002Fbackend.node-fullstack.test\u002Fapi\u002Fmail-preview\nmm service logs backend --tail 50\nmm service exec backend -- node --version\n",[148,433,434,449,454,464,474,484,489,507],{"__ignoreMap":159},[187,435,436,439,442,445],{"class":189,"line":190},[187,437,438],{"class":193},"curl",[187,440,441],{"class":319}," --resolve",[187,443,444],{"class":197}," backend.node-fullstack.test:443:127.0.0.1",[187,446,448],{"class":447},"s1Wbj"," \\\n",[187,450,451],{"class":189,"line":201},[187,452,453],{"class":197},"  https:\u002F\u002Fbackend.node-fullstack.test\u002Fhealth\n",[187,455,456,458,460,462],{"class":189,"line":213},[187,457,438],{"class":193},[187,459,441],{"class":319},[187,461,444],{"class":197},[187,463,448],{"class":447},[187,465,466,469,472],{"class":189,"line":224},[187,467,468],{"class":319},"  -H",[187,470,471],{"class":197}," 'content-type: application\u002Fjson'",[187,473,448],{"class":447},[187,475,476,479,482],{"class":189,"line":241},[187,477,478],{"class":319},"  -d",[187,480,481],{"class":197}," '{\"to\":\"developer@example.test\"}'",[187,483,448],{"class":447},[187,485,486],{"class":189,"line":255},[187,487,488],{"class":197},"  https:\u002F\u002Fbackend.node-fullstack.test\u002Fapi\u002Fmail-preview\n",[187,490,491,493,495,498,501,504],{"class":189,"line":380},[187,492,204],{"class":193},[187,494,385],{"class":197},[187,496,497],{"class":197}," logs",[187,499,500],{"class":197}," backend",[187,502,503],{"class":319}," --tail",[187,505,506],{"class":447}," 50\n",[187,508,510,512,514,517,519,522,525],{"class":189,"line":509},8,[187,511,204],{"class":193},[187,513,385],{"class":197},[187,515,516],{"class":197}," exec",[187,518,500],{"class":197},[187,520,521],{"class":319}," --",[187,523,524],{"class":197}," node",[187,526,527],{"class":319}," --version\n",[145,529,530,531,534],{},"Edit either ",[148,532,533],{},"server.js","; the bind mount exposes the change without replacing\ndependencies. A process restart may still be required because this deliberately\nsmall server does not include a file watcher.",[145,536,537,538,541],{},"MongoDB uses its generated password only while initializing an empty volume.\nCoordinate password rotation with the database, and remove project stacks\nthrough a reviewed deployment. Installation service removal is a separate\nreviewed operation; ",[148,539,540],{},"--purge"," destroys retained Mailpit\u002Fgate data.",[543,544,545],"style",{},"html pre.shiki code .svrjQ, html code.shiki .svrjQ{--shiki-default:var(--mm-code-function)}html pre.shiki code .sv8ni, html code.shiki .sv8ni{--shiki-default:var(--mm-code-string)}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 pre.shiki code .sbRf1, html code.shiki .sbRf1{--shiki-default:var(--mm-code-option)}html pre.shiki code .s1Wbj, html code.shiki .s1Wbj{--shiki-default:var(--mm-code-constant)}",{"title":159,"searchDepth":201,"depth":201,"links":547},[548,549,550,551],{"id":165,"depth":201,"text":166},{"id":177,"depth":201,"text":178},{"id":281,"depth":201,"text":12},{"id":427,"depth":201,"text":428},"Run automatic HTTPS, live Node mounts, MongoDB, and shared Mailpit.","md",{},true,{"title":135,"description":552},"docs\u002Ftutorials\u002Fnode-fullstack","hB0HqXXEInn0h79EopZVinSoh5jyQM7p2hURMpOF9tw",1794512546196]