[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates":671,"blog-author-\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates":1045,"i-material-symbols:arrow-back-rounded":1060},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Manage account","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","XlSALC7vYCXHcmcXnjJViwIZKsqnQWF4bn4o9RrcSBE",{"id":87,"extension":5,"links":88,"meta":668,"stem":669,"__hash__":670},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,303,307,311,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,454,458,461,465,469,473,477,481,485,488,491,494,497,501,505,508,512,516,520,524,528,532,536,540,544,548,552,556,559,563,567,571,575,579,582,585,588,592,595,599,603,607,611,614,618,622,625,628,631,635,639,643,646,649,652,656,660,664],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.linuxFlatpak","Linux Flatpak installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fflatpak",{"key":209,"label":210,"href":211},"downloads.guides.linuxSnap","Linux Snap installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide\u002Fsnap",{"key":213,"label":214,"href":215},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":217,"label":218,"href":219},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":221,"label":222,"href":223},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":225,"label":226,"href":227},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":229,"label":230,"href":231},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":233,"label":234,"href":235},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":237,"label":238,"href":239},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":241,"label":242,"href":243},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":245,"label":246,"href":247},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":249,"label":250,"href":251},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":253,"label":254,"href":255},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":257,"label":258,"href":259},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":261,"label":262,"href":263},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":265,"label":266,"href":267},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":269,"label":270,"href":271},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":273,"label":274,"href":275},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":277,"label":278,"href":279},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":281,"label":282,"href":283},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":285,"label":286,"href":287},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":289,"label":290,"href":291},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":293,"label":294,"href":295},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":297,"label":298,"href":299},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":301,"label":302,"href":92},"docs.desktop.download","Desktop download docs",{"key":304,"label":305,"href":306},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":308,"label":309,"href":310},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":312,"label":313,"href":215},"docs.piecesOS.install","PiecesOS install docs",{"key":315,"label":316,"href":317},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":319,"label":320,"href":321},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":323,"label":324,"href":325},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":327,"label":328,"href":329},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":331,"label":332,"href":333},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":335,"label":336,"href":337},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":343,"label":344,"href":345},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":347,"label":348,"href":349},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":351,"label":352,"href":353},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":355,"label":356,"href":357},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":359,"label":360,"href":361},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":363,"label":364,"href":365},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":367,"label":368,"href":369},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":371,"label":372,"href":373},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":375,"label":376,"href":377},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":379,"label":380,"href":381},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":383,"label":384,"href":385},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":387,"label":388,"href":389},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":391,"label":392,"href":393},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":395,"label":396,"href":397},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":399,"label":400,"href":401},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":403,"label":404,"href":405},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":407,"label":408,"href":409},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":411,"label":412,"href":413},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":415,"label":416,"href":417},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":419,"label":420,"href":421},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":423,"label":424,"href":425},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":427,"label":428,"href":429},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":431,"label":432,"href":433},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":435,"label":436,"href":437},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":439,"label":440,"href":441},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":443,"label":444,"href":445},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":447,"label":448,"href":449},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":451,"label":452,"href":453},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":455,"label":456,"href":457},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":459,"label":58,"href":460},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":462,"label":463,"href":464},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":466,"label":467,"href":468},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":470,"label":471,"href":472},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":474,"label":475,"href":476},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":478,"label":479,"href":480},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":482,"label":483,"href":484},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":486,"label":34,"href":487},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":489,"label":43,"href":490},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":492,"label":46,"href":493},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":495,"label":496,"href":493},"social.twitter","Twitter",{"key":498,"label":499,"href":500},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":502,"label":503,"href":504},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":506,"label":49,"href":507},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":509,"label":510,"href":511},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":513,"label":514,"href":515},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":517,"label":518,"href":519},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":521,"label":522,"href":523},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":525,"label":526,"href":527},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":529,"label":530,"href":531},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":533,"label":534,"href":535},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":537,"label":538,"href":539},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":541,"label":542,"href":543},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":545,"label":546,"href":547},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":549,"label":550,"href":551},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":553,"label":554,"href":555},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":557,"label":558,"href":255},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":560,"label":561,"href":562},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":564,"label":565,"href":566},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":568,"label":569,"href":570},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":572,"label":573,"href":574},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":576,"label":577,"href":578},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":580,"label":581,"href":66},"legal.privacyPolicy","Privacy policy",{"key":583,"label":584,"href":69},"legal.refundPolicy","Refund policy",{"key":586,"label":587,"href":72},"legal.terms","Terms",{"key":589,"label":590,"href":591},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":593,"label":594,"href":511},"videos.youtubeChannel","YouTube channel",{"key":596,"label":597,"href":598},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":600,"label":601,"href":602},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":604,"label":605,"href":606},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":608,"label":609,"href":610},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":612,"label":613,"href":527},"sales.feedback","Feedback discussions",{"key":615,"label":616,"href":617},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":619,"label":620,"href":621},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":623,"label":624,"href":19},"routes.home","Home route",{"key":626,"label":627,"href":56},"routes.about","About route",{"key":629,"label":630,"href":12},"routes.downloads","Downloads route",{"key":632,"label":633,"href":634},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":636,"label":637,"href":638},"routes.pricing","Pricing route","\u002Fpricing",{"key":640,"label":641,"href":642},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":644,"label":645,"href":22},"routes.enterprise","Enterprise route",{"key":647,"label":648,"href":62},"routes.contact","Contact route",{"key":650,"label":651,"href":59},"routes.updates","Updates route",{"key":653,"label":654,"href":655},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":657,"label":658,"href":659},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":661,"label":662,"href":663},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":665,"label":666,"href":667},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","2AvfSWI6bZACH5Kr1ZS3txMLjteRjCjbDR_ul1uRZ9Q",{"id":672,"title":673,"author":674,"authorPhoto":675,"authorPhotoAlt":676,"authorSlug":677,"body":678,"buttonText":1032,"buttonUrl":1032,"category":1033,"date":1034,"description":1035,"draft":1036,"editorsPick":1036,"extension":1037,"featured":1036,"image":1038,"imageAlt":1039,"meta":1040,"navigation":32,"ogImage":1032,"ogImageAlt":1032,"path":1041,"seo":1042,"stem":1043,"tags":1032,"__hash__":1044},"blog\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates.md","Serverside Rendering With Express And EJS Templates","Melvin Kosisochukwu","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fbuilding-a-fullstack-application-with-next-js-and-mongodb\u002Fauthor.jpeg","Melvin Kosisochukwu.","melvin-kosisochukwu",{"type":679,"value":680,"toc":1016},"minimark",[681,693,698,701,704,709,716,720,729,740,743,749,752,756,759,765,794,808,811,817,824,830,833,837,840,844,859,865,869,872,878,881,887,903,909,913,916,922,925,931,939,945,948,954,957,963,971,977,986,992,996,1008],[682,683,684,685,692],"p",{},"Server-side rendering means using a server to generate HTML files. This generation\u002Frendering of HTML files is in response to a URL request to the server. Server-side, unlike client-side rendering, utilizes JavaScript modules to render HTML instead of the browser and DOM element. This article will examine how we can achieve server-side rendering using an ",[686,687,691],"a",{"href":688,"rel":689},"https:\u002F\u002Fexpressjs.com\u002F",[690],"nofollow","Express"," server and EJS for templating.",[694,695,697],"h2",{"id":696},"what-is-ejs","What is EJS?",[682,699,700],{},"EJS is a JavaScript templating language for generating HTML with plain JavaScript. In addition, it provides support for writing JavaScript alongside HTML by utilizing unique tags.",[682,702,703],{},"A template language is a language that allows you to create placeholders that we can substitute for different values within our code. Templating with EJS provides a simple syntax that is easy to understand and aids fast development time. Also, EJS allows you to divide your HTML into sub-templates that can be reused and included in different templates.",[705,706,708],"h3",{"id":707},"ejs-tags-and-uses","EJS tags and uses",[682,710,711],{},[712,713],"img",{"alt":714,"src":715},"A table of EJS tags. ","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fimg-001.png",[694,717,719],{"id":718},"getting-started","Getting Started",[682,721,722,723,728],{},"To get started, we will need to create an express application; to do this, you must have Node.js installed. (You can download Node.js ",[686,724,727],{"href":725,"rel":726},"https:\u002F\u002Fnodejs.org\u002Fen\u002Fdownload\u002F",[690],"here"," if you do not already have it.) After this, create a new folder, \"express-ejs,\" and run the command below in the newly created folder.",[730,731,736],"pre",{"className":732,"code":734,"language":735},[733],"language-text","npm init -y\n","text",[737,738,734],"code",{"__ignoreMap":739},"",[682,741,742],{},"The command will create the new node environment we will need for development. Following this, we will install all required dependencies.",[730,744,747],{"className":745,"code":746,"language":735},[733],"npm install express ejs nodemon\n",[737,748,746],{"__ignoreMap":739},[682,750,751],{},"The code block above will install the Express framework and EJS templating engine.",[705,753,755],{"id":754},"set-up-express-application","Set up Express Application",[682,757,758],{},"In this section, we will set up the Express server. First, create an app.js file and views folder.",[730,760,763],{"className":761,"code":762,"language":735},[733],"const express = require(\"express\");\nconst app = express();\napp.use(express.json());\napp.use(express.static(__dirname + \"\u002Fpublic\"));\napp.set(\"view engine\", \"ejs\");\napp.set(\"views\", \".\u002Fviews\");\nmodule.exports = app;\n",[737,764,762],{"__ignoreMap":739},[682,766,767,768,771,772,777,778,783,784,789,790,793],{},"The ",[737,769,770],{},"express.json()"," is an ",[686,773,776],{"href":774,"rel":775},"http:\u002F\u002Fexpressjs.com\u002Fen\u002Fguide\u002Fusing-middleware.html#using-middleware",[690],"Express middleware"," that allows you to parse requests sent with a ",[686,779,782],{"href":780,"rel":781},"https:\u002F\u002Fwww.json.org\u002Fjson-en.html",[690],"JSON"," payload. We will also specify the folder to serve ",[686,785,788],{"href":786,"rel":787},"https:\u002F\u002Fexpressjs.com\u002Fen\u002Fstarter\u002Fstatic-files.html",[690],"static files"," using ",[737,791,792],{},"express.static()"," middleware; this accepts the directory for the static files as a parameter.",[682,795,796,797,800,801,803,807],{},"The code block above also creates a new Express application that sets up the template engine. In Express, ",[737,798,799],{},"views"," indicate the directory where the template files exist; in this case, we will pass the views folder as the second parameter. Once you specify ",[737,802,799],{},[804,805,806],"em",{},","," Express will load the template engine module internally.",[682,809,810],{},"Following this, we will update the package.json to the code below:",[730,812,815],{"className":813,"code":814,"language":735},[733],"{\n  \"name\": \"express-ejs\",\n    \"version\": \"1.0.0\",\n    \"description\": \"A simple app showing how to render ejs template from an express server.\",\n    \"main\": \"server.js\",\n    \"author\": \"Melvin Kosisoschukwu\",\n    \"license\": \"MIT\",\n    \"scripts\": {\n    \"start\": \"node server.js\",\n      \"start-dev\": \"nodemon server.js\"\n  },\n  \"dependencies\": {\n    \"ejs\": \"^3.1.8\",\n      \"express\": \"^4.18.1\",\n      \"nodemon\": \"^2.0.19\"\n  }\n}\n",[737,816,814],{"__ignoreMap":739},[682,818,819,820,823],{},"In the project folder, create a ",[737,821,822],{},"server.js"," file with the following code:",[730,825,828],{"className":826,"code":827,"language":735},[733],"const app = require(\".\u002Fapp\");\nconst PORT = process.env.PORT || 4400;\napp.listen(PORT, () => {\n  console.log(\"Server is running on port \" + PORT);\n});\n",[737,829,827],{"__ignoreMap":739},[682,831,832],{},"The code block above will create a new Express server that listens for connections between the specified host and port.",[694,834,836],{"id":835},"ejs","EJS",[682,838,839],{},"After bootstrapping the Express server, we will work on the template engine in the views folder. We will first set up the header and footer as partials; these are sub-templates you would like to reuse across other templates.",[705,841,843],{"id":842},"styling-headers-and-footers","Styling headers and footers",[682,845,846,847,852,853,858],{},"In the views folder, create a partials folder with two files; ",[686,848,851],{"href":849,"rel":850},"https:\u002F\u002Fgithub.com\u002FMelvinManni\u002Fexpress-ejs\u002Fblob\u002Fmain\u002Fviews\u002Fpartials\u002Fheader.ejs",[690],"header.ejs"," and ",[686,854,857],{"href":855,"rel":856},"https:\u002F\u002Fgithub.com\u002FMelvinManni\u002Fexpress-ejs\u002Fblob\u002Fmain\u002Fviews\u002Fpartials\u002Ffooter.ejs",[690],"footer.ejs",". Partials are added to other files using include; this accepts the file path as a value. The usage for include is demonstrated below:",[730,860,863],{"className":861,"code":862,"language":735},[733],"\u003C%- include(\"partials\u002Fheader.ejs\") -%>\n",[737,864,862],{"__ignoreMap":739},[705,866,868],{"id":867},"serving-a-template-from-an-express-application","Serving a template from an Express application",[682,870,871],{},"The next step will be to set up the pages for the application and serve them from the Express application. First, we will create an index.ejs file with the following code:",[730,873,876],{"className":874,"code":875,"language":735},[733],"\u003C%- include(\"partials\u002Fheader.ejs\") -%>  \n    **          Home Page                      View Posts            \n  \u003C%- include(\"partials\u002Ffooter.ejs\") -%>\n",[737,877,875],{"__ignoreMap":739},[682,879,880],{},"In the code block above, we added the header and footer using include in the file and the information we want for the home page. Next, we will serve the index.ejs page from the Express app:",[730,882,885],{"className":883,"code":884,"language":735},[733],"const express = require(\"express\");\nconst app = express();\napp.use(express.json());\napp.use(express.static(__dirname + \"\u002Fpublic\"));\napp.set(\"view engine\", \"ejs\");\napp.set(\"views\", \".\u002Fviews\");\nconst posts = [\n  {\n    id: \"1\",\n    title: \"Post 1\",\n    body: \"This is post 1\",\n  },\n  {\n    id: \"2\",\n    title: \"Post 2\",\n    body: \"This is post 2\",\n  },\n  {\n    id: \"3\",\n    title: \"Post 3\",\n    body: \"This is post 3\",\n  },\n];\napp.get(\"\u002F\", (req, res) => {\n  res.render(\"index\", {});\n});\nmodule.exports = app;\n",[737,886,884],{"__ignoreMap":739},[682,888,889,890,893,894,897,898,902],{},"From the code block above, we have a method that responds to GET requests on the \"\u002F\" route. Within the method, we render the index file as a response by calling the ",[737,891,892],{},"res.render()"," method; this accepts two parameters: the file's name to render and the data to pass to the file. To test this, we will run ",[737,895,896],{},"npm start-dev"," in the terminal. Visit",[686,899,900],{"href":900,"rel":901},"http:\u002F\u002Flocalhost:4400\u002F",[690]," on your web browser; you should see the index.ejs page rendered.",[682,904,905],{},[712,906],{"alt":907,"src":908},"The rendered index file. ","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fimg-002.png",[705,910,912],{"id":911},"injecting-dynamic-data-into-the-ejs-template","Injecting dynamic data into the EJS template",[682,914,915],{},"Following the previous section, we will look at how to use the data passed to the EJS template. In the views folder, create a posts.ejs file with the following code:",[730,917,920],{"className":918,"code":919,"language":735},[733],"\u003C%- include(\"partials\u002Fheader.ejs\") -%>  \n          Posts              \u003C% for (let post of posts) { %>                              \u003C%= post.title %>              \u003C%= post.body %>                                  View Post                                                      \u003C% } %>                      \n          \u003C%- include(\"partials\u002Ffooter.ejs\") -%>\n",[737,921,919],{"__ignoreMap":739},[682,923,924],{},"The template above expects the \"posts\" variable to exist in the data injected on a template render. Using the EJS template tags, we will loop through posts passed to the template and render the HTML file for each post data. In the Express app, we will add the code block below the GET method for the index route to render the posts.ejs file:",[730,926,929],{"className":927,"code":928,"language":735},[733],"...\napp.get(\"\u002Fposts\", (\n  req, res) => {res.render(\"posts\", { posts });\n               } );\n...\n",[737,930,928],{"__ignoreMap":739},[682,932,933,934,938],{},"From the code block above, we will render the posts.ejs file with the posts variable passed to the template. We can preview the posts page by visiting",[686,935,936],{"href":936,"rel":937},"http:\u002F\u002Flocalhost:4400\u002Fposts",[690],".",[682,940,941],{},[712,942],{"alt":943,"src":944},"Three posts on the rendered home page. ","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fimg-003.png",[682,946,947],{},"Next, we will set up a dynamic page that renders individual posts. But, first, we will create a post.ejs file with the code:",[730,949,952],{"className":950,"code":951,"language":735},[733],"\u003C%- include(\"partials\u002Fheader.ejs\") -%>  \n    \u003C%= title %>    \n      \u003C%= body %>\n      \u003C%- include(\"partials\u002Ffooter.ejs\") -%>\n",[737,953,951],{"__ignoreMap":739},[682,955,956],{},"The code block will accept a data object with the keys title and body. Using EJS tags, we will display the value of the keys in the HTML. Finally, we will add the code block in the app.js to render the post page:",[730,958,961],{"className":959,"code":960,"language":735},[733],"...\napp.get(\"\u002Fpost\u002F:id\", (req, res) => {\n  const post = posts.find(post => post.id === req.params.id);\n  res.render(\"post\", post);\n} );\napp.all(\"*\", (req, res) => {\n  res.status(404).send(\"404 Not Found\");\n} );\nmodule.exports = app;\n",[737,962,960],{"__ignoreMap":739},[682,964,965,966,970],{},"In the GET method, we have an id parameter passed to the request URL. We will use the id parameter to find the needed post from the posts variable and pass it to the post.ejs template. We can test this by visiting",[686,967,968],{"href":968,"rel":969},"http:\u002F\u002Flocalhost:4400\u002Fpost\u002F1",[690],", 1 being the id for the post we want to fetch.",[682,972,973],{},[712,974],{"alt":975,"src":976},"Navigating between posts and the homepage.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fimg-004.gif",[682,978,767,979,982,983,985],{},[737,980,981],{},"app.all()"," method is used to catch all requests that do not match the routes before it; this is why it is after all declared routes. We are using the ",[737,984,981],{}," method to catch all requests to routes that do not exist on our server and return a 404 error.",[682,987,988],{},[712,989],{"alt":990,"src":991},"A 404 error screen.","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fimg-005.png",[694,993,995],{"id":994},"conclusion-and-resources","Conclusion and resources",[682,997,998,999,1003,1004,938],{},"This article reviewed how to use EJS templates to create reusable partials and leverage the templates when rendering pages from an Express server. We also covered how to create dynamic pages using an Express server. If you want to learn more about EJS and Express, you can find visit the official documents at",[686,1000,1001],{"href":1001,"rel":1002},"https:\u002F\u002Fejs.co\u002F#docs",[690]," and",[686,1005,1006],{"href":1006,"rel":1007},"http:\u002F\u002Fexpressjs.com\u002Fen\u002Fguide\u002Frouting.html",[690],[682,1009,1010,1011,938],{},"Using the information from this article, I recommend that you try building a simple blog using Express and EJS. You can also review the complete code for the project in this ",[686,1012,1015],{"href":1013,"rel":1014},"https:\u002F\u002Fgithub.com\u002FMelvinManni\u002Fexpress-ejs",[690],"Github Repository",{"title":739,"searchDepth":1017,"depth":1017,"links":1018},2,[1019,1023,1026,1031],{"id":696,"depth":1017,"text":697,"children":1020},[1021],{"id":707,"depth":1022,"text":708},3,{"id":718,"depth":1017,"text":719,"children":1024},[1025],{"id":754,"depth":1022,"text":755},{"id":835,"depth":1017,"text":836,"children":1027},[1028,1029,1030],{"id":842,"depth":1022,"text":843},{"id":867,"depth":1022,"text":868},{"id":911,"depth":1022,"text":912},{"id":994,"depth":1017,"text":995},null,"Software Development","2022-09-12T00:00:00.000Z","Let's learn how to achieve server-side rendering of HTML files with Express and EJS. We'll build a strong foundation in this tutorial.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates\u002Fhero.jpeg","An open laptop with an IDE running.",{},"\u002Fblog\u002Fserverside-rendering-with-express-and-ejs-templates",{"title":673,"description":1035},"blog\u002Fserverside-rendering-with-express-and-ejs-templates","IaDReAZyu3eMcOQHLmCt3w6A7yXOebBxoARfg_Hlr-g",{"id":1046,"title":674,"body":1047,"description":1051,"draft":1036,"extension":1037,"meta":1054,"navigation":32,"path":1055,"photo":1056,"photoAlt":1032,"seo":1057,"stem":1058,"__hash__":1059},"authors\u002Fauthors\u002Fmelvin-kosisochukwu.md",{"type":679,"value":1048,"toc":1052},[1049],[682,1050,1051],{},"Melvin is a JavaScript Engineer, technical writer, blockchain enthusiast, and gamer. A JavaScript lover and an individual who wants to share knowledge.",{"title":739,"searchDepth":1017,"depth":1017,"links":1053},[],{},"\u002Fauthors\u002Fmelvin-kosisochukwu","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Fmelvin-kosisochukwu.jpg",{"title":674,"description":1051},"authors\u002Fmelvin-kosisochukwu","XyP4TmRG3-qr_lWfz9E2PFniwdKm6-F5bI_AHLoO1Ss",{"left":1061,"top":1061,"width":1062,"height":1062,"rotate":1061,"vFlip":1036,"hFlip":1036,"body":1063},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]