CINXE.COM
Express Tutorial Part 2: Creating a skeleton website - Learn web development | MDN
<!doctype html><html lang="en-US" prefix="og: https://ogp.me/ns#"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><link rel="icon" href="https://developer.mozilla.org/favicon-48x48.bc390275e955dacb2e65.png"/><link rel="apple-touch-icon" href="https://developer.mozilla.org/apple-touch-icon.528534bba673c38049c2.png"/><meta name="theme-color" content="#ffffff"/><link rel="manifest" href="https://developer.mozilla.org/manifest.f42880861b394dd4dc9b.json"/><link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="MDN Web Docs"/><title>Express Tutorial Part 2: Creating a skeleton website - Learn web development | MDN</title><link rel="alternate" title="Express Tutorial Teil 2: Erstellung eines Skelett-Webauftritts" href="https://developer.mozilla.org/de/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="de"/><link rel="alternate" title="Express Tutorial Part 2: Creating a skeleton website" href="https://developer.mozilla.org/es/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="es"/><link rel="alternate" title="Express チュートリアル Part 2: スケルトンウェブサイトの作成" href="https://developer.mozilla.org/ja/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="ja"/><link rel="alternate" title="Express Tutorial Parte 2: Criando a estrutura do website" href="https://developer.mozilla.org/pt-BR/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="pt"/><link rel="alternate" title="Учебник Express часть 2: Создание скелета сайта" href="https://developer.mozilla.org/ru/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="ru"/><link rel="alternate" title="Express 教程 2:创建站点框架" href="https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="zh"/><link rel="alternate" title="Express 教學 2: 創建一個骨架網站" href="https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="zh-Hant"/><link rel="alternate" title="Express Tutorial Part 2: Creating a skeleton website" href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website" hrefLang="en"/><link rel="preload" as="font" type="font/woff2" href="/static/media/Inter.var.c2fe3cb2b7c746f7966a.woff2" crossorigin=""/><link rel="alternate" type="application/rss+xml" title="MDN Blog RSS Feed" href="https://developer.mozilla.org/en-US/blog/rss.xml" hrefLang="en"/><meta name="description" content="You have now created a skeleton website project for the Local Library and verified that it runs using node. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library."/><meta property="og:url" content="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website"/><meta property="og:title" content="Express Tutorial Part 2: Creating a skeleton website - Learn web development | MDN"/><meta property="og:type" content="website"/><meta property="og:locale" content="en_US"/><meta property="og:description" content="You have now created a skeleton website project for the Local Library and verified that it runs using node. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library."/><meta property="og:image" content="https://developer.mozilla.org/mdn-social-share.d893525a4fb5fb1f67a2.png"/><meta property="og:image:type" content="image/png"/><meta property="og:image:height" content="1080"/><meta property="og:image:width" content="1920"/><meta property="og:image:alt" content="The MDN Web Docs logo, featuring a blue accent color, displayed on a solid black background."/><meta property="og:site_name" content="MDN Web Docs"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:creator" content="MozDevNet"/><link rel="canonical" href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website"/><style media="print">.article-actions-container,.document-toc-container,.language-menu,.main-menu-toggle,.on-github,.page-footer,.place,.sidebar,.top-banner,.top-navigation-main,ul.prev-next{display:none!important}.main-page-content,.main-page-content pre{padding:2px}.main-page-content pre{border-left-width:2px}</style><script src="/static/js/gtag.js" defer=""></script><script defer="" src="/static/js/main.4e767e67.js"></script><link href="/static/css/main.26c64ea7.css" rel="stylesheet"/></head><body><script>if(document.body.addEventListener("load",(t=>{t.target.classList.contains("interactive")&&t.target.setAttribute("data-readystate","complete")}),{capture:!0}),window&&document.documentElement){const t={light:"#ffffff",dark:"#1b1b1b"};try{const e=window.localStorage.getItem("theme");e&&(document.documentElement.className=e,document.documentElement.style.backgroundColor=t[e]);const o=window.localStorage.getItem("nop");o&&(document.documentElement.dataset.nop=o)}catch(t){console.warn("Unable to read theme from localStorage",t)}}</script><div id="root"><ul id="nav-access" class="a11y-nav"><li><a id="skip-main" href="#content">Skip to main content</a></li><li><a id="skip-search" href="#top-nav-search-input">Skip to search</a></li><li><a id="skip-select-language" href="#languages-switcher-button">Skip to select language</a></li></ul><div class="page-wrapper category-learn document-page"><div class="top-banner loading"><section class="place top container"></section></div><div class="sticky-header-container"><header class="top-navigation "><div class="container "><div class="top-navigation-wrap"><a href="/en-US/" class="logo" aria-label="MDN homepage"><svg id="mdn-docs-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 694.9 104.4" style="enable-background:new 0 0 694.9 104.4" xml:space="preserve" role="img"><title>MDN Web Docs</title><path d="M40.3 0 11.7 92.1H0L28.5 0h11.8zm10.4 0v92.1H40.3V0h10.4zM91 0 62.5 92.1H50.8L79.3 0H91zm10.4 0v92.1H91V0h10.4z" class="logo-m"></path><path d="M627.9 95.6h67v8.8h-67v-8.8z" class="logo-_"></path><path d="M367 42h-4l-10.7 30.8h-5.5l-10.8-26h-.4l-10.5 26h-5.2L308.7 42h-3.8v-5.6H323V42h-6.5l6.8 20.4h.4l10.3-26h4.7l11.2 26h.5l5.7-20.3h-6.2v-5.6H367V42zm34.9 20c-.4 3.2-2 5.9-4.7 8.2-2.8 2.3-6.5 3.4-11.3 3.4-5.4 0-9.7-1.6-13.1-4.7-3.3-3.2-5-7.7-5-13.7 0-5.7 1.6-10.3 4.7-14s7.4-5.5 12.9-5.5c5.1 0 9.1 1.6 11.9 4.7s4.3 6.9 4.3 11.3c0 1.5-.2 3-.5 4.7h-25.6c.3 7.7 4 11.6 10.9 11.6 2.9 0 5.1-.7 6.5-2 1.5-1.4 2.5-3 3-4.9l6 .9zM394 51.3c.2-2.4-.4-4.7-1.8-6.9s-3.8-3.3-7-3.3c-3.1 0-5.3 1-6.9 3-1.5 2-2.5 4.4-2.8 7.2H394zm51 2.4c0 5-1.3 9.5-4 13.7s-6.9 6.2-12.7 6.2c-6 0-10.3-2.2-12.7-6.7-.1.4-.2 1.4-.4 2.9s-.3 2.5-.4 2.9h-7.3c.3-1.7.6-3.5.8-5.3.3-1.8.4-3.7.4-5.5V22.3h-6v-5.6H416v27c1.1-2.2 2.7-4.1 4.7-5.7 2-1.6 4.8-2.4 8.4-2.4 4.6 0 8.4 1.6 11.4 4.7 3 3.2 4.5 7.6 4.5 13.4zm-7.7.6c0-4.2-1-7.4-3-9.5-2-2.2-4.4-3.3-7.4-3.3-3.4 0-6 1.2-8 3.7-1.9 2.4-2.9 5-3 7.7V57c0 3 1 5.6 3 7.7s4.5 3.1 7.6 3.1c3.6 0 6.3-1.3 8.1-3.9 1.8-2.7 2.7-5.9 2.7-9.6zm69.2 18.5h-13.2v-7.2c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2 5.7 0 9.8 2.2 12.3 6.5V22.3h-8.6v-5.6h15.8v50.6h6v5.5zM493.2 56v-4.4c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm53.1-1.4c0 5.6-1.8 10.2-5.3 13.7s-8.2 5.3-13.9 5.3-10.1-1.7-13.4-5.1c-3.3-3.4-5-7.9-5-13.5 0-5.3 1.6-9.9 4.7-13.7 3.2-3.8 7.9-5.7 14.2-5.7s11 1.9 14.1 5.7c3 3.7 4.6 8.1 4.6 13.3zm-7.7-.2c0-4-1-7.2-3-9.5s-4.8-3.5-8.2-3.5c-3.6 0-6.4 1.2-8.3 3.7s-2.9 5.6-2.9 9.5c0 3.7.9 6.8 2.8 9.4 1.9 2.6 4.6 3.9 8.3 3.9 3.6 0 6.4-1.3 8.4-3.8 1.9-2.6 2.9-5.8 2.9-9.7zm45 5.8c-.4 3.2-1.9 6.3-4.4 9.1-2.5 2.9-6.4 4.3-11.8 4.3-5.2 0-9.4-1.6-12.6-4.8-3.2-3.2-4.8-7.7-4.8-13.7 0-5.5 1.6-10.1 4.7-13.9 3.2-3.8 7.6-5.7 13.2-5.7 2.3 0 4.6.3 6.7.8 2.2.5 4.2 1.5 6.2 2.9l1.5 9.5-5.9.7-1.3-6.1c-2.1-1.2-4.5-1.8-7.2-1.8-3.5 0-6.1 1.2-7.7 3.7-1.7 2.5-2.5 5.7-2.5 9.6 0 4.1.9 7.3 2.7 9.5 1.8 2.3 4.4 3.4 7.8 3.4 5.2 0 8.2-2.9 9.2-8.8l6.2 1.3zm34.7 1.9c0 3.6-1.5 6.5-4.6 8.5s-7 3-11.7 3c-5.7 0-10.6-1.2-14.6-3.6l1.2-8.8 5.7.6-.2 4.7c1.1.5 2.3.9 3.6 1.1s2.6.3 3.9.3c2.4 0 4.5-.4 6.5-1.3 1.9-.9 2.9-2.2 2.9-4.1 0-1.8-.8-3.1-2.3-3.8s-3.5-1.3-5.8-1.7-4.6-.9-6.9-1.4c-2.3-.6-4.2-1.6-5.7-2.9-1.6-1.4-2.3-3.5-2.3-6.3 0-4.1 1.5-6.9 4.6-8.5s6.4-2.4 9.9-2.4c2.6 0 5 .3 7.2.9 2.2.6 4.3 1.4 6.1 2.4l.8 8.8-5.8.7-.8-5.7c-2.3-1-4.7-1.6-7.2-1.6-2.1 0-3.7.4-5.1 1.1-1.3.8-2 2-2 3.8 0 1.7.8 2.9 2.3 3.6 1.5.7 3.4 1.2 5.7 1.6 2.2.4 4.5.8 6.7 1.4 2.2.6 4.1 1.6 5.7 3 1.4 1.6 2.2 3.7 2.2 6.6zM197.6 73.2h-17.1v-5.5h3.8V51.9c0-3.7-.7-6.3-2.1-7.9-1.4-1.6-3.3-2.3-5.7-2.3-3.2 0-5.6 1.1-7.2 3.4s-2.4 4.6-2.5 6.9v15.6h6v5.5h-17.1v-5.5h3.8V51.9c0-3.8-.7-6.4-2.1-7.9-1.4-1.5-3.3-2.3-5.6-2.3-3.2 0-5.5 1.1-7.2 3.3-1.6 2.2-2.4 4.5-2.5 6.9v15.8h6.9v5.5h-20.2v-5.5h6V42.4h-6.1v-5.6h13.4v6.4c1.2-2.1 2.7-3.8 4.7-5.2 2-1.3 4.4-2 7.3-2s5.3.7 7.5 2.1c2.2 1.4 3.7 3.5 4.5 6.4 1.1-2.5 2.7-4.5 4.9-6.1s4.8-2.4 7.9-2.4c3.5 0 6.5 1.1 8.9 3.3s3.7 5.6 3.7 10.2v18.2h6.1v5.5zm42.5 0h-13.2V66c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2s9.8 2.2 12.3 6.5V22.7h-8.6v-5.6h15.8v50.6h6v5.5zm-13.3-16.8V52c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm61.5 16.8H269v-5.5h6V51.9c0-3.7-.7-6.3-2.2-7.9-1.4-1.6-3.4-2.3-5.7-2.3-3.1 0-5.6 1-7.4 3s-2.8 4.4-2.9 7v15.9h6v5.5h-19.3v-5.5h6V42.4h-6.2v-5.6h13.6V43c2.6-4.6 6.8-6.9 12.7-6.9 3.6 0 6.7 1.1 9.2 3.3s3.7 5.6 3.7 10.2v18.2h6v5.4h-.2z" class="logo-text"></path></svg></a><button title="Open main menu" type="button" class="button action has-icon main-menu-toggle" aria-haspopup="menu" aria-label="Open main menu" aria-expanded="false"><span class="button-wrap"><span class="icon icon-menu "></span><span class="visually-hidden">Open main menu</span></span></button></div><div class="top-navigation-main"><nav class="main-nav" aria-label="Main menu"><ul class="main-menu nojs"><li class="top-level-entry-container "><button type="button" id="references-button" class="top-level-entry menu-toggle" aria-controls="references-menu" aria-expanded="false">References</button><a href="/en-US/docs/Web" class="top-level-entry">References</a><ul id="references-menu" class="submenu references hidden inline-submenu-lg" aria-labelledby="references-button"><li class="apis-link-container mobile-only "><a href="/en-US/docs/Web" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li><li class="html-link-container "><a href="/en-US/docs/Web/HTML" class="submenu-item "><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Structure of content on the web</p></div></a></li><li class="css-link-container "><a href="/en-US/docs/Web/CSS" class="submenu-item "><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Code used to describe document style</p></div></a></li><li class="javascript-link-container "><a href="/en-US/docs/Web/JavaScript" class="submenu-item "><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">General-purpose scripting language</p></div></a></li><li class="http-link-container "><a href="/en-US/docs/Web/HTTP" class="submenu-item "><div class="submenu-icon http"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTTP</div><p class="submenu-item-description">Protocol for transmitting web resources</p></div></a></li><li class="apis-link-container "><a href="/en-US/docs/Web/API" class="submenu-item "><div class="submenu-icon apis"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web APIs</div><p class="submenu-item-description">Interfaces for building web applications</p></div></a></li><li class="apis-link-container "><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web Extensions</div><p class="submenu-item-description">Developing extensions for web browsers</p></div></a></li><li class="apis-link-container desktop-only "><a href="/en-US/docs/Web" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li></ul></li><li class="top-level-entry-container active"><button type="button" id="guides-button" class="top-level-entry menu-toggle" aria-controls="guides-menu" aria-expanded="false">Guides</button><a href="/en-US/docs/Learn" class="top-level-entry">Guides</a><ul id="guides-menu" class="submenu guides hidden inline-submenu-lg" aria-labelledby="guides-button"><li class="apis-link-container mobile-only "><a href="/en-US/docs/Learn" class="submenu-item "><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li class="apis-link-container desktop-only "><a href="/en-US/docs/Learn" class="submenu-item "><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li class="html-link-container "><a href="/en-US/docs/Learn/HTML" class="submenu-item "><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Learn to structure web content with HTML</p></div></a></li><li class="css-link-container "><a href="/en-US/docs/Learn/CSS" class="submenu-item "><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Learn to style content using CSS</p></div></a></li><li class="javascript-link-container "><a href="/en-US/docs/Learn/JavaScript" class="submenu-item "><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">Learn to run scripts in the browser</p></div></a></li><li class=" "><a href="/en-US/docs/Web/Accessibility" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Accessibility</div><p class="submenu-item-description">Learn to make the web accessible to all</p></div></a></li></ul></li><li class="top-level-entry-container "><button type="button" id="mdn-plus-button" class="top-level-entry menu-toggle" aria-controls="mdn-plus-menu" aria-expanded="false">Plus</button><a href="/en-US/plus" class="top-level-entry">Plus</a><ul id="mdn-plus-menu" class="submenu mdn-plus hidden inline-submenu-lg" aria-labelledby="mdn-plus-button"><li class=" "><a href="/en-US/plus" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview</div><p class="submenu-item-description">A customized MDN experience</p></div></a></li><li class=" "><a href="/en-US/plus/ai-help" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">AI Help</div><p class="submenu-item-description">Get real-time assistance and support</p></div></a></li><li class=" "><a href="/en-US/plus/updates" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Updates</div><p class="submenu-item-description">All browser compatibility updates at a glance</p></div></a></li><li class=" "><a href="/en-US/plus/docs/features/overview" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Documentation</div><p class="submenu-item-description">Learn how to use MDN Plus</p></div></a></li><li class=" "><a href="/en-US/plus/docs/faq" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">FAQ</div><p class="submenu-item-description">Frequently asked questions about MDN Plus</p></div></a></li></ul></li><li class="top-level-entry-container "><a class="top-level-entry menu-link" href="/en-US/curriculum/">Curriculum <sup class="new">New</sup></a></li><li class="top-level-entry-container "><a class="top-level-entry menu-link" href="/en-US/blog/">Blog</a></li><li class="top-level-entry-container "><button type="button" id="tools-button" class="top-level-entry menu-toggle" aria-controls="tools-menu" aria-expanded="false">Tools</button><ul id="tools-menu" class="submenu tools hidden inline-submenu-lg" aria-labelledby="tools-button"><li class=" "><a href="/en-US/play" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Playground</div><p class="submenu-item-description">Write, test and share your code</p></div></a></li><li class=" "><a href="/en-US/observatory" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTTP Observatory</div><p class="submenu-item-description">Scan a website for free</p></div></a></li><li class=" "><a href="/en-US/plus/ai-help" class="submenu-item "><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">AI Help</div><p class="submenu-item-description">Get real-time assistance and support</p></div></a></li></ul></li></ul></nav><div class="header-search"><form action="/en-US/search" class="search-form search-widget" id="top-nav-search-form" role="search"><label id="top-nav-search-label" for="top-nav-search-input" class="visually-hidden">Search MDN</label><input aria-activedescendant="" aria-autocomplete="list" aria-controls="top-nav-search-menu" aria-expanded="false" aria-labelledby="top-nav-search-label" autoComplete="off" id="top-nav-search-input" role="combobox" type="search" class="search-input-field" name="q" placeholder=" " required="" value=""/><button type="button" class="button action has-icon clear-search-button"><span class="button-wrap"><span class="icon icon-cancel "></span><span class="visually-hidden">Clear search input</span></span></button><button type="submit" class="button action has-icon search-button"><span class="button-wrap"><span class="icon icon-search "></span><span class="visually-hidden">Search</span></span></button><div id="top-nav-search-menu" role="listbox" aria-labelledby="top-nav-search-label"></div></form></div><div class="theme-switcher-menu"><button type="button" class="button action has-icon theme-switcher-menu small" aria-haspopup="menu"><span class="button-wrap"><span class="icon icon-theme-os-default "></span>Theme</span></button></div><ul class="auth-container"><li><a href="/users/fxa/login/authenticate/?next=%2Fen-US%2Fdocs%2FLearn%2FServer-side%2FExpress_Nodejs%2Fskeleton_website" class="login-link" rel="nofollow">Log in</a></li><li><a href="/users/fxa/login/authenticate/?next=%2Fen-US%2Fdocs%2FLearn%2FServer-side%2FExpress_Nodejs%2Fskeleton_website" target="_self" rel="nofollow" class="button primary mdn-plus-subscribe-link"><span class="button-wrap">Sign up for free</span></a></li></ul></div></div></header><div class="article-actions-container"><div class="container"><button type="button" class="button action has-icon sidebar-button" aria-label="Expand sidebar" aria-expanded="false" aria-controls="sidebar-quicklinks"><span class="button-wrap"><span class="icon icon-sidebar "></span></span></button><nav class="breadcrumbs-container" aria-label="Breadcrumb"><ol typeof="BreadcrumbList" vocab="https://schema.org/" aria-label="breadcrumbs"><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Learn" class="breadcrumb" property="item" typeof="WebPage"><span property="name">Guides</span></a><meta property="position" content="1"/></li><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Learn/Server-side" class="breadcrumb" property="item" typeof="WebPage"><span property="name">Server-side website programming</span></a><meta property="position" content="2"/></li><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Learn/Server-side/Express_Nodejs" class="breadcrumb" property="item" typeof="WebPage"><span property="name">Express web framework (Node.js/JavaScript)</span></a><meta property="position" content="3"/></li><li property="itemListElement" typeof="ListItem"><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="breadcrumb-current-page" property="item" typeof="WebPage"><span property="name">Express Tutorial Part 2: Creating a skeleton website</span></a><meta property="position" content="4"/></li></ol></nav><div class="article-actions"><button type="button" class="button action has-icon article-actions-toggle" aria-label="Article actions"><span class="button-wrap"><span class="icon icon-ellipses "></span><span class="article-actions-dialog-heading">Article Actions</span></span></button><ul class="article-actions-entries"><li class="article-actions-entry"><div class="languages-switcher-menu open-on-focus-within"><button id="languages-switcher-button" type="button" class="button action small has-icon languages-switcher-menu" aria-haspopup="menu"><span class="button-wrap"><span class="icon icon-language "></span>English (US)</span></button><div class="hidden"><ul class="submenu language-menu " aria-labelledby="language-menu-button"><li class=" "><form class="submenu-item locale-redirect-setting"><div class="group"><label class="switch"><input type="checkbox" name="locale-redirect"/><span class="slider"></span><span class="label">Remember language</span></label><a href="https://github.com/orgs/mdn/discussions/739" rel="external noopener noreferrer" target="_blank" title="Enable this setting to automatically switch to this language when it's available. (Click to learn more.)"><span class="icon icon-question-mark "></span></a></div></form></li><li class=" "><a data-locale="de" href="/de/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>Deutsch</span><span title="Diese Übersetzung ist Teil eines Experiments."><span class="icon icon-experimental "></span></span></a></li><li class=" "><a data-locale="es" href="/es/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>Español</span></a></li><li class=" "><a data-locale="ja" href="/ja/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>日本語</span></a></li><li class=" "><a data-locale="pt-BR" href="/pt-BR/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>Português (do Brasil)</span></a></li><li class=" "><a data-locale="ru" href="/ru/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>Русский</span></a></li><li class=" "><a data-locale="zh-CN" href="/zh-CN/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>中文 (简体)</span></a></li><li class=" "><a data-locale="zh-TW" href="/zh-TW/docs/Learn/Server-side/Express_Nodejs/skeleton_website" class="button submenu-item"><span>正體中文 (繁體)</span></a></li></ul></div></div></li></ul></div></div></div></div><div class="main-wrapper"><div class="sidebar-container"><aside id="sidebar-quicklinks" class="sidebar" data-macro="LearnSidebar"><button type="button" class="button action backdrop" aria-label="Collapse sidebar"><span class="button-wrap"></span></button><nav aria-label="Related Topics" class="sidebar-inner"><header class="sidebar-actions"><section class="sidebar-filter-container"><div class="sidebar-filter "><label id="sidebar-filter-label" class="sidebar-filter-label" for="sidebar-filter-input"><span class="icon icon-filter"></span><span class="visually-hidden">Filter sidebar</span></label><input id="sidebar-filter-input" autoComplete="off" class="sidebar-filter-input-field false" type="text" placeholder="Filter" value=""/><button type="button" class="button action has-icon clear-sidebar-filter-button"><span class="button-wrap"><span class="icon icon-cancel "></span><span class="visually-hidden">Clear filter input</span></span></button></div></section></header><div class="sidebar-inner-nav"><div class="in-nav-toc"><div class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list"><li class="document-toc-item "><a class="document-toc-link" href="#overview">Overview</a></li><li class="document-toc-item "><a class="document-toc-link" href="#using_the_application_generator">Using the application generator</a></li><li class="document-toc-item "><a class="document-toc-link" href="#creating_the_project">Creating the project</a></li><li class="document-toc-item "><a class="document-toc-link" href="#running_the_skeleton_website">Running the skeleton website</a></li><li class="document-toc-item "><a class="document-toc-link" href="#enable_server_restart_on_file_changes">Enable server restart on file changes</a></li><li class="document-toc-item "><a class="document-toc-link" href="#the_generated_project">The generated project</a></li><li class="document-toc-item "><a class="document-toc-link" href="#challenge_yourself">Challenge yourself</a></li><li class="document-toc-item "><a class="document-toc-link" href="#summary">Summary</a></li><li class="document-toc-item "><a class="document-toc-link" href="#see_also">See also</a></li></ul></section></div></div><div class="sidebar-body"><ol><li class="section"><a href="/en-US/docs/Learn/Getting_started_with_the_web">Complete beginners start here!</a></li><li><details><summary>Getting started with the web</summary><ol><li><a href="/en-US/docs/Learn/Getting_started_with_the_web">Getting started with the web</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/Installing_basic_software">Installing basic software</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like">What will your website look like?</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/Dealing_with_files">Dealing with files</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics">HTML basics</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/CSS_basics">CSS basics</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics">JavaScript basics</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/Publishing_your_website">Publishing your website</a></li><li><a href="/en-US/docs/Learn/Getting_started_with_the_web/How_the_Web_works">How the web works</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/HTML">HTML — Structuring the web</a></li><li><details><summary>Introduction to HTML</summary><ol><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started">Getting started with HTML</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">What's in the head? Metadata in HTML</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML text fundamentals</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creating hyperlinks</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">Advanced text formatting</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure">Document and website structure</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Debugging HTML</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter">Marking up a letter</a></li><li><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content">Structuring a page of content</a></li></ol></details></li><li><details><summary>Multimedia and embedding</summary><ol><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding">Multimedia and embedding</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Images in HTML</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Video and audio content</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">From object to iframe — other embedding technologies</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Adding vector graphics to the web</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Responsive images</a></li><li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla splash page</a></li></ol></details></li><li><details><summary>HTML tables</summary><ol><li><a href="/en-US/docs/Learn/HTML/Tables">HTML tables</a></li><li><a href="/en-US/docs/Learn/HTML/Tables/Basics">HTML table basics</a></li><li><a href="/en-US/docs/Learn/HTML/Tables/Advanced">HTML table advanced features and accessibility</a></li><li><a href="/en-US/docs/Learn/HTML/Tables/Structuring_planet_data">Structuring planet data</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/CSS">CSS — Styling the web</a></li><li><details><summary>CSS first steps</summary><ol><li><a href="/en-US/docs/Learn/CSS/First_steps">CSS first steps</a></li><li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">What is CSS?</a></li><li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Getting started with CSS</a></li><li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">How CSS is structured</a></li><li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">How CSS works</a></li><li><a href="/en-US/docs/Learn/CSS/First_steps/Styling_a_biography_page">Styling a biography page</a></li></ol></details></li><li><details><summary>CSS building blocks</summary><ol><li><a href="/en-US/docs/Learn/CSS/Building_blocks">CSS building blocks</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">CSS selectors</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Type, class, and ID selectors</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Attribute selectors</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Pseudo-classes and pseudo-elements</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Combinators</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascade, specificity, and inheritance</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers">Cascade layers</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">The box model</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Backgrounds and borders</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">Handling different text directions</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">Overflowing content</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">CSS values and units</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Sizing items in CSS</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Images, media, and form elements</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Styling tables</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Advanced_styling_effects">Advanced styling effects</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Debugging CSS</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizing your CSS</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Fundamental_CSS_comprehension">Fundamental CSS comprehension</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/Creating_fancy_letterheaded_paper">Creating fancy letterheaded paper</a></li><li><a href="/en-US/docs/Learn/CSS/Building_blocks/A_cool_looking_box">A cool-looking box</a></li></ol></details></li><li><details><summary>Styling text</summary><ol><li><a href="/en-US/docs/Learn/CSS/Styling_text">CSS styling text</a></li><li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Fundamental text and font styling</a></li><li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Styling lists</a></li><li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Styling links</a></li><li><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Web fonts</a></li><li><a href="/en-US/docs/Learn/CSS/Styling_text/Typesetting_a_homepage">Typesetting a community school homepage</a></li></ol></details></li><li><details><summary>CSS layout</summary><ol><li><a href="/en-US/docs/Learn/CSS/CSS_layout">CSS layout</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal Flow</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grids</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column layout</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Responsive design</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Beginner's guide to media queries</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy layout methods</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li><li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental layout comprehension</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/JavaScript">JavaScript — Dynamic client-side scripting</a></li><li><details><summary>JavaScript first steps</summary><ol><li><a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">What is JavaScript?</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">A first splash into JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Storing the information you need — Variables</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Basic math in JavaScript — numbers and operators</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Handling text — strings in JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li><li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Silly story generator</a></li></ol></details></li><li><details><summary>JavaScript building blocks</summary><ol><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks">JavaScript building blocks</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Event_bubbling">Event bubbling</a></li><li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li></ol></details></li><li><details><summary>Introducing JavaScript objects</summary><ol><li><a href="/en-US/docs/Learn/JavaScript/Objects">Introducing JavaScript objects</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_programming">Object-oriented programming</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Classes_in_JavaScript">Classes in JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li><li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li></ol></details></li><li><details><summary>Asynchronous JavaScript</summary><ol><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous">Asynchronous JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">How to use promises</a></li><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API">How to implement a promise-based API</a></li><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing_workers">Introducing workers</a></li><li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Sequencing_animations">Sequencing animations</a></li></ol></details></li><li><details><summary>Client-side web APIs</summary><ol><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs">Client-side web APIs</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introduction to web APIs</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipulating documents</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Fetching data from the server</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">Third-party APIs</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing graphics</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">Video and Audio APIs</a></li><li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Client-side storage</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Forms">Web forms — Working with user data</a></li><li><details><summary>Web form building blocks</summary><ol><li><a href="/en-US/docs/Learn/Forms">Web form building blocks</a></li><li><a href="/en-US/docs/Learn/Forms/Your_first_form">Your first form</a></li><li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">How to structure a web form</a></li><li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Basic native form controls</a></li><li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">The HTML5 input types</a></li><li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Other form controls</a></li><li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Styling web forms</a></li><li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Advanced form styling</a></li><li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">UI pseudo-classes</a></li><li><a href="/en-US/docs/Learn/Forms/Form_validation">Client-side form validation</a></li><li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Sending form data</a></li></ol></details></li><li><details><summary>Advanced web form techniques</summary><ol><li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">How to build custom form controls</a></li><li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li><li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_controls">CSS property compatibility table for form controls</a></li><li><a href="/en-US/docs/Learn/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Accessibility">Accessibility — Make the web usable by everyone</a></li><li><details><summary>Accessibility guides</summary><ol><li><a href="/en-US/docs/Learn/Accessibility">Accessibility</a></li><li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">What is accessibility?</a></li><li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A good basis for accessibility</a></li><li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">CSS and JavaScript accessibility best practices</a></li><li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA basics</a></li><li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Accessible multimedia</a></li><li><a href="/en-US/docs/Learn/Accessibility/Mobile">Mobile accessibility</a></li><li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Assessment: Accessibility troubleshooting</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Performance">Performance — Making websites fast and responsive</a></li><li><details><summary>Performance guides</summary><ol><li><a href="/en-US/docs/Learn/Performance">Web performance</a></li><li><a href="/en-US/docs/Learn/Performance/why_web_performance">The "why" of web performance</a></li><li><a href="/en-US/docs/Learn/Performance/What_is_web_performance">What is web performance?</a></li><li><a href="/en-US/docs/Learn/Performance/Perceived_performance">Perceived performance</a></li><li><a href="/en-US/docs/Learn/Performance/Measuring_performance">Measuring performance</a></li><li><a href="/en-US/docs/Learn/Performance/Multimedia">Multimedia: Images</a></li><li><a href="/en-US/docs/Learn/Performance/video">Multimedia: video</a></li><li><a href="/en-US/docs/Learn/Performance/JavaScript">JavaScript performance optimization</a></li><li><a href="/en-US/docs/Learn/Performance/HTML">HTML performance optimization</a></li><li><a href="/en-US/docs/Learn/Performance/CSS">CSS performance optimization</a></li><li><a href="/en-US/docs/Learn/Performance/business_case_for_performance">The business case for web performance</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/MathML">MathML — Writing mathematics with MathML</a></li><li><details><summary>MathML first steps</summary><ol><li><a href="/en-US/docs/Learn/MathML/First_steps">MathML first steps</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Getting_started">Getting started with MathML</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Text_containers">MathML Text Containers</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Fractions_and_roots">MathML fractions and roots</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Scripts">MathML scripted elements</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Tables">MathML tables</a></li><li><a href="/en-US/docs/Learn/MathML/First_steps/Three_famous_mathematical_formulas">Three famous mathematical formulas</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/../Games">Games — Developing games for the web</a></li><li><details><summary>Guides and tutorials</summary><ol><li><a href="/en-US/docs/Games/Introduction">Introduction to game development for the Web</a></li><li><a href="/en-US/docs/Games/Techniques">Techniques for game development</a></li><li><a href="/en-US/docs/Games/Tutorials">Tutorials</a></li><li><a href="/en-US/docs/Games/Publishing_games">Publishing games</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Tools_and_testing">Tools and testing</a></li><li><details><summary>Client-side web development tools</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools">Understanding client-side web development tools</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview">Client-side tooling overview</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">Command line crash course</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management">Package management basics</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Introducing_complete_toolchain">Introducing a complete toolchain</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Deployment">Deploying our app</a></li></ol></details></li><li><details><summary>Introduction to client-side frameworks</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introduction to client-side frameworks</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Framework main features</a></li></ol></details></li><li><details><summary>React</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Getting started with React</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Beginning our React todo list</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componentizing our React app</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">React interactivity: Events and state</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">React interactivity: Editing, filtering, conditional rendering</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accessibility in React</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">React resources</a></li></ol></details></li><li><details><summary>Ember</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Getting started with Ember</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Ember app structure and componentization</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Ember interactivity: Events, classes and state</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Ember Interactivity: Footer functionality, conditional rendering</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Routing in Ember</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Ember resources and troubleshooting</a></li></ol></details></li><li><details><summary>Vue</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Getting started with Vue</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Creating our first Vue component</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Rendering a list of Vue components</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Adding a new todo form: Vue events, methods, and models</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Styling Vue components with CSS</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Using Vue computed properties</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Vue conditional rendering: editing existing todos</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Vue refs and lifecycle methods for focus management</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Vue resources</a></li></ol></details></li><li><details><summary>Svelte</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started">Getting started with Svelte</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning">Starting our Svelte to-do list app</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props">Dynamic behavior in Svelte: working with variables and props</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components">Componentizing our Svelte app</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_reactivity_lifecycle_accessibility">Advanced Svelte: Reactivity, lifecycle, accessibility</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores">Working with Svelte stores</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_TypeScript">TypeScript support in Svelte</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_deployment_next">Deployment and next steps</a></li></ol></details></li><li><details><summary>Angular</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_getting_started">Getting started with Angular</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_todo_list_beginning">Beginning our Angular todo list app</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_styling">Styling our Angular app</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_item_component">Creating an item component</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_filtering">Filtering our to-do items</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_building">Building Angular applications and further resources</a></li></ol></details></li><li><details><summary>Git and GitHub</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/GitHub">Git and GitHub</a></li></ol></details></li><li><details><summary>Cross browser testing</summary><ol><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">Cross browser testing</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">Introduction to cross-browser testing</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies">Strategies for carrying out testing</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS">Handling common HTML and CSS problems</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript">Handling common JavaScript problems</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility">Handling common accessibility problems</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection">Implementing feature detection</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing">Introduction to automated testing</a></li><li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Setting up your own test automation environment</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Server-side">Server-side website programming</a></li><li><details><summary>First steps</summary><ol><li><a href="/en-US/docs/Learn/Server-side/First_steps">Server-side website programming first steps</a></li><li><a href="/en-US/docs/Learn/Server-side/First_steps/Introduction">Introduction to the server side</a></li><li><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Client-Server Overview</a></li><li><a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Server-side web frameworks</a></li><li><a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a></li></ol></details></li><li><details><summary>Django web framework (Python)</summary><ol><li><a href="/en-US/docs/Learn/Server-side/Django">Django Web Framework (Python)</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Introduction">Django introduction</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/development_environment">Setting up a Django development environment</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django Tutorial: The Local Library website</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Models">Django Tutorial Part 3: Using models</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django Tutorial Part 4: Django admin site</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Authentication">Django Tutorial Part 8: User authentication and permissions</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Part 9: Working with forms</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Tutorial Part 10: Testing a Django web application</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/Deployment">Django Tutorial Part 11: Deploying Django to production</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/web_application_security">Django web application security</a></li><li><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">Assessment: DIY Django mini blog</a></li></ol></details></li><li><details open=""><summary>Express Web Framework (Node.js/JavaScript)</summary><ol><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Express web framework (Node.js/JavaScript)</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node development environment</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li><li><em><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website" aria-current="page">Express Tutorial Part 2: Creating a skeleton website</a></em></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li><li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li></ol></details></li><li class="section"><a href="/en-US/docs/Learn/Common_questions">Further resources</a></li><li><details><summary>Common questions</summary><ol><li><a href="/en-US/docs/Learn/Common_questions">Common questions</a></li><li><a href="/en-US/docs/Learn/HTML/Howto">Use HTML to solve common problems</a></li><li><a href="/en-US/docs/Learn/CSS/Howto">Use CSS to solve common problems</a></li><li><a href="/en-US/docs/Learn/JavaScript/Howto">Solve common problems in your JavaScript code</a></li><li><a href="/en-US/docs/Learn/Common_questions/Web_mechanics">Web mechanics</a></li><li><a href="/en-US/docs/Learn/Common_questions/Tools_and_setup">Tools and setup</a></li><li><a href="/en-US/docs/Learn/Common_questions/Design_and_accessibility">Design and accessibility</a></li></ol></details></li></ol></div></div><section class="place side"></section></nav></aside><div class="toc-container"><aside class="toc"><nav><div class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list"><li class="document-toc-item "><a class="document-toc-link" href="#overview">Overview</a></li><li class="document-toc-item "><a class="document-toc-link" href="#using_the_application_generator">Using the application generator</a></li><li class="document-toc-item "><a class="document-toc-link" href="#creating_the_project">Creating the project</a></li><li class="document-toc-item "><a class="document-toc-link" href="#running_the_skeleton_website">Running the skeleton website</a></li><li class="document-toc-item "><a class="document-toc-link" href="#enable_server_restart_on_file_changes">Enable server restart on file changes</a></li><li class="document-toc-item "><a class="document-toc-link" href="#the_generated_project">The generated project</a></li><li class="document-toc-item "><a class="document-toc-link" href="#challenge_yourself">Challenge yourself</a></li><li class="document-toc-item "><a class="document-toc-link" href="#summary">Summary</a></li><li class="document-toc-item "><a class="document-toc-link" href="#see_also">See also</a></li></ul></section></div></nav></aside><section class="place side"></section></div></div><main id="content" class="main-content "><article class="main-page-content" lang="en-US"><header><h1>Express Tutorial Part 2: Creating a skeleton website</h1></header><div class="section-content"><ul class="prev-next"> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website"><span class="button-wrap"> Previous </span></a></li> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs"><span class="button-wrap"> Overview: Express web framework (Node.js/JavaScript)</span></a></li> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose"><span class="button-wrap"> Next </span></a></li> </ul> <p>This second article in our <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial</a> shows how you can create a "skeleton" website project which you can then go on to populate with site-specific routes, templates/views, and database calls.</p> <figure class="table-container"><table> <tbody> <tr> <th scope="row">Prerequisites:</th> <td> <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Set up a Node development environment</a>. Review the Express Tutorial. </td> </tr> <tr> <th scope="row">Objective:</th> <td>To be able to start your own new website projects using the <em>Express Application Generator</em>.</td> </tr> </tbody> </table></figure></div><section aria-labelledby="overview"><h2 id="overview"><a href="#overview">Overview</a></h2><div class="section-content"><p>This article shows how you can create a "skeleton" website using the <a href="https://expressjs.com/en/starter/generator.html" class="external" target="_blank">Express Application Generator</a> tool, which you can then populate with site-specific routes, views/templates, and database calls. In this case, we'll use the tool to create the framework for our <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Local Library website</a>, to which we'll later add all the other code needed by the site. The process is extremely simple, requiring only that you invoke the generator on the command line with a new project name, optionally also specifying the site's template engine and CSS generator.</p> <p>The following sections show you how to call the application generator, and provides a little explanation about the different view/CSS options. We'll also explain how the skeleton website is structured. At the end, we'll show how you can run the website to verify that it works.</p> <div class="notecard note"> <p><strong>Note:</strong></p> <ul> <li>The <em>Express Application Generator</em> is not the only generator for Express applications, and the generated project is not the only viable way to structure your files and directories. The generated site does however have a modular structure that is easy to extend and understand. For information about a <em>minimal</em> Express application, see <a href="https://expressjs.com/en/starter/hello-world.html" class="external" target="_blank">Hello world example</a> (Express docs).</li> <li> The <em>Express Application Generator</em> declares most variables using <code>var</code>. We have changed most of these to <a href="/en-US/docs/Web/JavaScript/Reference/Statements/const"><code>const</code></a> (and a few to <a href="/en-US/docs/Web/JavaScript/Reference/Statements/let"><code>let</code></a>) in the tutorial, because we want to demonstrate modern JavaScript practice. </li> <li> This tutorial uses the version of <em>Express</em> and other dependencies that are defined in the <strong>package.json</strong> created by the <em>Express Application Generator</em>. These are not (necessarily) the latest version, and you may want to update them when deploying a real application to production. </li> </ul> </div></div></section><section aria-labelledby="using_the_application_generator"><h2 id="using_the_application_generator"><a href="#using_the_application_generator">Using the application generator</a></h2><div class="section-content"><p>You should already have installed the generator as part of <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">setting up a Node development environment</a>. As a quick reminder, you install the generator tool site-wide using the npm package manager, as shown:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>npm install express-generator -g </code></pre></div> <p>The generator has a number of options, which you can view on the command line using the <code>--help</code> (or <code>-h</code>) command:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>> express --help Usage: express [options] [dir] Options: --version output the version number -e, --ejs add ejs engine support --pug add pug engine support --hbs add handlebars engine support -H, --hogan add hogan.js engine support -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade) --no-view use static html instead of view engine -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain CSS) --git add .gitignore -f, --force force on non-empty directory -h, --help output usage information </code></pre></div> <p>You can specify express to create a project inside the <em>current</em> directory using the <em>Jade</em> view engine and plain CSS (if you specify a directory name then the project will be created in a sub-folder with that name).</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>express </code></pre></div> <p>You can also choose a view (template) engine using <code>--view</code> and/or a CSS generation engine using <code>--css</code>.</p> <div class="notecard note"> <p><strong>Note:</strong> The other options for choosing template engines (e.g. <code>--hogan</code>, <code>--ejs</code>, <code>--hbs</code> etc.) are deprecated. Use <code>--view</code> (or <code>-v</code>).</p> </div></div></section><section aria-labelledby="what_view_engine_should_i_use"><h3 id="what_view_engine_should_i_use"><a href="#what_view_engine_should_i_use">What view engine should I use?</a></h3><div class="section-content"><p>The <em>Express Application Generator</em> allows you to configure a number of popular view/templating engines, including <a href="https://www.npmjs.com/package/ejs" class="external" target="_blank">EJS</a>, <a href="https://github.com/pillarjs/hbs" class="external" target="_blank">Hbs</a>, <a href="https://pugjs.org/api/getting-started.html" class="external" target="_blank">Pug</a> (Jade), <a href="https://www.npmjs.com/package/twig" class="external" target="_blank">Twig</a>, and <a href="https://www.npmjs.com/package/vash" class="external" target="_blank">Vash</a>, although it chooses Jade by default if you don't specify a view option. Express itself can also support a large number of other templating languages <a href="https://github.com/expressjs/express/wiki#template-engines" class="external" target="_blank">out of the box</a>.</p> <div class="notecard note"> <p><strong>Note:</strong> If you want to use a template engine that isn't supported by the generator then see <a href="https://expressjs.com/en/guide/using-template-engines.html" class="external" target="_blank">Using template engines with Express</a> (Express docs) and the documentation for your target view engine.</p> </div> <p>Generally speaking, you should select a templating engine that delivers all the functionality you need and allows you to be productive sooner — or in other words, in the same way that you choose any other component! Some of the things to consider when comparing template engines:</p> <ul> <li> <p>Time to productivity — If your team already has experience with a templating language then it is likely they will be productive faster using that language. If not, then you should consider the relative learning curve for candidate templating engines.</p> </li> <li> <p>Popularity and activity — Review the popularity of the engine and whether it has an active community. It is important to be able to get support when problems arise throughout the lifetime of the website.</p> </li> <li> <p>Style — Some template engines use specific markup to indicate inserted content within "ordinary" HTML, while others construct the HTML using a different syntax (for example, using indentation and block names).</p> </li> <li> <p>Performance/rendering time.</p> </li> <li> <p>Features — you should consider whether the engines you look at have the following features available:</p> <ul> <li>Layout inheritance: Allows you to define a base template and then "inherit" just the parts of it that you want to be different for a particular page. This is typically a better approach than building templates by including a number of required components or building a template from scratch each time.</li> <li>"Include" support: Allows you to build up templates by including other templates.</li> <li>Concise variable and loop control syntax.</li> <li>Ability to filter variable values at template level, such as making variables upper-case, or formatting a date value.</li> <li>Ability to generate output formats other than HTML, such as JSON or XML.</li> <li>Support for asynchronous operations and streaming.</li> <li>Client-side features. If a templating engine can be used on the client this allows the possibility of having all or most of the rendering done client-side.</li> </ul> </li> </ul> <div class="notecard note"> <p><strong>Note:</strong> There are many resources on the Internet to help you compare the different options!</p> </div> <p>For this project, we'll use the <a href="https://pugjs.org/api/getting-started.html" class="external" target="_blank">Pug</a> templating engine (this is the recently-renamed Jade engine), as this is one of the most popular Express/JavaScript templating languages and is supported out of the box by the generator.</p></div></section><section aria-labelledby="what_css_stylesheet_engine_should_i_use"><h3 id="what_css_stylesheet_engine_should_i_use"><a href="#what_css_stylesheet_engine_should_i_use">What CSS stylesheet engine should I use?</a></h3><div class="section-content"><p>The <em>Express Application Generator</em> allows you to create a project that is configured to use the most common CSS stylesheet engines: <a href="https://lesscss.org/" class="external" target="_blank">LESS</a>, <a href="https://sass-lang.com/" class="external" target="_blank">SASS</a>, <a href="https://stylus-lang.com/" class="external" target="_blank">Stylus</a>.</p> <div class="notecard note"> <p><strong>Note:</strong> CSS has some limitations that make certain tasks difficult. CSS stylesheet engines allow you to use more powerful syntax for defining your CSS and then compile the definition into plain-old CSS for browsers to use.</p> </div> <p>As with templating engines, you should use the stylesheet engine that will allow your team to be most productive. For this project, we'll use vanilla CSS (the default) as our CSS requirements are not sufficiently complicated to justify using anything else.</p></div></section><section aria-labelledby="what_database_should_i_use"><h3 id="what_database_should_i_use"><a href="#what_database_should_i_use">What database should I use?</a></h3><div class="section-content"><p>The generated code doesn't use/include any databases. <em>Express</em> apps can use any <a href="https://expressjs.com/en/guide/database-integration.html" class="external" target="_blank">database mechanism</a> supported by <em>Node</em> (<em>Express</em> itself doesn't define any specific additional behavior/requirements for database management).</p> <p>We'll discuss how to integrate with a database in a later article.</p></div></section><section aria-labelledby="creating_the_project"><h2 id="creating_the_project"><a href="#creating_the_project">Creating the project</a></h2><div class="section-content"><p>For the sample <em>Local Library</em> app we're going to build, we'll create a project named <em>express-locallibrary-tutorial</em> using the <em>Pug</em> template library and no CSS engine.</p> <p>First, navigate to where you want to create the project and then run the <em>Express Application Generator</em> in the command prompt as shown:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>express express-locallibrary-tutorial --view=pug </code></pre></div> <p>The generator will create (and list) the project's files.</p> <pre class="brush: plain notranslate"> create : express-locallibrary-tutorial\ create : express-locallibrary-tutorial\public\ create : express-locallibrary-tutorial\public\javascripts\ create : express-locallibrary-tutorial\public\images\ create : express-locallibrary-tutorial\public\stylesheets\ create : express-locallibrary-tutorial\public\stylesheets\style.css create : express-locallibrary-tutorial\routes\ create : express-locallibrary-tutorial\routes\index.js create : express-locallibrary-tutorial\routes\users.js create : express-locallibrary-tutorial\views\ create : express-locallibrary-tutorial\views\error.pug create : express-locallibrary-tutorial\views\index.pug create : express-locallibrary-tutorial\views\layout.pug create : express-locallibrary-tutorial\app.js create : express-locallibrary-tutorial\package.json create : express-locallibrary-tutorial\bin\ create : express-locallibrary-tutorial\bin\www change directory: > cd express-locallibrary-tutorial install dependencies: > npm install run the app (Bash (Linux or macOS)) > DEBUG=express-locallibrary-tutorial:* npm start run the app (PowerShell (Windows)) > $ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start run the app (Command Prompt (Windows)): > SET DEBUG=express-locallibrary-tutorial:* & npm start </pre> <p>At the end of the output, the generator provides instructions on how to install the dependencies (as listed in the <strong>package.json</strong> file) and how to run the application on different operating systems.</p> <div class="notecard note"> <p> <strong>Note:</strong> The generator-created files define all variables as <code>var</code>. Open all of the generated files and change the <code>var</code> declarations to <code>const</code> before you continue (the remainder of the tutorial assumes that you have done so). </p> </div></div></section><section aria-labelledby="running_the_skeleton_website"><h2 id="running_the_skeleton_website"><a href="#running_the_skeleton_website">Running the skeleton website</a></h2><div class="section-content"><p>At this point, we have a complete skeleton project. The website doesn't actually <em>do</em> very much yet, but it's worth running it to show that it works.</p> <ol> <li> <p>First, install the dependencies (the <code>install</code> command will fetch all the dependency packages listed in the project's <strong>package.json</strong> file).</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>cd express-locallibrary-tutorial npm install </code></pre></div> </li> <li> <p>Then run the application.</p> <ul> <li> <p>On the Windows CMD prompt, use this command:</p> <div class="code-example"><div class="example-header"><span class="language-name">batch</span></div><pre class="brush: batch notranslate"><code>SET DEBUG=express-locallibrary-tutorial:* & npm start </code></pre></div> </li> <li> <p>On Windows PowerShell, use this command:</p> <div class="code-example"><div class="example-header"><span class="language-name">powershell</span></div><pre class="brush: powershell notranslate"><code>ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start </code></pre></div> <div class="notecard note"> <p><strong>Note:</strong> PowerShell commands are not covered in this tutorial (The provided "Windows" commands assume you're using the Windows CMD prompt.)</p> </div> </li> <li> <p>On macOS or Linux, use this command:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>DEBUG=express-locallibrary-tutorial:* npm start </code></pre></div> </li> </ul> </li> <li> <p>Then load <code>http://localhost:3000/</code> in your browser to access the app.</p> </li> </ol> <p>You should see a browser page that looks like this:</p> <p> <img src="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website/expressgeneratorskeletonwebsite.png" alt="Browser for default Express app generator website" width="576" height="403" loading="lazy"> </p> <p>Congratulations! You now have a working Express application that can be accessed via port 3000.</p> <div class="notecard note"> <p><strong>Note:</strong> You could also start the app just using the <code>npm start</code> command. Specifying the DEBUG variable as shown enables console logging/debugging. For example, when you visit the above page you'll see debug output like this:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>SET DEBUG=express-locallibrary-tutorial:* & npm start </code></pre></div> <pre class="brush: plain notranslate">> express-locallibrary-tutorial@0.0.0 start D:\github\mdn\test\exprgen\express-locallibrary-tutorial > node ./bin/www express-locallibrary-tutorial:server Listening on port 3000 +0ms GET / 304 490.296 ms - - GET /stylesheets/style.css 200 4.886 ms - 111 </pre> </div></div></section><section aria-labelledby="enable_server_restart_on_file_changes"><h2 id="enable_server_restart_on_file_changes"><a href="#enable_server_restart_on_file_changes">Enable server restart on file changes</a></h2><div class="section-content"><p>Any changes you make to your Express website are currently not visible until you restart the server. It quickly becomes very irritating to have to stop and restart your server every time you make a change, so it is worth taking the time to automate restarting the server when needed.</p> <p>A convenient tool for this purpose is <a href="https://github.com/remy/nodemon" class="external" target="_blank">nodemon</a>. This is usually installed globally (as it is a "tool"), but here we'll install and use it locally as a <em>developer dependency</em>, so that any developers working with the project get it automatically when they install the application. Use the following command in the root directory for the skeleton project:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>npm install --save-dev nodemon </code></pre></div> <p>If you still choose to install <a href="https://github.com/remy/nodemon" class="external" target="_blank">nodemon</a> globally to your machine, and not only to your project's <strong>package.json</strong> file:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>npm install -g nodemon </code></pre></div> <p>If you open your project's <strong>package.json</strong> file you'll now see a new section with this dependency:</p> <div class="code-example"><div class="example-header"><span class="language-name">json</span></div><pre class="brush: json notranslate"><code> "devDependencies": { "nodemon": "^3.1.3" } </code></pre></div> <p>Because the tool isn't installed globally we can't launch it from the command line (unless we add it to the path) but we can call it from an npm script because npm knows all about the installed packages. Find the <code>scripts</code> section of your package.json. Initially, it will contain one line, which begins with <code>"start"</code>. Update it by putting a comma at the end of that line, and adding the <code>"devstart"</code> and <code>"serverstart"</code> lines:</p> <ul> <li> <p>On Linux and macOS, the scripts section will look like this:</p> <div class="code-example"><div class="example-header"><span class="language-name">json</span></div><pre class="brush: json notranslate"><code> "scripts": { "start": "node ./bin/www", "devstart": "nodemon ./bin/www", "serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart" }, </code></pre></div> </li> <li> <p>On Windows, the "serverstart" value would instead look like this (if using the command prompt):</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>"serverstart": "SET DEBUG=express-locallibrary-tutorial:* & npm run devstart" </code></pre></div> </li> </ul> <p>We can now start the server in almost exactly the same way as previously, but using the <code>devstart</code> command.</p> <div class="notecard note"> <p><strong>Note:</strong> Now if you edit any file in the project the server will restart (or you can restart it by typing <code>rs</code> on the command prompt at any time). You will still need to reload the browser to refresh the page.</p> <p>We now have to call <code>npm run <script-name></code> rather than just <code>npm start</code>, because "start" is actually an npm command that is mapped to the named script. We could have replaced the command in the <em>start</em> script but we only want to use <em>nodemon</em> during development, so it makes sense to create a new script command.</p> <p>The <code>serverstart</code> command added to the scripts in the <strong>package.json</strong> above is a very good example. Using this approach means you no longer have to type a long command to start the server. Note that the particular command added to the script works for macOS or Linux only.</p> </div></div></section><section aria-labelledby="the_generated_project"><h2 id="the_generated_project"><a href="#the_generated_project">The generated project</a></h2><div class="section-content"><p>Let's now take a look at the project we just created.</p></div></section><section aria-labelledby="directory_structure"><h3 id="directory_structure"><a href="#directory_structure">Directory structure</a></h3><div class="section-content"><p> The generated project, now that you have installed dependencies, has the following file structure (files are the items <strong>not</strong> prefixed with "/"). The <strong>package.json</strong> file defines the application dependencies and other information. It also defines a startup script that will call the application entry point, the JavaScript file <strong>/bin/www</strong>. This sets up some of the application error handling and then loads <strong>app.js</strong> to do the rest of the work. The app routes are stored in separate modules under the <strong>routes/</strong> directory. The templates are stored under the /<strong>views</strong> directory. </p> <pre class="brush: plain notranslate">express-locallibrary-tutorial app.js /bin www package.json package-lock.json /node_modules [about 6700 subdirectories and files] /public /images /javascripts /stylesheets style.css /routes index.js users.js /views error.pug index.pug layout.pug </pre> <p>The following sections describe the files in a little more detail.</p></div></section><section aria-labelledby="package.json"><h3 id="package.json"><a href="#package.json">package.json</a></h3><div class="section-content"><p>The <strong>package.json</strong> file defines the application dependencies and other information:</p> <div class="code-example"><div class="example-header"><span class="language-name">json</span></div><pre class="brush: json notranslate"><code>{ "name": "express-locallibrary-tutorial", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", "http-errors": "~1.6.3", "morgan": "~1.9.1", "pug": "2.0.0-beta11" }, "devDependencies": { "nodemon": "^3.1.3" } } </code></pre></div> <p>The scripts section first defines a "<em>start</em>" script, which is what we are invoking when we call <code>npm start</code> to start the server (this script was added by the <em>Express Application Generator</em>). From the script definition, you can see that this actually starts the JavaScript file <strong>./bin/www</strong> with <em>node</em>.</p> <p> We already modified this section in <a href="#enable_server_restart_on_file_changes">Enable server restart on file changes</a> by adding the <em>devstart</em> and <em>serverstart</em> scripts. These can be used to start the same <strong>./bin/www</strong> file with <em>nodemon</em> rather than <em>node</em> (this version of the scripts is for Linux and macOS, as discussed above). </p> <div class="code-example"><div class="example-header"><span class="language-name">json</span></div><pre class="brush: json notranslate"><code> "scripts": { "start": "node ./bin/www", "devstart": "nodemon ./bin/www", "serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart" }, </code></pre></div> <p> The dependencies include the <em>express</em> package and the package for our selected view engine (<em>pug</em>). In addition, we have the following packages that are useful in many web applications: </p> <ul> <li><a href="https://www.npmjs.com/package/cookie-parser" class="external" target="_blank">cookie-parser</a>: Used to parse the cookie header and populate <code>req.cookies</code> (essentially provides a convenient method for accessing cookie information).</li> <li><a href="https://www.npmjs.com/package/debug" class="external" target="_blank">debug</a>: A tiny node debugging utility modeled after node core's debugging technique.</li> <li><a href="https://www.npmjs.com/package/morgan" class="external" target="_blank">morgan</a>: An HTTP request logger middleware for node.</li> <li><a href="https://www.npmjs.com/package/http-errors" class="external" target="_blank">http-errors</a>: Create HTTP errors where needed (for express error handling).</li> </ul> <p> The default versions in the generated project are a little out of date. Replace the dependencies section of your <code>package.json</code> file with the following text, which specifies the latest versions of these libraries at the time of writing: </p> <div class="code-example"><div class="example-header"><span class="language-name">json</span></div><pre class="brush: json notranslate"><code> "dependencies": { "cookie-parser": "^1.4.6", "debug": "^4.3.5", "express": "^4.19.2", "http-errors": "~2.0.0", "morgan": "^1.10.0", "pug": "3.0.3" }, </code></pre></div> <p>Then update your installed dependencies using the command:</p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>npm install </code></pre></div> <div class="notecard note"> <p><strong>Note:</strong> It is a good idea to regularly update to the latest compatible versions of your dependency libraries — this may even be done automatically or semi-automatically as part of a continuous integration setup.</p> <p> Usually library updates to the minor and patch version remain compatible. We've prefixed each version with <code>^</code> above so that we can automatically update to the latest <code>minor.patch</code> version by running: </p> <div class="code-example"><div class="example-header"><span class="language-name">bash</span></div><pre class="brush: bash notranslate"><code>npm update --save </code></pre></div> <p> Major versions change the compatibility. For those updates we'll need to manually update the <code>package.json</code> and code that uses the library, and extensively re-test the project. </p> </div></div></section><section aria-labelledby="www_file"><h3 id="www_file"><a href="#www_file">www file</a></h3><div class="section-content"><p> The file <strong>/bin/www</strong> is the application entry point! The very first thing this does is <code>require()</code> the "real" application entry point (<strong>app.js</strong>, in the project root) that sets up and returns the <a href="https://expressjs.com/en/api.html" class="external" target="_blank"><code>express()</code></a> application object. <code>require()</code> is the <a href="https://nodejs.org/api/modules.html" class="external" target="_blank">CommonJS way</a> to import JavaScript code, JSON, and other files into the current file. Here we specify <strong>app.js</strong> module using a relative path and omit the optional (.<strong>js</strong>) file extension. </p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>#!/usr/bin/env node /** * Module dependencies. */ const app = require("../app"); </code></pre></div> <div class="notecard note"> <p> <strong>Note:</strong> Node.js 14 and later support ES6 <code>import</code> statements for importing JavaScript (ECMAScript) modules. To use this feature you have to add <code>"type": "module",</code> to your Express <strong>package.json</strong> file, all the modules in your application have to use <code>import</code> rather than <code>require()</code>, and for <em>relative imports</em> you must include the file extension (for more information see the <a href="https://nodejs.org/api/esm.html#introduction" class="external" target="_blank">Node documentation</a>). While there are benefits to using <code>import</code>, this tutorial uses <code>require()</code> in order to match <a href="https://expressjs.com/en/starter/hello-world.html" class="external" target="_blank">the Express documentation</a>. </p> </div> <p>The remainder of the code in this file sets up a node HTTP server with <code>app</code> set to a specific port (defined in an environment variable or 3000 if the variable isn't defined), and starts listening and reporting server errors and connections. For now you don't really need to know anything else about the code (everything in this file is "boilerplate"), but feel free to review it if you're interested.</p></div></section><section aria-labelledby="app.js"><h3 id="app.js"><a href="#app.js">app.js</a></h3><div class="section-content"><p>This file creates an <code>express</code> application object (named <code>app</code>, by convention), sets up the application with various settings and middleware, and then exports the app from the module. The code below shows just the parts of the file that create and export the app object:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const express = require("express"); const app = express(); // … module.exports = app; </code></pre></div> <p>Back in the <strong>www</strong> entry point file above, it is this <code>module.exports</code> object that is supplied to the caller when this file is imported.</p> <p>Let's work through the <strong>app.js</strong> file in detail. First, we import some useful node libraries into the file using <code>require()</code>, including <em>http-errors</em>, <em>express</em>, <em>morgan</em> and <em>cookie-parser</em> that we previously downloaded for our application using npm; and <em>path</em>, which is a core Node library for parsing file and directory paths.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const createError = require("http-errors"); const express = require("express"); const path = require("path"); const cookieParser = require("cookie-parser"); const logger = require("morgan"); </code></pre></div> <p>Then we <code>require()</code> modules from our routes directory. These modules/files contain code for handling particular sets of related "routes" (URL paths). When we extend the skeleton application, for example to list all books in the library, we will add a new file for dealing with book-related routes.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const indexRouter = require("./routes/index"); const usersRouter = require("./routes/users"); </code></pre></div> <div class="notecard note"> <p><strong>Note:</strong> At this point, we have just <em>imported</em> the module; we haven't actually used its routes yet (this happens just a little bit further down the file).</p> </div> <p>Next, we create the <code>app</code> object using our imported <em>express</em> module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First, we set the <code>"views"</code> value to specify the folder where the templates will be stored (in this case the subfolder <strong>/views</strong>). Then we set the <code>"view engine"</code> value to specify the template library (in this case "pug").</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const app = express(); // view engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); </code></pre></div> <p> The next set of functions call <code>app.use()</code> to add the <em>middleware</em> libraries that we imported above into the request handling chain. For example, <code>express.json()</code> and <code>express.urlencoded()</code> are needed to populate <a href="https://expressjs.com/en/api.html#req.body" class="external" target="_blank"><code>req.body</code></a> with the form fields. After these libraries we also use the <code>express.static</code> middleware, which makes <em>Express</em> serve all the static files in the <strong>/public</strong> directory in the project root. </p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, "public"))); </code></pre></div> <p>Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different <em>parts</em> of the site:</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>app.use("/", indexRouter); app.use("/users", usersRouter); </code></pre></div> <div class="notecard note"> <p> <strong>Note:</strong> The paths specified above (<code>"/"</code> and <code>"/users"</code>) are treated as a prefix to routes defined in the imported files. So for example, if the imported <strong>users</strong> module defines a route for <code>/profile</code>, you would access that route at <code>/users/profile</code>. We'll talk more about routes in a later article. </p> </div> <p>The last middleware in the file adds handler methods for errors and HTTP 404 responses.</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>// catch 404 and forward to error handler app.use((req, res, next) => { next(createError(404)); }); // error handler app.use((err, req, res, next) => { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; // render the error page res.status(err.status || 500); res.render("error"); }); </code></pre></div> <p>The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by <strong>/bin/www</strong>).</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>module.exports = app; </code></pre></div></div></section><section aria-labelledby="routes"><h3 id="routes"><a href="#routes">Routes</a></h3><div class="section-content"><p> The route file <strong>/routes/users.js</strong> is shown below (route files share a similar structure, so we don't need to also show <strong>index.js</strong>). First, it loads the <em>express</em> module and uses it to get an <code>express.Router</code> object. Then it specifies a route on that object and lastly exports the router from the module (this is what allows the file to be imported into <strong>app.js</strong>). </p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>const express = require("express"); const router = express.Router(); /* GET users listing. */ router.get("/", (req, res, next) => { res.send("respond with a resource"); }); module.exports = router; </code></pre></div> <p>The route defines a callback that will be invoked whenever an HTTP <code>GET</code> request with the correct pattern is detected. The matching pattern is the route specified when the module is imported (<code>"/users"</code>) plus whatever is defined in this file (<code>"/"</code>). In other words, this route will be used when a URL of <code>/users/</code> is received.</p> <div class="notecard note"> <p><strong>Note:</strong> Try this out by running the server with node and visiting the URL in your browser: <code>http://localhost:3000/users/</code>. You should see a message: 'respond with a resource'.</p> </div> <p>One thing of interest above is that the callback function has the third argument <code>next</code>, and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the <code>next</code> argument, it may be useful in the future if you want to add multiple route handlers to the <code>'/'</code> route path.</p></div></section><section aria-labelledby="views_templates"><h3 id="views_templates"><a href="#views_templates">Views (templates)</a></h3><div class="section-content"><p>The views (templates) are stored in the <strong>/views</strong> directory (as specified in <strong>app.js</strong>) and are given the file extension <strong>.pug</strong>. The method <a href="https://expressjs.com/en/4x/api.html#res.render" class="external" target="_blank"><code>Response.render()</code></a> is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from <strong>/routes/index.js</strong> you can see how that route renders a response using the template "index" passing the template variable "title".</p> <div class="code-example"><div class="example-header"><span class="language-name">js</span></div><pre class="brush: js notranslate"><code>/* GET home page. */ router.get("/", (req, res, next) => { res.render("index", { title: "Express" }); }); </code></pre></div> <p>The corresponding template for the above route is given below (<strong>index.pug</strong>). We'll talk more about the syntax later. All you need to know for now is that the <code>title</code> variable (with value <code>'Express'</code>) is inserted where specified in the template.</p> <div class="code-example"><div class="example-header"><span class="language-name">pug</span></div><pre class="brush: pug notranslate"><code>extends layout block content h1= title p Welcome to #{title} </code></pre></div></div></section><section aria-labelledby="challenge_yourself"><h2 id="challenge_yourself"><a href="#challenge_yourself">Challenge yourself</a></h2><div class="section-content"><p>Create a new route in <strong>/routes/users.js</strong> that will display the text "<em>You're so cool"</em> at URL <code>/users/cool/</code>. Test it by running the server and visiting <code>http://localhost:3000/users/cool/</code> in your browser</p></div></section><section aria-labelledby="summary"><h2 id="summary"><a href="#summary">Summary</a></h2><div class="section-content"><p>You have now created a skeleton website project for the <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Local Library</a> and verified that it runs using <em>node</em>. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.</p> <p>Next, we'll start modifying the skeleton so that it works as a library website.</p></div></section><section aria-labelledby="see_also"><h2 id="see_also"><a href="#see_also">See also</a></h2><div class="section-content"><ul> <li><a href="https://expressjs.com/en/starter/generator.html" class="external" target="_blank">Express application generator</a> (Express docs)</li> <li><a href="https://expressjs.com/en/guide/using-template-engines.html" class="external" target="_blank">Using template engines with Express</a> (Express docs)</li> </ul><ul class="prev-next"> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website"><span class="button-wrap"> Previous </span></a></li> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs"><span class="button-wrap"> Overview: Express web framework (Node.js/JavaScript)</span></a></li> <li><a class="button secondary" href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose"><span class="button-wrap"> Next </span></a></li> </ul></div></section></article><aside class="article-footer"><div class="article-footer-inner"><div class="svg-container"><svg xmlns="http://www.w3.org/2000/svg" width="162" height="162" viewBox="0 0 162 162" fill="none" role="none"><mask id="b" fill="#fff"><path d="M97.203 47.04c8.113-7.886 18.004-13.871 28.906-17.492a78 78 0 0 1 33.969-3.39c11.443 1.39 22.401 5.295 32.024 11.411s17.656 14.28 23.476 23.86c5.819 9.579 9.269 20.318 10.083 31.385a69.85 69.85 0 0 1-5.387 32.44c-4.358 10.272-11.115 19.443-19.747 26.801-8.632 7.359-18.908 12.709-30.034 15.637l-6.17-21.698c7.666-2.017 14.746-5.703 20.694-10.773 5.948-5.071 10.603-11.389 13.606-18.467a48.14 48.14 0 0 0 3.712-22.352c-.561-7.625-2.938-15.025-6.948-21.625s-9.544-12.226-16.175-16.44-14.181-6.904-22.065-7.863a53.75 53.75 0 0 0-23.405 2.336c-7.513 2.495-14.327 6.62-19.918 12.053z"></path></mask><path stroke="url(#a)" stroke-dasharray="6, 6" stroke-width="2" d="M97.203 47.04c8.113-7.886 18.004-13.871 28.906-17.492a78 78 0 0 1 33.969-3.39c11.443 1.39 22.401 5.295 32.024 11.411s17.656 14.28 23.476 23.86c5.819 9.579 9.269 20.318 10.083 31.385a69.85 69.85 0 0 1-5.387 32.44c-4.358 10.272-11.115 19.443-19.747 26.801-8.632 7.359-18.908 12.709-30.034 15.637l-6.17-21.698c7.666-2.017 14.746-5.703 20.694-10.773 5.948-5.071 10.603-11.389 13.606-18.467a48.14 48.14 0 0 0 3.712-22.352c-.561-7.625-2.938-15.025-6.948-21.625s-9.544-12.226-16.175-16.44-14.181-6.904-22.065-7.863a53.75 53.75 0 0 0-23.405 2.336c-7.513 2.495-14.327 6.62-19.918 12.053z" mask="url(#b)" style="stroke:url(#a)" transform="translate(-63.992 -25.587)"></path><ellipse cx="8.066" cy="111.597" fill="var(--background-tertiary)" rx="53.677" ry="53.699" transform="matrix(.71707 -.697 .7243 .6895 0 0)"></ellipse><g clip-path="url(#c)" transform="translate(-63.992 -25.587)"><path fill="#9abff5" d="m144.256 137.379 32.906 12.434a4.41 4.41 0 0 1 2.559 5.667l-9.326 24.679a4.41 4.41 0 0 1-5.667 2.559l-8.226-3.108-2.332 6.17c-.466 1.233-.375 1.883-1.609 1.417l-2.253-.527c-.411-.155-.95-.594-1.206-1.161l-4.734-10.484-12.545-4.741a4.41 4.41 0 0 1-2.559-5.667l9.325-24.679a4.41 4.41 0 0 1 5.667-2.559m9.961 29.617 8.227 3.108 3.264-8.638-.498-6.768-4.113-1.555.548 7.258-4.319-1.632zm-12.339-4.663 8.226 3.108 3.264-8.637-.498-6.769-4.113-1.554.548 7.257-4.319-1.632z"></path></g><g clip-path="url(#d)" transform="translate(-63.992 -25.587)"><path fill="#81b0f3" d="M135.35 60.136 86.67 41.654c-3.346-1.27-7.124.428-8.394 3.775L64.414 81.938c-1.27 3.347.428 7.125 3.774 8.395l12.17 4.62-3.465 9.128c-.693 1.826-1.432 2.457.394 3.15l3.014 1.625c.609.231 1.637.274 2.477-.104l15.53-6.983 18.56 7.047c3.346 1.27 7.124-.428 8.395-3.775l13.862-36.51c1.27-3.346-.428-7.124-3.775-8.395M95.261 83.207l-12.17-4.62 4.852-12.779 7.19-7.017 6.085 2.31-7.725 7.51 6.389 2.426zm18.255 6.93-12.17-4.62 4.852-12.778 7.189-7.017 6.085 2.31-7.725 7.51 6.39 2.426z"></path></g><defs><clipPath id="c"><path fill="#fff" d="m198.638 146.586-65.056-24.583-24.583 65.057 65.056 24.582z"></path></clipPath><clipPath id="d"><path fill="#fff" d="m66.438 14.055 96.242 36.54-36.54 96.243-96.243-36.54z"></path></clipPath><linearGradient id="a" x1="97.203" x2="199.995" y1="47.04" y2="152.793" gradientUnits="userSpaceOnUse"><stop stop-color="#086DFC"></stop><stop offset="0.246" stop-color="#2C81FA"></stop><stop offset="0.516" stop-color="#5497F8"></stop><stop offset="0.821" stop-color="#80B0F6"></stop><stop offset="1" stop-color="#9ABFF5"></stop></linearGradient></defs></svg></div><h2>Help improve MDN</h2><fieldset class="feedback"><label>Was this page helpful to you?</label><div class="button-container"><button type="button" class="button primary has-icon yes"><span class="button-wrap"><span class="icon icon-thumbs-up "></span>Yes</span></button><button type="button" class="button primary has-icon no"><span class="button-wrap"><span class="icon icon-thumbs-down "></span>No</span></button></div></fieldset><a class="contribute" href="https://github.com/mdn/content/blob/main/CONTRIBUTING.md" title="This will take you to our contribution guidelines on GitHub." target="_blank" rel="noopener noreferrer">Learn how to contribute</a>.<p class="last-modified-date">This page was last modified on<!-- --> <time dateTime="2024-11-22T16:43:48.000Z">Nov 22, 2024</time> by<!-- --> <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website/contributors.txt" rel="nofollow">MDN contributors</a>.</p><div id="on-github" class="on-github"><a href="https://github.com/mdn/content/blob/main/files/en-us/learn/server-side/express_nodejs/skeleton_website/index.md?plain=1" title="Folder: en-us/learn/server-side/express_nodejs/skeleton_website (Opens in a new tab)" target="_blank" rel="noopener noreferrer">View this page on GitHub</a> <!-- -->•<!-- --> <a href="https://github.com/mdn/content/issues/new?template=page-report.yml&mdn-url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FLearn%2FServer-side%2FExpress_Nodejs%2Fskeleton_website&metadata=%3C%21--+Do+not+make+changes+below+this+line+--%3E%0A%3Cdetails%3E%0A%3Csummary%3EPage+report+details%3C%2Fsummary%3E%0A%0A*+Folder%3A+%60en-us%2Flearn%2Fserver-side%2Fexpress_nodejs%2Fskeleton_website%60%0A*+MDN+URL%3A+https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FLearn%2FServer-side%2FExpress_Nodejs%2Fskeleton_website%0A*+GitHub+URL%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Fcontent%2Fblob%2Fmain%2Ffiles%2Fen-us%2Flearn%2Fserver-side%2Fexpress_nodejs%2Fskeleton_website%2Findex.md%0A*+Last+commit%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Fcontent%2Fcommit%2F5f76b99045f87349ed030bbd6a3c2e43badb3c22%0A*+Document+last+modified%3A+2024-11-22T16%3A43%3A48.000Z%0A%0A%3C%2Fdetails%3E" title="This will take you to GitHub to file a new issue." target="_blank" rel="noopener noreferrer">Report a problem with this content</a></div></div></aside></main></div></div><footer id="nav-footer" class="page-footer"><div class="page-footer-grid"><div class="page-footer-logo-col"><a href="/" class="mdn-footer-logo" aria-label="MDN homepage"><svg width="48" height="17" viewBox="0 0 48 17" fill="none" xmlns="http://www.w3.org/2000/svg"><title id="mdn-footer-logo-svg">MDN logo</title><path d="M20.04 16.512H15.504V10.416C15.504 9.488 15.344 8.824 15.024 8.424C14.72 8.024 14.264 7.824 13.656 7.824C12.92 7.824 12.384 8.064 12.048 8.544C11.728 9.024 11.568 9.64 11.568 10.392V14.184H13.008V16.512H8.472V10.416C8.472 9.488 8.312 8.824 7.992 8.424C7.688 8.024 7.232 7.824 6.624 7.824C5.872 7.824 5.336 8.064 5.016 8.544C4.696 9.024 4.536 9.64 4.536 10.392V14.184H6.6V16.512H0V14.184H1.44V8.04H0.024V5.688H4.536V7.32C5.224 6.088 6.32 5.472 7.824 5.472C8.608 5.472 9.328 5.664 9.984 6.048C10.64 6.432 11.096 7.016 11.352 7.8C11.992 6.248 13.168 5.472 14.88 5.472C15.856 5.472 16.72 5.776 17.472 6.384C18.224 6.992 18.6 7.936 18.6 9.216V14.184H20.04V16.512Z" fill="currentColor"></path><path d="M33.6714 16.512H29.1354V14.496C28.8314 15.12 28.3834 15.656 27.7914 16.104C27.1994 16.536 26.4154 16.752 25.4394 16.752C24.0154 16.752 22.8954 16.264 22.0794 15.288C21.2634 14.312 20.8554 12.984 20.8554 11.304C20.8554 9.688 21.2554 8.312 22.0554 7.176C22.8554 6.04 24.0634 5.472 25.6794 5.472C26.5594 5.472 27.2794 5.648 27.8394 6C28.3994 6.352 28.8314 6.8 29.1354 7.344V2.352H26.9754V0H32.2314V14.184H33.6714V16.512ZM29.1354 11.04V10.776C29.1354 9.88 28.8954 9.184 28.4154 8.688C27.9514 8.176 27.3674 7.92 26.6634 7.92C25.9754 7.92 25.3674 8.176 24.8394 8.688C24.3274 9.2 24.0714 10.008 24.0714 11.112C24.0714 12.152 24.3114 12.944 24.7914 13.488C25.2714 14.032 25.8394 14.304 26.4954 14.304C27.3114 14.304 27.9514 13.96 28.4154 13.272C28.8954 12.584 29.1354 11.84 29.1354 11.04Z" fill="currentColor"></path><path d="M47.9589 16.512H41.9829V14.184H43.4229V10.416C43.4229 9.488 43.2629 8.824 42.9429 8.424C42.6389 8.024 42.1829 7.824 41.5749 7.824C40.8389 7.824 40.2709 8.056 39.8709 8.52C39.4709 8.968 39.2629 9.56 39.2469 10.296V14.184H40.6869V16.512H34.7109V14.184H36.1509V8.04H34.5909V5.688H39.2469V7.344C39.9669 6.096 41.1269 5.472 42.7269 5.472C43.7509 5.472 44.6389 5.776 45.3909 6.384C46.1429 6.992 46.5189 7.936 46.5189 9.216V14.184H47.9589V16.512Z" fill="currentColor"></path></svg></a><p>Your blueprint for a better internet.</p><ul class="social-icons"><li><a href="https://mozilla.social/@mdn" target="_blank" rel="me noopener noreferrer"><span class="icon icon-mastodon"></span><span class="visually-hidden">MDN on Mastodon</span></a></li><li><a href="https://twitter.com/mozdevnet" target="_blank" rel="noopener noreferrer"><span class="icon icon-twitter-x"></span><span class="visually-hidden">MDN on X (formerly Twitter)</span></a></li><li><a href="https://github.com/mdn/" target="_blank" rel="noopener noreferrer"><span class="icon icon-github-mark-small"></span><span class="visually-hidden">MDN on GitHub</span></a></li><li><a href="/en-US/blog/rss.xml" target="_blank"><span class="icon icon-feed"></span><span class="visually-hidden">MDN Blog RSS Feed</span></a></li></ul></div><div class="page-footer-nav-col-1"><h2 class="footer-nav-heading">MDN</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a href="/en-US/about">About</a></li><li class="footer-nav-item"><a href="/en-US/blog/">Blog</a></li><li class="footer-nav-item"><a href="https://www.mozilla.org/en-US/careers/listings/?team=ProdOps" target="_blank" rel="noopener noreferrer">Careers</a></li><li class="footer-nav-item"><a href="/en-US/advertising">Advertise with us</a></li></ul></div><div class="page-footer-nav-col-2"><h2 class="footer-nav-heading">Support</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="https://support.mozilla.org/products/mdn-plus">Product help</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/MDN/Community/Issues">Report an issue</a></li></ul></div><div class="page-footer-nav-col-3"><h2 class="footer-nav-heading">Our communities</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/community">MDN Community</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="https://discourse.mozilla.org/c/mdn/236" target="_blank" rel="noopener noreferrer">MDN Forum</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/discord" target="_blank" rel="noopener noreferrer">MDN Chat</a></li></ul></div><div class="page-footer-nav-col-4"><h2 class="footer-nav-heading">Developers</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/Web">Web Technologies</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/docs/Learn">Learn Web Development</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/plus">MDN Plus</a></li><li class="footer-nav-item"><a href="https://hacks.mozilla.org/" target="_blank" rel="noopener noreferrer">Hacks Blog</a></li></ul></div><div class="page-footer-moz"><a href="https://www.mozilla.org/" class="footer-moz-logo-link" target="_blank" rel="noopener noreferrer"><svg width="112" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"><title id="mozilla-footer-logo-svg">Mozilla logo</title><path d="M41.753 14.218c-2.048 0-3.324 1.522-3.324 4.157 0 2.423 1.119 4.286 3.29 4.286 2.082 0 3.447-1.678 3.447-4.347 0-2.826-1.522-4.096-3.413-4.096Zm54.89 7.044c0 .901.437 1.618 1.645 1.618 1.427 0 2.949-1.024 3.044-3.352-.649-.095-1.365-.185-2.02-.185-1.426-.005-2.668.397-2.668 1.92Z" fill="currentColor"></path><path d="M0 0v32h111.908V0H0Zm32.56 25.426h-5.87v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h1.864v3.044h-5.864v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h2.669v3.044H6.642v-3.044h1.863v-7.918H6.642V11.42h5.864v2.11c.839-1.489 2.3-2.39 4.252-2.39 2.02 0 3.878.963 4.566 3.01.778-1.862 2.361-3.01 4.566-3.01 2.512 0 4.812 1.522 4.812 4.84v6.402h1.863v3.044h-.005Zm9.036.307c-4.314 0-7.296-2.635-7.296-7.106 0-4.096 2.484-7.481 7.514-7.481s7.481 3.38 7.481 7.29c0 4.472-3.228 7.297-7.699 7.297Zm22.578-.307H51.942l-.403-2.11 7.7-8.846h-4.376l-.621 2.17-2.888-.313.498-4.907h12.294l.313 2.11-7.767 8.852h4.533l.654-2.172 3.167.308-.872 4.908Zm7.99 0h-4.191v-5.03h4.19v5.03Zm0-8.976h-4.191v-5.03h4.19v5.03Zm2.618 8.976 6.054-21.358h3.945l-6.054 21.358h-3.945Zm8.136 0 6.048-21.358h3.945l-6.054 21.358h-3.939Zm21.486.307c-1.863 0-2.887-1.085-3.072-2.792-.805 1.427-2.232 2.792-4.498 2.792-2.02 0-4.314-1.085-4.314-4.006 0-3.447 3.323-4.253 6.518-4.253.778 0 1.584.034 2.3.124v-.465c0-1.427-.034-3.133-2.3-3.133-.84 0-1.488.061-2.143.402l-.453 1.578-3.195-.34.549-3.224c2.45-.996 3.692-1.27 5.992-1.27 3.01 0 5.556 1.55 5.556 4.75v6.083c0 .805.314 1.085.963 1.085.184 0 .375-.034.587-.095l.034 2.11a5.432 5.432 0 0 1-2.524.654Z" fill="currentColor"></path></svg></a><ul class="footer-moz-list"><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Website Privacy Notice</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/#cookies" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Cookies</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/legal/terms/mozilla" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Legal</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/governance/policies/participation/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Community Participation Guidelines</a></li></ul></div><div class="page-footer-legal"><p id="license" class="page-footer-legal-text">Visit<!-- --> <a href="https://www.mozilla.org" target="_blank" rel="noopener noreferrer">Mozilla Corporation’s</a> <!-- -->not-for-profit parent, the<!-- --> <a target="_blank" rel="noopener noreferrer" href="https://foundation.mozilla.org/">Mozilla Foundation</a>.<br/>Portions of this content are ©1998–<!-- -->2024<!-- --> by individual mozilla.org contributors. Content available under<!-- --> <a href="/en-US/docs/MDN/Writing_guidelines/Attrib_copyright_license">a Creative Commons license</a>.</p></div></div></footer></div><script type="application/json" id="hydration">{"url":"/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website","doc":{"isMarkdown":true,"isTranslated":false,"isActive":true,"flaws":{},"title":"Express Tutorial Part 2: Creating a skeleton website","mdn_url":"/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website","locale":"en-US","native":"English (US)","sidebarHTML":"<ol><li class=\"section\"><a href=\"/en-US/docs/Learn/Getting_started_with_the_web\">Complete beginners start here!</a></li><li><details><summary>Getting started with the web</summary><ol><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web\">Getting started with the web</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/Installing_basic_software\">Installing basic software</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like\">What will your website look like?</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/Dealing_with_files\">Dealing with files</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics\">HTML basics</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/CSS_basics\">CSS basics</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics\">JavaScript basics</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/Publishing_your_website\">Publishing your website</a></li><li><a href=\"/en-US/docs/Learn/Getting_started_with_the_web/How_the_Web_works\">How the web works</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/HTML\">HTML — Structuring the web</a></li><li><details><summary>Introduction to HTML</summary><ol><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML\">Introduction to HTML</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started\">Getting started with HTML</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML\">What's in the head? Metadata in HTML</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals\">HTML text fundamentals</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks\">Creating hyperlinks</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting\">Advanced text formatting</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure\">Document and website structure</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML\">Debugging HTML</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter\">Marking up a letter</a></li><li><a href=\"/en-US/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content\">Structuring a page of content</a></li></ol></details></li><li><details><summary>Multimedia and embedding</summary><ol><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding\">Multimedia and embedding</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML\">Images in HTML</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content\">Video and audio content</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies\">From object to iframe — other embedding technologies</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web\">Adding vector graphics to the web</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images\">Responsive images</a></li><li><a href=\"/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page\">Mozilla splash page</a></li></ol></details></li><li><details><summary>HTML tables</summary><ol><li><a href=\"/en-US/docs/Learn/HTML/Tables\">HTML tables</a></li><li><a href=\"/en-US/docs/Learn/HTML/Tables/Basics\">HTML table basics</a></li><li><a href=\"/en-US/docs/Learn/HTML/Tables/Advanced\">HTML table advanced features and accessibility</a></li><li><a href=\"/en-US/docs/Learn/HTML/Tables/Structuring_planet_data\">Structuring planet data</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/CSS\">CSS — Styling the web</a></li><li><details><summary>CSS first steps</summary><ol><li><a href=\"/en-US/docs/Learn/CSS/First_steps\">CSS first steps</a></li><li><a href=\"/en-US/docs/Learn/CSS/First_steps/What_is_CSS\">What is CSS?</a></li><li><a href=\"/en-US/docs/Learn/CSS/First_steps/Getting_started\">Getting started with CSS</a></li><li><a href=\"/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured\">How CSS is structured</a></li><li><a href=\"/en-US/docs/Learn/CSS/First_steps/How_CSS_works\">How CSS works</a></li><li><a href=\"/en-US/docs/Learn/CSS/First_steps/Styling_a_biography_page\">Styling a biography page</a></li></ol></details></li><li><details><summary>CSS building blocks</summary><ol><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks\">CSS building blocks</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Selectors\">CSS selectors</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors\">Type, class, and ID selectors</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors\">Attribute selectors</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements\">Pseudo-classes and pseudo-elements</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators\">Combinators</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance\">Cascade, specificity, and inheritance</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers\">Cascade layers</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/The_box_model\">The box model</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders\">Backgrounds and borders</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions\">Handling different text directions</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content\">Overflowing content</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Values_and_units\">CSS values and units</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS\">Sizing items in CSS</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements\">Images, media, and form elements</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Styling_tables\">Styling tables</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Advanced_styling_effects\">Advanced styling effects</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS\">Debugging CSS</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Organizing\">Organizing your CSS</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Fundamental_CSS_comprehension\">Fundamental CSS comprehension</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/Creating_fancy_letterheaded_paper\">Creating fancy letterheaded paper</a></li><li><a href=\"/en-US/docs/Learn/CSS/Building_blocks/A_cool_looking_box\">A cool-looking box</a></li></ol></details></li><li><details><summary>Styling text</summary><ol><li><a href=\"/en-US/docs/Learn/CSS/Styling_text\">CSS styling text</a></li><li><a href=\"/en-US/docs/Learn/CSS/Styling_text/Fundamentals\">Fundamental text and font styling</a></li><li><a href=\"/en-US/docs/Learn/CSS/Styling_text/Styling_lists\">Styling lists</a></li><li><a href=\"/en-US/docs/Learn/CSS/Styling_text/Styling_links\">Styling links</a></li><li><a href=\"/en-US/docs/Learn/CSS/Styling_text/Web_fonts\">Web fonts</a></li><li><a href=\"/en-US/docs/Learn/CSS/Styling_text/Typesetting_a_homepage\">Typesetting a community school homepage</a></li></ol></details></li><li><details><summary>CSS layout</summary><ol><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout\">CSS layout</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Introduction\">Introduction to CSS layout</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow\">Normal Flow</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Flexbox\">Flexbox</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Grids\">Grids</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Floats\">Floats</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Positioning\">Positioning</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout\">Multiple-column layout</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design\">Responsive design</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Media_queries\">Beginner's guide to media queries</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods\">Legacy layout methods</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers\">Supporting older browsers</a></li><li><a href=\"/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension\">Fundamental layout comprehension</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/JavaScript\">JavaScript — Dynamic client-side scripting</a></li><li><details><summary>JavaScript first steps</summary><ol><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps\">JavaScript first steps</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript\">What is JavaScript?</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/A_first_splash\">A first splash into JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong\">What went wrong? Troubleshooting JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Variables\">Storing the information you need — Variables</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Math\">Basic math in JavaScript — numbers and operators</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Strings\">Handling text — strings in JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods\">Useful string methods</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Arrays\">Arrays</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator\">Silly story generator</a></li></ol></details></li><li><details><summary>JavaScript building blocks</summary><ol><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks\">JavaScript building blocks</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/conditionals\">Making decisions in your code — conditionals</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code\">Looping code</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Functions\">Functions — reusable blocks of code</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function\">Build your own function</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Return_values\">Function return values</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Events\">Introduction to events</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Event_bubbling\">Event bubbling</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery\">Image gallery</a></li></ol></details></li><li><details><summary>Introducing JavaScript objects</summary><ol><li><a href=\"/en-US/docs/Learn/JavaScript/Objects\">Introducing JavaScript objects</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Basics\">JavaScript object basics</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Object_prototypes\">Object prototypes</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Object-oriented_programming\">Object-oriented programming</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Classes_in_JavaScript\">Classes in JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/JSON\">Working with JSON</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Object_building_practice\">Object building practice</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features\">Adding features to our bouncing balls demo</a></li></ol></details></li><li><details><summary>Asynchronous JavaScript</summary><ol><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous\">Asynchronous JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous/Introducing\">Introducing asynchronous JavaScript</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous/Promises\">How to use promises</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous/Implementing_a_promise-based_API\">How to implement a promise-based API</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous/Introducing_workers\">Introducing workers</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Asynchronous/Sequencing_animations\">Sequencing animations</a></li></ol></details></li><li><details><summary>Client-side web APIs</summary><ol><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs\">Client-side web APIs</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction\">Introduction to web APIs</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents\">Manipulating documents</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data\">Fetching data from the server</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs\">Third-party APIs</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics\">Drawing graphics</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs\">Video and Audio APIs</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage\">Client-side storage</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Forms\">Web forms — Working with user data</a></li><li><details><summary>Web form building blocks</summary><ol><li><a href=\"/en-US/docs/Learn/Forms\">Web form building blocks</a></li><li><a href=\"/en-US/docs/Learn/Forms/Your_first_form\">Your first form</a></li><li><a href=\"/en-US/docs/Learn/Forms/How_to_structure_a_web_form\">How to structure a web form</a></li><li><a href=\"/en-US/docs/Learn/Forms/Basic_native_form_controls\">Basic native form controls</a></li><li><a href=\"/en-US/docs/Learn/Forms/HTML5_input_types\">The HTML5 input types</a></li><li><a href=\"/en-US/docs/Learn/Forms/Other_form_controls\">Other form controls</a></li><li><a href=\"/en-US/docs/Learn/Forms/Styling_web_forms\">Styling web forms</a></li><li><a href=\"/en-US/docs/Learn/Forms/Advanced_form_styling\">Advanced form styling</a></li><li><a href=\"/en-US/docs/Learn/Forms/UI_pseudo-classes\">UI pseudo-classes</a></li><li><a href=\"/en-US/docs/Learn/Forms/Form_validation\">Client-side form validation</a></li><li><a href=\"/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data\">Sending form data</a></li></ol></details></li><li><details><summary>Advanced web form techniques</summary><ol><li><a href=\"/en-US/docs/Learn/Forms/How_to_build_custom_form_controls\">How to build custom form controls</a></li><li><a href=\"/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript\">Sending forms through JavaScript</a></li><li><a href=\"/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_controls\">CSS property compatibility table for form controls</a></li><li><a href=\"/en-US/docs/Learn/Forms/HTML_forms_in_legacy_browsers\">HTML forms in legacy browsers</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Accessibility\">Accessibility — Make the web usable by everyone</a></li><li><details><summary>Accessibility guides</summary><ol><li><a href=\"/en-US/docs/Learn/Accessibility\">Accessibility</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/What_is_accessibility\">What is accessibility?</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/HTML\">HTML: A good basis for accessibility</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/CSS_and_JavaScript\">CSS and JavaScript accessibility best practices</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/WAI-ARIA_basics\">WAI-ARIA basics</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/Multimedia\">Accessible multimedia</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/Mobile\">Mobile accessibility</a></li><li><a href=\"/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting\">Assessment: Accessibility troubleshooting</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Performance\">Performance — Making websites fast and responsive</a></li><li><details><summary>Performance guides</summary><ol><li><a href=\"/en-US/docs/Learn/Performance\">Web performance</a></li><li><a href=\"/en-US/docs/Learn/Performance/why_web_performance\">The \"why\" of web performance</a></li><li><a href=\"/en-US/docs/Learn/Performance/What_is_web_performance\">What is web performance?</a></li><li><a href=\"/en-US/docs/Learn/Performance/Perceived_performance\">Perceived performance</a></li><li><a href=\"/en-US/docs/Learn/Performance/Measuring_performance\">Measuring performance</a></li><li><a href=\"/en-US/docs/Learn/Performance/Multimedia\">Multimedia: Images</a></li><li><a href=\"/en-US/docs/Learn/Performance/video\">Multimedia: video</a></li><li><a href=\"/en-US/docs/Learn/Performance/JavaScript\">JavaScript performance optimization</a></li><li><a href=\"/en-US/docs/Learn/Performance/HTML\">HTML performance optimization</a></li><li><a href=\"/en-US/docs/Learn/Performance/CSS\">CSS performance optimization</a></li><li><a href=\"/en-US/docs/Learn/Performance/business_case_for_performance\">The business case for web performance</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/MathML\">MathML — Writing mathematics with MathML</a></li><li><details><summary>MathML first steps</summary><ol><li><a href=\"/en-US/docs/Learn/MathML/First_steps\">MathML first steps</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Getting_started\">Getting started with MathML</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Text_containers\">MathML Text Containers</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Fractions_and_roots\">MathML fractions and roots</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Scripts\">MathML scripted elements</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Tables\">MathML tables</a></li><li><a href=\"/en-US/docs/Learn/MathML/First_steps/Three_famous_mathematical_formulas\">Three famous mathematical formulas</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/../Games\">Games — Developing games for the web</a></li><li><details><summary>Guides and tutorials</summary><ol><li><a href=\"/en-US/docs/Games/Introduction\">Introduction to game development for the Web</a></li><li><a href=\"/en-US/docs/Games/Techniques\">Techniques for game development</a></li><li><a href=\"/en-US/docs/Games/Tutorials\">Tutorials</a></li><li><a href=\"/en-US/docs/Games/Publishing_games\">Publishing games</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Tools_and_testing\">Tools and testing</a></li><li><details><summary>Client-side web development tools</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools\">Understanding client-side web development tools</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview\">Client-side tooling overview</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line\">Command line crash course</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management\">Package management basics</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Introducing_complete_toolchain\">Introducing a complete toolchain</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Deployment\">Deploying our app</a></li></ol></details></li><li><details><summary>Introduction to client-side frameworks</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction\">Introduction to client-side frameworks</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features\">Framework main features</a></li></ol></details></li><li><details><summary>React</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started\">Getting started with React</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning\">Beginning our React todo list</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components\">Componentizing our React app</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state\">React interactivity: Events and state</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering\">React interactivity: Editing, filtering, conditional rendering</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility\">Accessibility in React</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources\">React resources</a></li></ol></details></li><li><details><summary>Ember</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started\">Getting started with Ember</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization\">Ember app structure and componentization</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state\">Ember interactivity: Events, classes and state</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer\">Ember Interactivity: Footer functionality, conditional rendering</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing\">Routing in Ember</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources\">Ember resources and troubleshooting</a></li></ol></details></li><li><details><summary>Vue</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started\">Getting started with Vue</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component\">Creating our first Vue component</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists\">Rendering a list of Vue components</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models\">Adding a new todo form: Vue events, methods, and models</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling\">Styling Vue components with CSS</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties\">Using Vue computed properties</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering\">Vue conditional rendering: editing existing todos</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management\">Vue refs and lifecycle methods for focus management</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources\">Vue resources</a></li></ol></details></li><li><details><summary>Svelte</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started\">Getting started with Svelte</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning\">Starting our Svelte to-do list app</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props\">Dynamic behavior in Svelte: working with variables and props</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components\">Componentizing our Svelte app</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_reactivity_lifecycle_accessibility\">Advanced Svelte: Reactivity, lifecycle, accessibility</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores\">Working with Svelte stores</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_TypeScript\">TypeScript support in Svelte</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_deployment_next\">Deployment and next steps</a></li></ol></details></li><li><details><summary>Angular</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_getting_started\">Getting started with Angular</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_todo_list_beginning\">Beginning our Angular todo list app</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_styling\">Styling our Angular app</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_item_component\">Creating an item component</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_filtering\">Filtering our to-do items</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Angular_building\">Building Angular applications and further resources</a></li></ol></details></li><li><details><summary>Git and GitHub</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/GitHub\">Git and GitHub</a></li></ol></details></li><li><details><summary>Cross browser testing</summary><ol><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing\">Cross browser testing</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction\">Introduction to cross-browser testing</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies\">Strategies for carrying out testing</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS\">Handling common HTML and CSS problems</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript\">Handling common JavaScript problems</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility\">Handling common accessibility problems</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection\">Implementing feature detection</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing\">Introduction to automated testing</a></li><li><a href=\"/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment\">Setting up your own test automation environment</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Server-side\">Server-side website programming</a></li><li><details><summary>First steps</summary><ol><li><a href=\"/en-US/docs/Learn/Server-side/First_steps\">Server-side website programming first steps</a></li><li><a href=\"/en-US/docs/Learn/Server-side/First_steps/Introduction\">Introduction to the server side</a></li><li><a href=\"/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview\">Client-Server Overview</a></li><li><a href=\"/en-US/docs/Learn/Server-side/First_steps/Web_frameworks\">Server-side web frameworks</a></li><li><a href=\"/en-US/docs/Learn/Server-side/First_steps/Website_security\">Website security</a></li></ol></details></li><li><details><summary>Django web framework (Python)</summary><ol><li><a href=\"/en-US/docs/Learn/Server-side/Django\">Django Web Framework (Python)</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Introduction\">Django introduction</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/development_environment\">Setting up a Django development environment</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website\">Django Tutorial: The Local Library website</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/skeleton_website\">Django Tutorial Part 2: Creating a skeleton website</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Models\">Django Tutorial Part 3: Using models</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Admin_site\">Django Tutorial Part 4: Django admin site</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Home_page\">Django Tutorial Part 5: Creating our home page</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Generic_views\">Django Tutorial Part 6: Generic list and detail views</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Sessions\">Django Tutorial Part 7: Sessions framework</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Authentication\">Django Tutorial Part 8: User authentication and permissions</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Forms\">Django Tutorial Part 9: Working with forms</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Testing\">Django Tutorial Part 10: Testing a Django web application</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/Deployment\">Django Tutorial Part 11: Deploying Django to production</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/web_application_security\">Django web application security</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Django/django_assessment_blog\">Assessment: DIY Django mini blog</a></li></ol></details></li><li><details open=\"\"><summary>Express Web Framework (Node.js/JavaScript)</summary><ol><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs\">Express web framework (Node.js/JavaScript)</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction\">Express/Node introduction</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment\">Setting up a Node development environment</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\">Express Tutorial: The Local Library website</a></li><li><em><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website\" aria-current=\"page\">Express Tutorial Part 2: Creating a skeleton website</a></em></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose\">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/routes\">Express Tutorial Part 4: Routes and controllers</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data\">Express Tutorial Part 5: Displaying library data</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/forms\">Express Tutorial Part 6: Working with forms</a></li><li><a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/deployment\">Express Tutorial Part 7: Deploying to production</a></li></ol></details></li><li class=\"section\"><a href=\"/en-US/docs/Learn/Common_questions\">Further resources</a></li><li><details><summary>Common questions</summary><ol><li><a href=\"/en-US/docs/Learn/Common_questions\">Common questions</a></li><li><a href=\"/en-US/docs/Learn/HTML/Howto\">Use HTML to solve common problems</a></li><li><a href=\"/en-US/docs/Learn/CSS/Howto\">Use CSS to solve common problems</a></li><li><a href=\"/en-US/docs/Learn/JavaScript/Howto\">Solve common problems in your JavaScript code</a></li><li><a href=\"/en-US/docs/Learn/Common_questions/Web_mechanics\">Web mechanics</a></li><li><a href=\"/en-US/docs/Learn/Common_questions/Tools_and_setup\">Tools and setup</a></li><li><a href=\"/en-US/docs/Learn/Common_questions/Design_and_accessibility\">Design and accessibility</a></li></ol></details></li></ol>","sidebarMacro":"LearnSidebar","body":[{"type":"prose","value":{"id":null,"title":null,"isH3":false,"content":"<ul class=\"prev-next\">\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\"><span class=\"button-wrap\"> Previous </span></a></li>\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs\"><span class=\"button-wrap\"> Overview: Express web framework (Node.js/JavaScript)</span></a></li>\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose\"><span class=\"button-wrap\"> Next </span></a></li>\n</ul>\n<p>This second article in our <a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\">Express Tutorial</a> shows how you can create a \"skeleton\" website project which you can then go on to populate with site-specific routes, templates/views, and database calls.</p>\n<figure class=\"table-container\"><table>\n <tbody>\n <tr>\n <th scope=\"row\">Prerequisites:</th>\n <td>\n <a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment\">Set up a Node development environment</a>.\n Review the Express Tutorial.\n </td>\n </tr>\n <tr>\n <th scope=\"row\">Objective:</th>\n <td>To be able to start your own new website projects using the <em>Express Application Generator</em>.</td>\n </tr>\n </tbody>\n</table></figure>"}},{"type":"prose","value":{"id":"overview","title":"Overview","isH3":false,"content":"<p>This article shows how you can create a \"skeleton\" website using the <a href=\"https://expressjs.com/en/starter/generator.html\" class=\"external\" target=\"_blank\">Express Application Generator</a> tool, which you can then populate with site-specific routes, views/templates, and database calls. In this case, we'll use the tool to create the framework for our <a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\">Local Library website</a>, to which we'll later add all the other code needed by the site. The process is extremely simple, requiring only that you invoke the generator on the command line with a new project name, optionally also specifying the site's template engine and CSS generator.</p>\n<p>The following sections show you how to call the application generator, and provides a little explanation about the different view/CSS options. We'll also explain how the skeleton website is structured. At the end, we'll show how you can run the website to verify that it works.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong></p>\n <ul>\n <li>The <em>Express Application Generator</em> is not the only generator for Express applications, and the generated project is not the only viable way to structure your files and directories. The generated site does however have a modular structure that is easy to extend and understand. For information about a <em>minimal</em> Express application, see <a href=\"https://expressjs.com/en/starter/hello-world.html\" class=\"external\" target=\"_blank\">Hello world example</a> (Express docs).</li>\n <li>\n The <em>Express Application Generator</em> declares most variables using <code>var</code>.\n We have changed most of these to <a href=\"/en-US/docs/Web/JavaScript/Reference/Statements/const\"><code>const</code></a> (and a few to <a href=\"/en-US/docs/Web/JavaScript/Reference/Statements/let\"><code>let</code></a>) in the tutorial, because we want to demonstrate modern JavaScript practice.\n </li>\n <li>\n This tutorial uses the version of <em>Express</em> and other dependencies that are defined in the <strong>package.json</strong> created by the <em>Express Application Generator</em>.\n These are not (necessarily) the latest version, and you may want to update them when deploying a real application to production.\n </li>\n </ul>\n</div>"}},{"type":"prose","value":{"id":"using_the_application_generator","title":"Using the application generator","isH3":false,"content":"<p>You should already have installed the generator as part of <a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment\">setting up a Node development environment</a>. As a quick reminder, you install the generator tool site-wide using the npm package manager, as shown:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>npm install express-generator -g\n</code></pre></div>\n<p>The generator has a number of options, which you can view on the command line using the <code>--help</code> (or <code>-h</code>) command:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>> express --help\n\n Usage: express [options] [dir]\n\n Options:\n\n --version output the version number\n -e, --ejs add ejs engine support\n --pug add pug engine support\n --hbs add handlebars engine support\n -H, --hogan add hogan.js engine support\n -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)\n --no-view use static html instead of view engine\n -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain CSS)\n --git add .gitignore\n -f, --force force on non-empty directory\n -h, --help output usage information\n</code></pre></div>\n<p>You can specify express to create a project inside the <em>current</em> directory using the <em>Jade</em> view engine and plain CSS (if you specify a directory name then the project will be created in a sub-folder with that name).</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>express\n</code></pre></div>\n<p>You can also choose a view (template) engine using <code>--view</code> and/or a CSS generation engine using <code>--css</code>.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> The other options for choosing template engines (e.g. <code>--hogan</code>, <code>--ejs</code>, <code>--hbs</code> etc.) are deprecated. Use <code>--view</code> (or <code>-v</code>).</p>\n</div>"}},{"type":"prose","value":{"id":"what_view_engine_should_i_use","title":"What view engine should I use?","isH3":true,"content":"<p>The <em>Express Application Generator</em> allows you to configure a number of popular view/templating engines, including <a href=\"https://www.npmjs.com/package/ejs\" class=\"external\" target=\"_blank\">EJS</a>, <a href=\"https://github.com/pillarjs/hbs\" class=\"external\" target=\"_blank\">Hbs</a>, <a href=\"https://pugjs.org/api/getting-started.html\" class=\"external\" target=\"_blank\">Pug</a> (Jade), <a href=\"https://www.npmjs.com/package/twig\" class=\"external\" target=\"_blank\">Twig</a>, and <a href=\"https://www.npmjs.com/package/vash\" class=\"external\" target=\"_blank\">Vash</a>, although it chooses Jade by default if you don't specify a view option. Express itself can also support a large number of other templating languages <a href=\"https://github.com/expressjs/express/wiki#template-engines\" class=\"external\" target=\"_blank\">out of the box</a>.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> If you want to use a template engine that isn't supported by the generator then see <a href=\"https://expressjs.com/en/guide/using-template-engines.html\" class=\"external\" target=\"_blank\">Using template engines with Express</a> (Express docs) and the documentation for your target view engine.</p>\n</div>\n<p>Generally speaking, you should select a templating engine that delivers all the functionality you need and allows you to be productive sooner — or in other words, in the same way that you choose any other component! Some of the things to consider when comparing template engines:</p>\n<ul>\n <li>\n <p>Time to productivity — If your team already has experience with a templating language then it is likely they will be productive faster using that language. If not, then you should consider the relative learning curve for candidate templating engines.</p>\n </li>\n <li>\n <p>Popularity and activity — Review the popularity of the engine and whether it has an active community. It is important to be able to get support when problems arise throughout the lifetime of the website.</p>\n </li>\n <li>\n <p>Style — Some template engines use specific markup to indicate inserted content within \"ordinary\" HTML, while others construct the HTML using a different syntax (for example, using indentation and block names).</p>\n </li>\n <li>\n <p>Performance/rendering time.</p>\n </li>\n <li>\n <p>Features — you should consider whether the engines you look at have the following features available:</p>\n <ul>\n <li>Layout inheritance: Allows you to define a base template and then \"inherit\" just the parts of it that you want to be different for a particular page. This is typically a better approach than building templates by including a number of required components or building a template from scratch each time.</li>\n <li>\"Include\" support: Allows you to build up templates by including other templates.</li>\n <li>Concise variable and loop control syntax.</li>\n <li>Ability to filter variable values at template level, such as making variables upper-case, or formatting a date value.</li>\n <li>Ability to generate output formats other than HTML, such as JSON or XML.</li>\n <li>Support for asynchronous operations and streaming.</li>\n <li>Client-side features. If a templating engine can be used on the client this allows the possibility of having all or most of the rendering done client-side.</li>\n </ul>\n </li>\n</ul>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> There are many resources on the Internet to help you compare the different options!</p>\n</div>\n<p>For this project, we'll use the <a href=\"https://pugjs.org/api/getting-started.html\" class=\"external\" target=\"_blank\">Pug</a> templating engine (this is the recently-renamed Jade engine), as this is one of the most popular Express/JavaScript templating languages and is supported out of the box by the generator.</p>"}},{"type":"prose","value":{"id":"what_css_stylesheet_engine_should_i_use","title":"What CSS stylesheet engine should I use?","isH3":true,"content":"<p>The <em>Express Application Generator</em> allows you to create a project that is configured to use the most common CSS stylesheet engines: <a href=\"https://lesscss.org/\" class=\"external\" target=\"_blank\">LESS</a>, <a href=\"https://sass-lang.com/\" class=\"external\" target=\"_blank\">SASS</a>, <a href=\"https://stylus-lang.com/\" class=\"external\" target=\"_blank\">Stylus</a>.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> CSS has some limitations that make certain tasks difficult. CSS stylesheet engines allow you to use more powerful syntax for defining your CSS and then compile the definition into plain-old CSS for browsers to use.</p>\n</div>\n<p>As with templating engines, you should use the stylesheet engine that will allow your team to be most productive. For this project, we'll use vanilla CSS (the default) as our CSS requirements are not sufficiently complicated to justify using anything else.</p>"}},{"type":"prose","value":{"id":"what_database_should_i_use","title":"What database should I use?","isH3":true,"content":"<p>The generated code doesn't use/include any databases. <em>Express</em> apps can use any <a href=\"https://expressjs.com/en/guide/database-integration.html\" class=\"external\" target=\"_blank\">database mechanism</a> supported by <em>Node</em> (<em>Express</em> itself doesn't define any specific additional behavior/requirements for database management).</p>\n<p>We'll discuss how to integrate with a database in a later article.</p>"}},{"type":"prose","value":{"id":"creating_the_project","title":"Creating the project","isH3":false,"content":"<p>For the sample <em>Local Library</em> app we're going to build, we'll create a project named <em>express-locallibrary-tutorial</em> using the <em>Pug</em> template library and no CSS engine.</p>\n<p>First, navigate to where you want to create the project and then run the <em>Express Application Generator</em> in the command prompt as shown:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>express express-locallibrary-tutorial --view=pug\n</code></pre></div>\n<p>The generator will create (and list) the project's files.</p>\n<pre class=\"brush: plain notranslate\"> create : express-locallibrary-tutorial\\\n create : express-locallibrary-tutorial\\public\\\n create : express-locallibrary-tutorial\\public\\javascripts\\\n create : express-locallibrary-tutorial\\public\\images\\\n create : express-locallibrary-tutorial\\public\\stylesheets\\\n create : express-locallibrary-tutorial\\public\\stylesheets\\style.css\n create : express-locallibrary-tutorial\\routes\\\n create : express-locallibrary-tutorial\\routes\\index.js\n create : express-locallibrary-tutorial\\routes\\users.js\n create : express-locallibrary-tutorial\\views\\\n create : express-locallibrary-tutorial\\views\\error.pug\n create : express-locallibrary-tutorial\\views\\index.pug\n create : express-locallibrary-tutorial\\views\\layout.pug\n create : express-locallibrary-tutorial\\app.js\n create : express-locallibrary-tutorial\\package.json\n create : express-locallibrary-tutorial\\bin\\\n create : express-locallibrary-tutorial\\bin\\www\n\n change directory:\n > cd express-locallibrary-tutorial\n\n install dependencies:\n > npm install\n\n run the app (Bash (Linux or macOS))\n > DEBUG=express-locallibrary-tutorial:* npm start\n\n run the app (PowerShell (Windows))\n > $ENV:DEBUG = \"express-locallibrary-tutorial:*\"; npm start\n\n run the app (Command Prompt (Windows)):\n > SET DEBUG=express-locallibrary-tutorial:* & npm start\n</pre>\n<p>At the end of the output, the generator provides instructions on how to install the dependencies (as listed in the <strong>package.json</strong> file) and how to run the application on different operating systems.</p>\n<div class=\"notecard note\">\n <p>\n <strong>Note:</strong> The generator-created files define all variables as <code>var</code>.\n Open all of the generated files and change the <code>var</code> declarations to <code>const</code> before you continue (the remainder of the tutorial assumes that you have done so).\n </p>\n</div>"}},{"type":"prose","value":{"id":"running_the_skeleton_website","title":"Running the skeleton website","isH3":false,"content":"<p>At this point, we have a complete skeleton project. The website doesn't actually <em>do</em> very much yet, but it's worth running it to show that it works.</p>\n<ol>\n <li>\n <p>First, install the dependencies (the <code>install</code> command will fetch all the dependency packages listed in the project's <strong>package.json</strong> file).</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>cd express-locallibrary-tutorial\nnpm install\n</code></pre></div>\n </li>\n <li>\n <p>Then run the application.</p>\n <ul>\n <li>\n <p>On the Windows CMD prompt, use this command:</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">batch</span></div><pre class=\"brush: batch notranslate\"><code>SET DEBUG=express-locallibrary-tutorial:* & npm start\n</code></pre></div>\n </li>\n <li>\n <p>On Windows PowerShell, use this command:</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">powershell</span></div><pre class=\"brush: powershell notranslate\"><code>ENV:DEBUG = \"express-locallibrary-tutorial:*\"; npm start\n</code></pre></div>\n <div class=\"notecard note\">\n <p><strong>Note:</strong> PowerShell commands are not covered in this tutorial (The provided \"Windows\" commands assume you're using the Windows CMD prompt.)</p>\n </div>\n </li>\n <li>\n <p>On macOS or Linux, use this command:</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>DEBUG=express-locallibrary-tutorial:* npm start\n</code></pre></div>\n </li>\n </ul>\n </li>\n <li>\n <p>Then load <code>http://localhost:3000/</code> in your browser to access the app.</p>\n </li>\n</ol>\n<p>You should see a browser page that looks like this:</p>\n<p>\n <img src=\"/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website/expressgeneratorskeletonwebsite.png\" alt=\"Browser for default Express app generator website\" width=\"576\" height=\"403\" loading=\"lazy\">\n</p>\n<p>Congratulations! You now have a working Express application that can be accessed via port 3000.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> You could also start the app just using the <code>npm start</code> command. Specifying the DEBUG variable as shown enables console logging/debugging. For example, when you visit the above page you'll see debug output like this:</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>SET DEBUG=express-locallibrary-tutorial:* & npm start\n</code></pre></div>\n <pre class=\"brush: plain notranslate\">> express-locallibrary-tutorial@0.0.0 start D:\\github\\mdn\\test\\exprgen\\express-locallibrary-tutorial\n> node ./bin/www\n\n express-locallibrary-tutorial:server Listening on port 3000 +0ms\nGET / 304 490.296 ms - -\nGET /stylesheets/style.css 200 4.886 ms - 111\n</pre>\n</div>"}},{"type":"prose","value":{"id":"enable_server_restart_on_file_changes","title":"Enable server restart on file changes","isH3":false,"content":"<p>Any changes you make to your Express website are currently not visible until you restart the server. It quickly becomes very irritating to have to stop and restart your server every time you make a change, so it is worth taking the time to automate restarting the server when needed.</p>\n<p>A convenient tool for this purpose is <a href=\"https://github.com/remy/nodemon\" class=\"external\" target=\"_blank\">nodemon</a>. This is usually installed globally (as it is a \"tool\"), but here we'll install and use it locally as a <em>developer dependency</em>, so that any developers working with the project get it automatically when they install the application. Use the following command in the root directory for the skeleton project:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>npm install --save-dev nodemon\n</code></pre></div>\n<p>If you still choose to install <a href=\"https://github.com/remy/nodemon\" class=\"external\" target=\"_blank\">nodemon</a> globally to your machine, and not only to your project's <strong>package.json</strong> file:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>npm install -g nodemon\n</code></pre></div>\n<p>If you open your project's <strong>package.json</strong> file you'll now see a new section with this dependency:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">json</span></div><pre class=\"brush: json notranslate\"><code> \"devDependencies\": {\n \"nodemon\": \"^3.1.3\"\n}\n</code></pre></div>\n<p>Because the tool isn't installed globally we can't launch it from the command line (unless we add it to the path) but we can call it from an npm script because npm knows all about the installed packages. Find the <code>scripts</code> section of your package.json. Initially, it will contain one line, which begins with <code>\"start\"</code>. Update it by putting a comma at the end of that line, and adding the <code>\"devstart\"</code> and <code>\"serverstart\"</code> lines:</p>\n<ul>\n <li>\n <p>On Linux and macOS, the scripts section will look like this:</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">json</span></div><pre class=\"brush: json notranslate\"><code> \"scripts\": {\n \"start\": \"node ./bin/www\",\n \"devstart\": \"nodemon ./bin/www\",\n \"serverstart\": \"DEBUG=express-locallibrary-tutorial:* npm run devstart\"\n },\n</code></pre></div>\n </li>\n <li>\n <p>On Windows, the \"serverstart\" value would instead look like this (if using the command prompt):</p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>\"serverstart\": \"SET DEBUG=express-locallibrary-tutorial:* & npm run devstart\"\n</code></pre></div>\n </li>\n</ul>\n<p>We can now start the server in almost exactly the same way as previously, but using the <code>devstart</code> command.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> Now if you edit any file in the project the server will restart (or you can restart it by typing <code>rs</code> on the command prompt at any time). You will still need to reload the browser to refresh the page.</p>\n <p>We now have to call <code>npm run <script-name></code> rather than just <code>npm start</code>, because \"start\" is actually an npm command that is mapped to the named script. We could have replaced the command in the <em>start</em> script but we only want to use <em>nodemon</em> during development, so it makes sense to create a new script command.</p>\n <p>The <code>serverstart</code> command added to the scripts in the <strong>package.json</strong> above is a very good example. Using this approach means you no longer have to type a long command to start the server. Note that the particular command added to the script works for macOS or Linux only.</p>\n</div>"}},{"type":"prose","value":{"id":"the_generated_project","title":"The generated project","isH3":false,"content":"<p>Let's now take a look at the project we just created.</p>"}},{"type":"prose","value":{"id":"directory_structure","title":"Directory structure","isH3":true,"content":"<p>\n The generated project, now that you have installed dependencies, has the following file structure (files are the items <strong>not</strong> prefixed with \"/\").\n The <strong>package.json</strong> file defines the application dependencies and other information.\n It also defines a startup script that will call the application entry point, the JavaScript file <strong>/bin/www</strong>.\n This sets up some of the application error handling and then loads <strong>app.js</strong> to do the rest of the work.\n The app routes are stored in separate modules under the <strong>routes/</strong> directory.\n The templates are stored under the /<strong>views</strong> directory.\n</p>\n<pre class=\"brush: plain notranslate\">express-locallibrary-tutorial\n app.js\n /bin\n www\n package.json\n package-lock.json\n /node_modules\n [about 6700 subdirectories and files]\n /public\n /images\n /javascripts\n /stylesheets\n style.css\n /routes\n index.js\n users.js\n /views\n error.pug\n index.pug\n layout.pug\n</pre>\n<p>The following sections describe the files in a little more detail.</p>"}},{"type":"prose","value":{"id":"package.json","title":"package.json","isH3":true,"content":"<p>The <strong>package.json</strong> file defines the application dependencies and other information:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">json</span></div><pre class=\"brush: json notranslate\"><code>{\n \"name\": \"express-locallibrary-tutorial\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"scripts\": {\n \"start\": \"node ./bin/www\"\n },\n \"dependencies\": {\n \"cookie-parser\": \"~1.4.4\",\n \"debug\": \"~2.6.9\",\n \"express\": \"~4.16.1\",\n \"http-errors\": \"~1.6.3\",\n \"morgan\": \"~1.9.1\",\n \"pug\": \"2.0.0-beta11\"\n },\n \"devDependencies\": {\n \"nodemon\": \"^3.1.3\"\n }\n}\n</code></pre></div>\n<p>The scripts section first defines a \"<em>start</em>\" script, which is what we are invoking when we call <code>npm start</code> to start the server (this script was added by the <em>Express Application Generator</em>). From the script definition, you can see that this actually starts the JavaScript file <strong>./bin/www</strong> with <em>node</em>.</p>\n<p>\n We already modified this section in <a href=\"#enable_server_restart_on_file_changes\">Enable server restart on file changes</a> by adding the <em>devstart</em> and <em>serverstart</em> scripts.\n These can be used to start the same <strong>./bin/www</strong> file with <em>nodemon</em> rather than <em>node</em> (this version of the scripts is for Linux and macOS, as discussed above).\n</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">json</span></div><pre class=\"brush: json notranslate\"><code> \"scripts\": {\n \"start\": \"node ./bin/www\",\n \"devstart\": \"nodemon ./bin/www\",\n \"serverstart\": \"DEBUG=express-locallibrary-tutorial:* npm run devstart\"\n },\n</code></pre></div>\n<p>\n The dependencies include the <em>express</em> package and the package for our selected view engine (<em>pug</em>).\n In addition, we have the following packages that are useful in many web applications:\n</p>\n<ul>\n <li><a href=\"https://www.npmjs.com/package/cookie-parser\" class=\"external\" target=\"_blank\">cookie-parser</a>: Used to parse the cookie header and populate <code>req.cookies</code> (essentially provides a convenient method for accessing cookie information).</li>\n <li><a href=\"https://www.npmjs.com/package/debug\" class=\"external\" target=\"_blank\">debug</a>: A tiny node debugging utility modeled after node core's debugging technique.</li>\n <li><a href=\"https://www.npmjs.com/package/morgan\" class=\"external\" target=\"_blank\">morgan</a>: An HTTP request logger middleware for node.</li>\n <li><a href=\"https://www.npmjs.com/package/http-errors\" class=\"external\" target=\"_blank\">http-errors</a>: Create HTTP errors where needed (for express error handling).</li>\n</ul>\n<p>\n The default versions in the generated project are a little out of date.\n Replace the dependencies section of your <code>package.json</code> file with the following text, which specifies the latest versions of these libraries at the time of writing:\n</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">json</span></div><pre class=\"brush: json notranslate\"><code> \"dependencies\": {\n \"cookie-parser\": \"^1.4.6\",\n \"debug\": \"^4.3.5\",\n \"express\": \"^4.19.2\",\n \"http-errors\": \"~2.0.0\",\n \"morgan\": \"^1.10.0\",\n \"pug\": \"3.0.3\"\n },\n</code></pre></div>\n<p>Then update your installed dependencies using the command:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>npm install\n</code></pre></div>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> It is a good idea to regularly update to the latest compatible versions of your dependency libraries — this may even be done automatically or semi-automatically as part of a continuous integration setup.</p>\n <p>\n Usually library updates to the minor and patch version remain compatible.\n We've prefixed each version with <code>^</code> above so that we can automatically update to the latest <code>minor.patch</code> version by running:\n </p>\n <div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">bash</span></div><pre class=\"brush: bash notranslate\"><code>npm update --save\n</code></pre></div>\n <p>\n Major versions change the compatibility.\n For those updates we'll need to manually update the <code>package.json</code> and code that uses the library, and extensively re-test the project.\n </p>\n</div>"}},{"type":"prose","value":{"id":"www_file","title":"www file","isH3":true,"content":"<p>\n The file <strong>/bin/www</strong> is the application entry point! The very first thing this does is <code>require()</code> the \"real\" application entry point (<strong>app.js</strong>, in the project root) that sets up and returns the <a href=\"https://expressjs.com/en/api.html\" class=\"external\" target=\"_blank\"><code>express()</code></a> application object.\n <code>require()</code> is the <a href=\"https://nodejs.org/api/modules.html\" class=\"external\" target=\"_blank\">CommonJS way</a> to import JavaScript code, JSON, and other files into the current file.\n Here we specify <strong>app.js</strong> module using a relative path and omit the optional (.<strong>js</strong>) file extension.\n</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nconst app = require(\"../app\");\n</code></pre></div>\n<div class=\"notecard note\">\n <p>\n <strong>Note:</strong> Node.js 14 and later support ES6 <code>import</code> statements for importing JavaScript (ECMAScript) modules.\n To use this feature you have to add <code>\"type\": \"module\",</code> to your Express <strong>package.json</strong> file, all the modules in your application have to use <code>import</code> rather than <code>require()</code>, and for <em>relative imports</em> you must include the file extension (for more information see the <a href=\"https://nodejs.org/api/esm.html#introduction\" class=\"external\" target=\"_blank\">Node documentation</a>).\n While there are benefits to using <code>import</code>, this tutorial uses <code>require()</code> in order to match <a href=\"https://expressjs.com/en/starter/hello-world.html\" class=\"external\" target=\"_blank\">the Express documentation</a>.\n </p>\n</div>\n<p>The remainder of the code in this file sets up a node HTTP server with <code>app</code> set to a specific port (defined in an environment variable or 3000 if the variable isn't defined), and starts listening and reporting server errors and connections. For now you don't really need to know anything else about the code (everything in this file is \"boilerplate\"), but feel free to review it if you're interested.</p>"}},{"type":"prose","value":{"id":"app.js","title":"app.js","isH3":true,"content":"<p>This file creates an <code>express</code> application object (named <code>app</code>, by convention), sets up the application with various settings and middleware, and then exports the app from the module. The code below shows just the parts of the file that create and export the app object:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const express = require(\"express\");\nconst app = express();\n// …\nmodule.exports = app;\n</code></pre></div>\n<p>Back in the <strong>www</strong> entry point file above, it is this <code>module.exports</code> object that is supplied to the caller when this file is imported.</p>\n<p>Let's work through the <strong>app.js</strong> file in detail. First, we import some useful node libraries into the file using <code>require()</code>, including <em>http-errors</em>, <em>express</em>, <em>morgan</em> and <em>cookie-parser</em> that we previously downloaded for our application using npm; and <em>path</em>, which is a core Node library for parsing file and directory paths.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const createError = require(\"http-errors\");\nconst express = require(\"express\");\nconst path = require(\"path\");\nconst cookieParser = require(\"cookie-parser\");\nconst logger = require(\"morgan\");\n</code></pre></div>\n<p>Then we <code>require()</code> modules from our routes directory. These modules/files contain code for handling particular sets of related \"routes\" (URL paths). When we extend the skeleton application, for example to list all books in the library, we will add a new file for dealing with book-related routes.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const indexRouter = require(\"./routes/index\");\nconst usersRouter = require(\"./routes/users\");\n</code></pre></div>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> At this point, we have just <em>imported</em> the module; we haven't actually used its routes yet (this happens just a little bit further down the file).</p>\n</div>\n<p>Next, we create the <code>app</code> object using our imported <em>express</em> module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First, we set the <code>\"views\"</code> value to specify the folder where the templates will be stored (in this case the subfolder <strong>/views</strong>). Then we set the <code>\"view engine\"</code> value to specify the template library (in this case \"pug\").</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const app = express();\n\n// view engine setup\napp.set(\"views\", path.join(__dirname, \"views\"));\napp.set(\"view engine\", \"pug\");\n</code></pre></div>\n<p>\n The next set of functions call <code>app.use()</code> to add the <em>middleware</em> libraries that we imported above into the request handling chain.\n For example, <code>express.json()</code> and <code>express.urlencoded()</code> are needed to populate <a href=\"https://expressjs.com/en/api.html#req.body\" class=\"external\" target=\"_blank\"><code>req.body</code></a> with the form fields.\n After these libraries we also use the <code>express.static</code> middleware, which makes <em>Express</em> serve all the static files in the <strong>/public</strong> directory in the project root.\n</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>app.use(logger(\"dev\"));\napp.use(express.json());\napp.use(express.urlencoded({ extended: false }));\napp.use(cookieParser());\n\napp.use(express.static(path.join(__dirname, \"public\")));\n</code></pre></div>\n<p>Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different <em>parts</em> of the site:</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>app.use(\"/\", indexRouter);\napp.use(\"/users\", usersRouter);\n</code></pre></div>\n<div class=\"notecard note\">\n <p>\n <strong>Note:</strong> The paths specified above (<code>\"/\"</code> and <code>\"/users\"</code>) are treated as a prefix to routes defined in the imported files.\n So for example, if the imported <strong>users</strong> module defines a route for <code>/profile</code>, you would access that route at <code>/users/profile</code>. We'll talk more about routes in a later article.\n </p>\n</div>\n<p>The last middleware in the file adds handler methods for errors and HTTP 404 responses.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>// catch 404 and forward to error handler\napp.use((req, res, next) => {\n next(createError(404));\n});\n\n// error handler\napp.use((err, req, res, next) => {\n // set locals, only providing error in development\n res.locals.message = err.message;\n res.locals.error = req.app.get(\"env\") === \"development\" ? err : {};\n\n // render the error page\n res.status(err.status || 500);\n res.render(\"error\");\n});\n</code></pre></div>\n<p>The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by <strong>/bin/www</strong>).</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>module.exports = app;\n</code></pre></div>"}},{"type":"prose","value":{"id":"routes","title":"Routes","isH3":true,"content":"<p>\n The route file <strong>/routes/users.js</strong> is shown below (route files share a similar structure, so we don't need to also show <strong>index.js</strong>).\n First, it loads the <em>express</em> module and uses it to get an <code>express.Router</code> object.\n Then it specifies a route on that object and lastly exports the router from the module (this is what allows the file to be imported into <strong>app.js</strong>).\n</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>const express = require(\"express\");\nconst router = express.Router();\n\n/* GET users listing. */\nrouter.get(\"/\", (req, res, next) => {\n res.send(\"respond with a resource\");\n});\n\nmodule.exports = router;\n</code></pre></div>\n<p>The route defines a callback that will be invoked whenever an HTTP <code>GET</code> request with the correct pattern is detected. The matching pattern is the route specified when the module is imported (<code>\"/users\"</code>) plus whatever is defined in this file (<code>\"/\"</code>). In other words, this route will be used when a URL of <code>/users/</code> is received.</p>\n<div class=\"notecard note\">\n <p><strong>Note:</strong> Try this out by running the server with node and visiting the URL in your browser: <code>http://localhost:3000/users/</code>. You should see a message: 'respond with a resource'.</p>\n</div>\n<p>One thing of interest above is that the callback function has the third argument <code>next</code>, and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the <code>next</code> argument, it may be useful in the future if you want to add multiple route handlers to the <code>'/'</code> route path.</p>"}},{"type":"prose","value":{"id":"views_templates","title":"Views (templates)","isH3":true,"content":"<p>The views (templates) are stored in the <strong>/views</strong> directory (as specified in <strong>app.js</strong>) and are given the file extension <strong>.pug</strong>. The method <a href=\"https://expressjs.com/en/4x/api.html#res.render\" class=\"external\" target=\"_blank\"><code>Response.render()</code></a> is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from <strong>/routes/index.js</strong> you can see how that route renders a response using the template \"index\" passing the template variable \"title\".</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">js</span></div><pre class=\"brush: js notranslate\"><code>/* GET home page. */\nrouter.get(\"/\", (req, res, next) => {\n res.render(\"index\", { title: \"Express\" });\n});\n</code></pre></div>\n<p>The corresponding template for the above route is given below (<strong>index.pug</strong>). We'll talk more about the syntax later. All you need to know for now is that the <code>title</code> variable (with value <code>'Express'</code>) is inserted where specified in the template.</p>\n<div class=\"code-example\"><div class=\"example-header\"><span class=\"language-name\">pug</span></div><pre class=\"brush: pug notranslate\"><code>extends layout\n\nblock content\n h1= title\n p Welcome to #{title}\n</code></pre></div>"}},{"type":"prose","value":{"id":"challenge_yourself","title":"Challenge yourself","isH3":false,"content":"<p>Create a new route in <strong>/routes/users.js</strong> that will display the text \"<em>You're so cool\"</em> at URL <code>/users/cool/</code>. Test it by running the server and visiting <code>http://localhost:3000/users/cool/</code> in your browser</p>"}},{"type":"prose","value":{"id":"summary","title":"Summary","isH3":false,"content":"<p>You have now created a skeleton website project for the <a href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\">Local Library</a> and verified that it runs using <em>node</em>. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.</p>\n<p>Next, we'll start modifying the skeleton so that it works as a library website.</p>"}},{"type":"prose","value":{"id":"see_also","title":"See also","isH3":false,"content":"<ul>\n <li><a href=\"https://expressjs.com/en/starter/generator.html\" class=\"external\" target=\"_blank\">Express application generator</a> (Express docs)</li>\n <li><a href=\"https://expressjs.com/en/guide/using-template-engines.html\" class=\"external\" target=\"_blank\">Using template engines with Express</a> (Express docs)</li>\n</ul><ul class=\"prev-next\">\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website\"><span class=\"button-wrap\"> Previous </span></a></li>\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs\"><span class=\"button-wrap\"> Overview: Express web framework (Node.js/JavaScript)</span></a></li>\n <li><a class=\"button secondary\" href=\"/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose\"><span class=\"button-wrap\"> Next </span></a></li>\n</ul>"}}],"toc":[{"text":"Overview","id":"overview"},{"text":"Using the application generator","id":"using_the_application_generator"},{"text":"Creating the project","id":"creating_the_project"},{"text":"Running the skeleton website","id":"running_the_skeleton_website"},{"text":"Enable server restart on file changes","id":"enable_server_restart_on_file_changes"},{"text":"The generated project","id":"the_generated_project"},{"text":"Challenge yourself","id":"challenge_yourself"},{"text":"Summary","id":"summary"},{"text":"See also","id":"see_also"}],"summary":"You have now created a skeleton website project for the Local Library and verified that it runs using node. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.","popularity":0.0059,"modified":"2024-11-22T16:43:48.000Z","other_translations":[{"locale":"de","title":"Express Tutorial Teil 2: Erstellung eines Skelett-Webauftritts","native":"Deutsch"},{"locale":"es","title":"Express Tutorial Part 2: Creating a skeleton website","native":"Español"},{"locale":"ja","title":"Express チュートリアル Part 2: スケルトンウェブサイトの作成","native":"日本語"},{"locale":"pt-BR","title":"Express Tutorial Parte 2: Criando a estrutura do website","native":"Português (do Brasil)"},{"locale":"ru","title":"Учебник Express часть 2: Создание скелета сайта","native":"Русский"},{"locale":"zh-CN","title":"Express 教程 2:创建站点框架","native":"中文 (简体)"},{"locale":"zh-TW","title":"Express 教學 2: 創建一個骨架網站","native":"正體中文 (繁體)"}],"pageType":"learn-module-chapter","source":{"folder":"en-us/learn/server-side/express_nodejs/skeleton_website","github_url":"https://github.com/mdn/content/blob/main/files/en-us/learn/server-side/express_nodejs/skeleton_website/index.md","last_commit_url":"https://github.com/mdn/content/commit/5f76b99045f87349ed030bbd6a3c2e43badb3c22","filename":"index.md"},"short_title":"Express Tutorial Part 2: Creating a skeleton website","parents":[{"uri":"/en-US/docs/Learn","title":"Guides"},{"uri":"/en-US/docs/Learn/Server-side","title":"Server-side website programming"},{"uri":"/en-US/docs/Learn/Server-side/Express_Nodejs","title":"Express web framework (Node.js/JavaScript)"},{"uri":"/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website","title":"Express Tutorial Part 2: Creating a skeleton website"}],"pageTitle":"Express Tutorial Part 2: Creating a skeleton website - Learn web development | MDN","noIndexing":false}}</script></body></html>