Build Your First Node.js Web Project

Build and debug a local Node.js website in VS Code on Windows.

Introduction

30 Second Summary

A Windows computer can handle everyday tasks while still leaving the path to a working webpage unclear. Confidence arrives when each tool fits into a routine you can repeat.

In this project, you will build an interactive Developer Launchpad on a verified Windows web development setup. The finished page runs on a Node.js server through npm. You can inspect its live requests in the Visual Studio Code debugger.

What You'll Build

You'll open the Developer Launchpad in Microsoft Edge and watch it respond from a local web address while Visual Studio Code pauses a request for inspection.

By the end of this project, you'll have:

  • An interactive Developer Launchpad where JavaScript changes the status text after you click Start my coding session.
  • A repeatable npm workflow that serves your page at http://127.0.0.1:3000.
  • A live debugging workflow that pauses at a breakpoint so you can inspect the browser path inside Visual Studio Code.
  • Secret Mission: Add a /status endpoint that reports whether your local server is running.

Are there any prerequisites?

No prior coding experience is required. You only need a computer running Windows 10 or Windows 11 because the project guides you through installing every required tool.

Before We Start

A clear outcome gives every setup choice a purpose. Before the hands-on work begins, commit to the Developer Launchpad you are building and why a repeatable local web development setup matters to you.

Set Up Your Windows Web Development Tools

Your Developer Launchpad needs a dependable Windows foundation. Matching each installer to your processor prevents the toolchain from failing before you write a file.

Visual Studio Code becomes your project workspace.

Node.js supplies the runtime. npm runs project commands from the same Windows PowerShell terminal.

Microsoft Edge displays the page you build. In this step, you will install each tool before proving that they work together.

In this step, get ready to:
  • Identify whether Windows reports an x64-based or ARM-based processor.
  • Install the complete Windows web development toolchain.
  • Verify every command from a Windows PowerShell terminal in Visual Studio Code.
Identify your Windows architecture

This setting is tucked inside the About page, so it is easy to miss. Your system type determines which installer can run on your processor.

  • Open Start from the Windows taskbar.
  • Select Settings.
  • Select System.
  • Select About.
  • Find System type under Device specifications.
  • Record the displayed value here: your Windows system type.

You will see either an x64-based processor or an ARM-based processor in the system type.

Install the matching tools

A pinned toolchain removes version guesswork from the rest of the project. You are aiming for Visual Studio Code 1.137, Node.js v24.21.0 LTS, and npm 11.19.0.

Why Native Windows?

Native Windows installers keep this first workflow inside one operating system. WSL adds a second environment.

That second environment has its own files. It also has its own commands.

The Visual Studio Code User Installer is recommended for most people. It installs for your Windows account without requiring administrator permissions.

  • Press the Windows key to open Windows search.
  • Type Windows PowerShell into the search box.
  • Press Enter to open Windows PowerShell.
  • Check whether Visual Studio Code is already installed by running:
code --version

What Does This Command Check?

  • The code --version command prints the installed Visual Studio Code version first.
  • The remaining output identifies the build commit plus your processor architecture.

✔️ I see the required version

Great, your editor already matches the project. The first output line begins with 1.137.

ⓧ I see an older version

Your existing editor needs an update before the rest of the workflow can rely on it.

  • Open the Visual Studio Code download page in your browser.
  • Select the x64 User Installer when your Windows system type reports an x64-based processor.
  • Select the Arm64 User Installer when your Windows system type reports an ARM-based processor.
  • Run the downloaded User Installer.
  • Complete the setup using the default options.

When setup finishes, Windows search lists Visual Studio Code for your account.

ⓧ Visual Studio Code is unavailable

The User Installer adds Visual Studio Code for your Windows account.

  • Open the Visual Studio Code download page in your browser.
  • Select the x64 User Installer when your Windows system type reports an x64-based processor.
  • Select the Arm64 User Installer when your Windows system type reports an ARM-based processor.
  • Run the downloaded User Installer.
  • Complete the setup using the default options.

When setup finishes, Windows search lists Visual Studio Code for your account.

Node.js includes npm in the same installer. The next check tells you whether both commands already have the required versions.

  • Return to the Windows PowerShell window from the Visual Studio Code check.
  • Check the installed Node.js and npm versions by running:
node --version
npm --version

What Do These Commands Check?

  • The node --version command reports the installed Node.js runtime version.
  • The npm --version command reports the npm version bundled with the Node.js installer.

The Node.js installer may trigger a Windows permission request. The direct download links below come from the official Node.js release.

✔️ I see both required versions

Your runtime already reports v24.21.0. Your package manager reports 11.19.0.

ⓧ I see different versions

Installing the pinned Node.js release replaces the mismatched runtime. The same installer supplies the matching npm version.

  • Download the Windows x64 installer when your Windows system type reports an x64-based processor.
  • Download the Windows Arm64 installer when your Windows system type reports an ARM-based processor.
  • Run the downloaded Node.js installer.
  • Approve the Windows permission request if it appears.
  • Complete the setup using the default options.

When setup finishes, Node.js plus npm are installed together.

ⓧ A command is not found

The pinned Node.js installer adds the runtime plus npm to your Windows computer.

  • Download the Windows x64 installer when your Windows system type reports an x64-based processor.
  • Download the Windows Arm64 installer when your Windows system type reports an ARM-based processor.
  • Run the downloaded Node.js installer.
  • Approve the Windows permission request if it appears.
  • Complete the setup using the default options.

When setup finishes, Node.js plus npm are installed together.

Microsoft Edge gives this project one consistent browser verification path. Windows usually includes it already.

  • Press the Windows key to open Windows search.
  • Type Microsoft Edge into the search box.
  • Select Microsoft Edge if it appears.

✔️ Microsoft Edge opens

Microsoft Edge is ready to display the Developer Launchpad in the next step.

ⓧ Microsoft Edge is unavailable

  • Open the Microsoft Edge download page in an available browser.
  • Select Download Edge for Windows.
  • Run the downloaded Microsoft Edge installer.
  • Complete the browser setup.

Windows search should now list Microsoft Edge.

Verify the toolchain in one terminal

A new terminal session picks up the command locations added by the installers. Restarting the console now prevents an old session from hiding a successful installation.

  • Close the standalone Windows PowerShell window.
  • Close any open Visual Studio Code windows.
  • Press the Windows key to open Windows search.
  • Type Visual Studio Code into the search box.
  • Press Enter to open Visual Studio Code.
  • Select View from the menu bar.
  • Select Terminal.
  • Select Windows PowerShell from the terminal profile menu.

Before you run the final check, do you expect all three commands to succeed from the same terminal?

  • Verify the runtime, package manager, and editor connection by running:
node --version
npm --version
code .

What Does the Final Check Prove?

  • The node --version command proves that Windows PowerShell can find the pinned Node.js runtime.
  • The npm --version command proves that the matching package manager is available.
  • The code . command proves that the Visual Studio Code command can open the current folder.

You will see v24.21.0 first. You will see 11.19.0 next.

Visual Studio Code opens the current folder after the final command. That is your Windows web development toolchain working from one terminal.

Checks Still Failing?

  • Close every Visual Studio Code window before repeating the check in a new Windows PowerShell terminal.
  • Run the Node.js installer that matches your recorded Windows system type if either version differs.
  • Run the Visual Studio Code User Installer again if PowerShell cannot find the editor command.

Help me diagnose my Windows tool setup

Your editor, runtime, package manager, browser, and terminal are ready. Next, you will turn an empty folder into an interactive Developer Launchpad page.

Build Your Developer Launchpad Page

Your verified Windows toolchain can now prove itself with something visible. The next milestone is a page you can open in Microsoft Edge from your Visual Studio Code workspace.

A browser can load front-end files directly from disk. This gives you an early working page before a local server enters the picture.

In this step, get ready to:
  • Create the developer-launchpad workspace with three front-end files.
  • Build the page structure with HTML plus its visual design with CSS.
  • Connect the button to browser JavaScript before testing the page in Microsoft Edge.
Create the project workspace

A workspace gives VS Code one named folder to manage. Your public folder will hold every file that Microsoft Edge loads.

The final command below opens the new folder in another Visual Studio Code window.

  • Return to the Windows PowerShell integrated terminal from the previous step.
  • Create the workspace on your Desktop by running these commands:
Set-Location -Path "$HOME\Desktop"
New-Item -Path "developer-launchpad" -ItemType Directory
Set-Location -Path "developer-launchpad"
New-Item -Path "public" -ItemType Directory
code .

What do these commands do?

  • The first command moves PowerShell to your Desktop.
  • The next commands create the developer-launchpad folder with a nested public folder.
  • The final command opens the current folder as your VS Code workspace.
  • Continue in the new Visual Studio Code window.
  • Check the Explorer sidebar for the public folder.

You should see developer-launchpad as the workspace name. Its public folder should appear in the Explorer sidebar.

Workspace folder missing?

Check that the terminal reached your Desktop before creating the folder. A redirected Windows Desktop may appear inside your OneDrive folder.

If the folder exists but is absent from Explorer, use File followed by Open Folder to select developer-launchpad from your Desktop.

Help me fix my project workspace.

The workspace is ready for its three front-end files. PowerShell can create them together so their locations stay consistent.

  • Switch to the integrated terminal in the developer-launchpad workspace.
  • Create the three files inside public by running these commands:
New-Item -Path "public\index.html" -ItemType File
New-Item -Path "public\style.css" -ItemType File
New-Item -Path "public\app.js" -ItemType File

What did this create?

  • The index.html file holds the page structure.
  • The style.css file controls the page design.
  • The app.js file handles the button interaction.
  • Expand the public folder in the Explorer sidebar.

You should see index.html, style.css, plus app.js listed inside the folder.

Files missing from Explorer?

Confirm that the terminal path ends with developer-launchpad. Running the commands from another folder creates the files in the wrong place.

If PowerShell reports that a file already exists, keep the existing file. Select it from the Explorer sidebar before continuing.

Help me find my front-end files.

Build and style the page

The HTML defines everything the browser displays. It also connects the stylesheet plus a deferred script that runs after the page structure is ready.

  • Select public/index.html in the Explorer sidebar.
  • Paste this code into the empty editor:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Developer Launchpad</title>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js" defer></script>
  </head>
  <body>
    <main>
      <p class="eyebrow">Windows web development setup</p>
      <h1>Developer Launchpad</h1>
      <p>Your local project is ready for a focused coding session.</p>

      <ul>
        <li>Visual Studio Code workspace opened</li>
        <li>Node.js runtime connected</li>
        <li>Browser JavaScript loaded</li>
      </ul>

      <button id="start-session" type="button">Start my coding session</button>
      <p id="status" aria-live="polite">Waiting for your first click.</p>
    </main>
  </body>
</html>

What does this code do?

  • The head section sets the page title before connecting style.css plus app.js.
  • The main section contains the heading with its setup checklist.
  • The start-session button gives the script a specific element to detect.
  • The status paragraph gives the script a specific place to display feedback.
  • Save public/index.html.
  • Right-click public/index.html in the Explorer sidebar.
  • Select Reveal in File Explorer.
  • Right-click index.html in File Explorer.
  • Select Open with.
  • Choose Microsoft Edge.

You should see the Developer Launchpad heading with its checklist. The page still uses the browser's basic styling.

Page blank or missing text?

Make sure index.html is saved inside the public folder. Check that the opening plus closing main tags both appear in the file.

Help me fix the blank HTML page.

The browser now has the page structure. The first CSS section creates the full-screen background with its centered card.

  • Switch back to Visual Studio Code.
  • Select public/style.css in the Explorer sidebar.
  • Paste this first CSS section into the empty editor:
:root {
  font-family: "Segoe UI", sans-serif;
  color: #e8eef9;
  background: #08111f;
}

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #08111f, #162b4d);
}

main {
  width: min(680px, 90vw);
  padding: 2.5rem;
  border: 1px solid #36577f;
  border-radius: 1.25rem;
  background: rgba(12, 27, 48, 0.92);
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.35);
}

What does this CSS control?

  • The :root block sets the page font with its base colours.
  • The body block fills the browser window with a dark gradient.
  • The main block turns the content into a centered card.
  • Save public/style.css.
  • Refresh the Developer Launchpad tab in Microsoft Edge.

You should see the content centered inside a dark rounded card. A blue gradient should fill the page behind it.

Still seeing an unstyled page?

Check that style.css sits beside index.html inside public. Confirm that the HTML link uses href="style.css".

Help me connect the stylesheet.

The card has its overall shape. The next CSS section improves the text hierarchy with its checklist spacing plus button design.

  • Return to public/style.css in Visual Studio Code.
  • Paste this section below the closing brace of the main block:
.eyebrow {
  margin: 0;
  color: #7dd3fc;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1 {
  margin-bottom: 0.5rem;
  font-size: clamp(2rem, 6vw, 3.5rem);
}

ul {
  margin: 1.5rem 0;
  padding-left: 1.25rem;
  line-height: 1.8;
}

button {
  padding: 0.8rem 1.1rem;
  border: 0;
  border-radius: 0.65rem;
  color: #08111f;
  background: #7dd3fc;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

How does this refine the page?

  • The .eyebrow block turns the setup label into a compact blue heading.
  • The h1 block gives the main title a responsive size.
  • The ul block makes the checklist easier to scan.
  • The button block creates the blue rounded control.
  • Save public/style.css.
  • Refresh the page in Microsoft Edge.

You should see a larger Developer Launchpad heading. The checklist should have wider line spacing beneath the blue setup label.

Text or button unchanged?

Confirm that this section appears after the closing brace of the main block. A missing brace can cause the browser to ignore the selectors below it.

Help me find the CSS syntax issue.

The final CSS section adds hover feedback to the button. It also gives the status message a stable space with a green colour.

  • Return to public/style.css in Visual Studio Code.
  • Paste this section below the closing brace of the button block:
button:hover {
  background: #bae6fd;
}

#status {
  min-height: 1.5rem;
  margin-top: 1rem;
  color: #a7f3d0;
}

What finishes the design?

  • The button:hover selector lightens the button when your pointer rests over it.
  • The #status selector reserves space for feedback beneath the button.
  • Save public/style.css.
  • Refresh the page in Microsoft Edge.
  • Move your pointer over Start my coding session.

You should see the button change to a lighter blue. The waiting status should appear in green beneath it.

Hover colour missing?

Check that the selector includes the colon in button:hover. Confirm that the block appears after the main button styles.

Help me fix the button hover style.

Add the button interaction

An event listener waits for a specific browser action. Your script will listen for a click before replacing the text inside the status paragraph.

  • Select public/app.js in the Explorer sidebar.
  • Paste this code into the empty editor:
const startButton = document.querySelector("#start-session");
const statusText = document.querySelector("#status");

startButton.addEventListener("click", () => {
  statusText.textContent =
    "Session started. Your editor, JavaScript, and browser are working together.";
});

What does this code do?

  • The startButton constant stores the page element with the #start-session selector.
  • The statusText constant stores the page element with the #status selector.
  • The click listener changes statusText.textContent when you use the button.
  • Save public/app.js.
  • Return to the Developer Launchpad tab in Microsoft Edge.

Before you refresh, which result do you expect from the button? Which kind of address do you expect to see?

  • Refresh the Developer Launchpad page.
  • Click Start my coding session.
  • Inspect the beginning of the address in the Microsoft Edge address bar.

You should see Session started. Your editor, JavaScript, and browser are working together. beneath the button. The address bar should still begin with file:///.

You have your first working browser interaction. The button now updates the page in Microsoft Edge.

What does the file address prove?

The file:/// address means Microsoft Edge loaded index.html directly from your computer's disk.

No Node.js HTTP server is handling the page yet. That missing server is the intended limit of this first working version.

Button not changing the status?

Confirm that app.js sits beside index.html inside public. Check that the script tag uses src="app.js".

Compare #start-session with the button's id="start-session". Compare #status with the paragraph's id="status".

Help me debug the button interaction.

✔️ Awesome, I've got everything!

Great. Make sure all three files inside public are saved.

ⓧ I'd like to double check the full code

Compare each saved file with the complete versions below.

public/index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Developer Launchpad</title>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js" defer></script>
  </head>
  <body>
    <main>
      <p class="eyebrow">Windows web development setup</p>
      <h1>Developer Launchpad</h1>
      <p>Your local project is ready for a focused coding session.</p>

      <ul>
        <li>Visual Studio Code workspace opened</li>
        <li>Node.js runtime connected</li>
        <li>Browser JavaScript loaded</li>
      </ul>

      <button id="start-session" type="button">Start my coding session</button>
      <p id="status" aria-live="polite">Waiting for your first click.</p>
    </main>
  </body>
</html>

public/style.css

:root {
  font-family: "Segoe UI", sans-serif;
  color: #e8eef9;
  background: #08111f;
}

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #08111f, #162b4d);
}

main {
  width: min(680px, 90vw);
  padding: 2.5rem;
  border: 1px solid #36577f;
  border-radius: 1.25rem;
  background: rgba(12, 27, 48, 0.92);
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.35);
}

.eyebrow {
  margin: 0;
  color: #7dd3fc;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1 {
  margin-bottom: 0.5rem;
  font-size: clamp(2rem, 6vw, 3.5rem);
}

ul {
  margin: 1.5rem 0;
  padding-left: 1.25rem;
  line-height: 1.8;
}

button {
  padding: 0.8rem 1.1rem;
  border: 0;
  border-radius: 0.65rem;
  color: #08111f;
  background: #7dd3fc;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

button:hover {
  background: #bae6fd;
}

#status {
  min-height: 1.5rem;
  margin-top: 1rem;
  color: #a7f3d0;
}

public/app.js

const startButton = document.querySelector("#start-session");
const statusText = document.querySelector("#status");

startButton.addEventListener("click", () => {
  statusText.textContent =
    "Session started. Your editor, JavaScript, and browser are working together.";
});

Your front end now works directly from disk. Next, you will serve the same page through a repeatable npm workflow with a local HTTP address.

Serve the App with Node.js

Your Developer Launchpad already responds to a click in Microsoft Edge. That result proves the front-end files work together.

The file:/// address still points straight to a file on your computer. A web app needs a local server to answer browser requests through HTTP.

In this step, you will package the project with npm. You will serve the same page with Node.js at http://127.0.0.1:3000.

In this step, get ready to:
  • Define a repeatable start command in package.json.
  • Create a local server that routes browser requests to the front-end files.
  • Start the app with npm start and verify it through a local HTTP address.
Create the npm workflow

An npm script gives your project one dependable start command. The package configuration also tells Node.js to treat .js files as CommonJS modules.

  • Create package.json beside the public folder by using the file creation control in the Explorer sidebar.
  • Define the project package by pasting this code into package.json:
{
  "name": "developer-launchpad",
  "version": "1.0.0",
  "type": "commonjs",
  "scripts": {
    "start": "node server.js"
  }
}

What does this configuration do?

  • The name and version fields identify the local package.
  • The type field enables the CommonJS module format used by server.js.
  • The start script gives npm the instruction that launches the server.
  • Save package.json.
  • Confirm package.json appears beside the public folder in Explorer.

You should see the saved package file in the project workspace with no JSON syntax highlighted as invalid.

Seeing a JSON problem?

Check each comma and quotation mark in package.json. JSON requires double quotation marks around every key and string value.

Ask for help with the exact section VS Code highlights: help me fix my package.json syntax

Build the local server

The server needs a map between browser paths and the files inside public. Node.js includes the modules needed to receive requests, read files, and build Windows-safe file paths.

Why use built-in Node.js modules?

Built-in modules keep this first server focused on the request flow. You can see how a browser path becomes a file response without adding a third-party framework.

  • Create server.js beside package.json by using the file creation control in the Visual Studio Code Explorer sidebar.
  • Add the server modules and file map by pasting this code into server.js:
const http = require("node:http");
const fs = require("node:fs");
const path = require("node:path");

const host = "127.0.0.1";
const port = 3000;

const files = {
  "/": {
    body: fs.readFileSync(path.join(__dirname, "public", "index.html")),
    contentType: "text/html; charset=utf-8",
  },
  "/style.css": {
    body: fs.readFileSync(path.join(__dirname, "public", "style.css")),
    contentType: "text/css; charset=utf-8",
  },
  "/app.js": {
    body: fs.readFileSync(path.join(__dirname, "public", "app.js")),
    contentType: "text/javascript; charset=utf-8",
  },
};

What does this code do?

  • The http module provides the local web server.
  • The fs module reads each saved front-end file into memory.
  • The path module builds file locations using the correct Windows separator.
  • The files map connects each browser path to its response body and content type.
  • Save server.js.
  • Confirm the file map contains /, /style.css, and /app.js.

You should see all three routes in server.js. Each route points to its matching file inside public.

Does a file path look wrong?

Check that every file path begins with __dirname and includes the public folder. Confirm each filename matches the Explorer sidebar.

Use this prompt if a route points to the wrong file: help me check my Node.js file map

  • Place your cursor after the closing }; for the files map in server.js.
  • Add the request handler and listener by pasting this code below the file map:
const server = http.createServer((request, response) => {
  const file = files[request.url];

  if (!file) {
    response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
    response.end("Not found");
    return;
  }

  response.writeHead(200, { "Content-Type": file.contentType });
  response.end(file.body);
});

server.listen(port, host, () => {
  console.log(`Developer Launchpad running at http://${host}:${port}`);
});

How does the request flow work?

  • The http.createServer() callback receives each browser request and its response.
  • The request.url value selects the matching entry from files.
  • A missing entry returns status code 404 with the text Not found.
  • A matching entry returns status code 200 with the file body and its content type.
  • The server.listen() call starts the server on host 127.0.0.1 and port 3000.
  • Save server.js.
  • Confirm the final line closes the server.listen() call.

Your saved server now has a complete request handler and a listener for the local address.

Seeing JavaScript syntax highlighting in the wrong place?

Check the closing braces and parentheses around http.createServer() and server.listen(). The listener belongs after the request handler has closed.

Use this prompt to compare the two sections: help me find the syntax issue in server.js

✔️ Awesome, I've got everything!

Great work. Make sure package.json and server.js are saved before you start the server.

ⓧ I'd like to double check the full code

Compare each project file with the saved version below.

package.json.

{
  "name": "developer-launchpad",
  "version": "1.0.0",
  "type": "commonjs",
  "scripts": {
    "start": "node server.js"
  }
}

server.js.

const http = require("node:http");
const fs = require("node:fs");
const path = require("node:path");

const host = "127.0.0.1";
const port = 3000;

const files = {
  "/": {
    body: fs.readFileSync(path.join(__dirname, "public", "index.html")),
    contentType: "text/html; charset=utf-8",
  },
  "/style.css": {
    body: fs.readFileSync(path.join(__dirname, "public", "style.css")),
    contentType: "text/css; charset=utf-8",
  },
  "/app.js": {
    body: fs.readFileSync(path.join(__dirname, "public", "app.js")),
    contentType: "text/javascript; charset=utf-8",
  },
};

const server = http.createServer((request, response) => {
  const file = files[request.url];

  if (!file) {
    response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
    response.end("Not found");
    return;
  }

  response.writeHead(200, { "Content-Type": file.contentType });
  response.end(file.body);
});

server.listen(port, host, () => {
  console.log(`Developer Launchpad running at http://${host}:${port}`);
});

public/index.html.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Developer Launchpad</title>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js" defer></script>
  </head>
  <body>
    <main>
      <p class="eyebrow">Windows web development setup</p>
      <h1>Developer Launchpad</h1>
      <p>Your local project is ready for a focused coding session.</p>

      <ul>
        <li>Visual Studio Code workspace opened</li>
        <li>Node.js runtime connected</li>
        <li>Browser JavaScript loaded</li>
      </ul>

      <button id="start-session" type="button">Start my coding session</button>
      <p id="status" aria-live="polite">Waiting for your first click.</p>
    </main>
  </body>
</html>

public/style.css.

:root {
  font-family: "Segoe UI", sans-serif;
  color: #e8eef9;
  background: #08111f;
}

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #08111f, #162b4d);
}

main {
  width: min(680px, 90vw);
  padding: 2.5rem;
  border: 1px solid #36577f;
  border-radius: 1.25rem;
  background: rgba(12, 27, 48, 0.92);
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.35);
}

.eyebrow {
  margin: 0;
  color: #7dd3fc;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1 {
  margin-bottom: 0.5rem;
  font-size: clamp(2rem, 6vw, 3.5rem);
}

ul {
  margin: 1.5rem 0;
  padding-left: 1.25rem;
  line-height: 1.8;
}

button {
  padding: 0.8rem 1.1rem;
  border: 0;
  border-radius: 0.65rem;
  color: #08111f;
  background: #7dd3fc;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

button:hover {
  background: #bae6fd;
}

#status {
  min-height: 1.5rem;
  margin-top: 1rem;
  color: #a7f3d0;
}

public/app.js.

const startButton = document.querySelector("#start-session");
const statusText = document.querySelector("#status");

startButton.addEventListener("click", () => {
  statusText.textContent =
    "Session started. Your editor, JavaScript, and browser are working together.";
});
Start and verify the app

The npm script now starts a Node.js process that keeps listening for browser requests. Your Windows PowerShell terminal stays occupied while that server is running.

Before you run the server, predict whether the address it prints begins with file:/// or http://.

  • Start the local server from the existing VS Code Windows PowerShell terminal by running:
npm start

What does npm start do?

npm reads the start script from package.json and launches server.js with Node.js.

You should see Developer Launchpad running at http://127.0.0.1:3000 in the terminal. The waiting cursor means the server is ready for requests.

Did the server fail to start?

Confirm the terminal is inside the developer-launchpad folder. Check that Explorer shows both package.json and server.js beside public.

Use the terminal output with this prompt: help me troubleshoot why npm start cannot launch my local Node.js server

Before you load the page, predict which part of the address proves the browser is now talking to a server.

  • Return to Microsoft Edge from earlier.
  • Enter http://127.0.0.1:3000 in the address bar.

You should see the styled Developer Launchpad again. Its address now begins with http://.

  • Click Start my coding session.

You should see the status change to Session started. Your editor, JavaScript, and browser are working together. That confirms the server delivered the HTML, CSS, and browser JavaScript successfully.

That is the server boundary crossed. Your Developer Launchpad now runs through one repeatable npm command while keeping its browser interaction intact.

  • Leave the server running for the next step.
  • Press Ctrl+C whenever you need to stop the server and regain the terminal prompt.

Your local web workflow is working from browser click to Node.js response. Next, you will pause a live request inside the server and inspect the path that Microsoft Edge sent.

Debug a Live Node.js Request

Your Node.js server already delivers the Developer Launchpad to Microsoft Edge. The terminal confirms that the server started, but it cannot show which browser path enters the request handler.

The Visual Studio Code debugger can pause a live request at a breakpoint. You can then inspect request.url before the server chooses a file.

In this step, get ready to:
  • Stop the normal Node.js server and set a breakpoint inside its request handler.
  • Start the server from the JavaScript Debug Terminal.
  • Pause a browser request and inspect its URL in Visual Studio Code.
Set a breakpoint in the request handler

A breakpoint marks a line where the debugger pauses execution. The server must stop before you restart it under the debugger.

  • Switch back to the Windows PowerShell integrated terminal from earlier.
  • Press Ctrl+C to stop the normal server.
  • Select server.js in the Visual Studio Code Explorer sidebar.
  • Find the line containing const file = files[request.url];.
  • Click the editor gutter beside that line.

You should see a red breakpoint marker beside const file = files[request.url];. The debugger now has a precise place to pause each request.

Cannot see the breakpoint marker?

Make sure you clicked the narrow gutter to the left of the line number. You can also place your cursor on the target line and press F9.

Ask for help if the breakpoint still does not appear: help me set a breakpoint on the file lookup line in server.js

Start a JavaScript Debug Terminal

A JavaScript Debug Terminal automatically attaches the debugger to Node.js processes started inside it. This connects your existing server command to the breakpoint.

  • Press Ctrl+Shift+P to open the Command Palette.
  • Enter Debug: Create JavaScript Debug Terminal in the Command Palette search box.
  • Select Debug: Create JavaScript Debug Terminal from the results.

You should see a new terminal panel ready for a command. Commands started here run with the JavaScript debugger attached.

  • Start the server under the Visual Studio Code debugger by running:
npm start

What does this command do?

  • The npm start command runs the start script from package.json.
  • That script starts node server.js inside the debugger-enabled terminal.

You should see the Developer Launchpad address http://127.0.0.1:3000 printed in the JavaScript Debug Terminal. The server is ready to receive a request.

Server does not start?

A previous server process may still be using port 3000. Return to that terminal and press Ctrl+C before trying again in the JavaScript Debug Terminal.

Ask for help if the server still fails to start: help me start npm in the JavaScript Debug Terminal

Inspect the live request

The next browser refresh sends a live request through the server handler. The breakpoint gives you a chance to inspect that request before the response continues.

Before you refresh, do you think the request will pass through the handler immediately or pause inside Visual Studio Code?

  • Switch back to the Developer Launchpad page in Microsoft Edge.
  • Refresh http://127.0.0.1:3000.

Visual Studio Code should pause on const file = files[request.url];. The highlighted line shows where the current request stopped.

  • Find request.url in the VARIABLES area.
  • Hover over request.url in the highlighted line if you prefer an inline view.

You should see request.url set to /. This value proves that Microsoft Edge requested the root route of your server.

Before you continue, what do you expect the paused request to do after the debugger releases it?

  • Press F5 to continue the request.
  • Switch back to Microsoft Edge.

You should see the Developer Launchpad finish loading at http://127.0.0.1:3000. You have now paused a real browser request and inspected the route received by Node.js.

Request does not pause?

Confirm that the red breakpoint remains beside const file = files[request.url];. Confirm that the server is running in the JavaScript Debug Terminal.

Ask for help if refreshing the page still skips the breakpoint: help me debug why my Node.js breakpoint is not pausing

Debugging leaves every project file unchanged. Use these tabs to confirm that your saved files still match the working project.

✔️ Awesome, I've got everything!

Your files are unchanged. Leave the breakpoint set in server.js.

ⓧ I'd like to double check the full code

Compare each saved file with the matching reference below.

package.json.

{
  "name": "developer-launchpad",
  "version": "1.0.0",
  "type": "commonjs",
  "scripts": {
    "start": "node server.js"
  }
}

public/app.js.

const startButton = document.querySelector("#start-session");
const statusText = document.querySelector("#status");

startButton.addEventListener("click", () => {
  statusText.textContent =
    "Session started. Your editor, JavaScript, and browser are working together.";
});

public/index.html.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Developer Launchpad</title>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js" defer></script>
  </head>
  <body>
    <main>
      <p class="eyebrow">Windows web development setup</p>
      <h1>Developer Launchpad</h1>
      <p>Your local project is ready for a focused coding session.</p>

      <ul>
        <li>Visual Studio Code workspace opened</li>
        <li>Node.js runtime connected</li>
        <li>Browser JavaScript loaded</li>
      </ul>

      <button id="start-session" type="button">Start my coding session</button>
      <p id="status" aria-live="polite">Waiting for your first click.</p>
    </main>
  </body>
</html>

public/style.css.

:root {
  font-family: "Segoe UI", sans-serif;
  color: #e8eef9;
  background: #08111f;
}

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #08111f, #162b4d);
}

main {
  width: min(680px, 90vw);
  padding: 2.5rem;
  border: 1px solid #36577f;
  border-radius: 1.25rem;
  background: rgba(12, 27, 48, 0.92);
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.35);
}

.eyebrow {
  margin: 0;
  color: #7dd3fc;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1 {
  margin-bottom: 0.5rem;
  font-size: clamp(2rem, 6vw, 3.5rem);
}

ul {
  margin: 1.5rem 0;
  padding-left: 1.25rem;
  line-height: 1.8;
}

button {
  padding: 0.8rem 1.1rem;
  border: 0;
  border-radius: 0.65rem;
  color: #08111f;
  background: #7dd3fc;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

button:hover {
  background: #bae6fd;
}

#status {
  min-height: 1.5rem;
  margin-top: 1rem;
  color: #a7f3d0;
}

server.js.

const http = require("node:http");
const fs = require("node:fs");
const path = require("node:path");

const host = "127.0.0.1";
const port = 3000;

const files = {
  "/": {
    body: fs.readFileSync(path.join(__dirname, "public", "index.html")),
    contentType: "text/html; charset=utf-8",
  },
  "/style.css": {
    body: fs.readFileSync(path.join(__dirname, "public", "style.css")),
    contentType: "text/css; charset=utf-8",
  },
  "/app.js": {
    body: fs.readFileSync(path.join(__dirname, "public", "app.js")),
    contentType: "text/javascript; charset=utf-8",
  },
};

const server = http.createServer((request, response) => {
  const file = files[request.url];

  if (!file) {
    response.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
    response.end("Not found");
    return;
  }

  response.writeHead(200, { "Content-Type": file.contentType });
  response.end(file.body);
});

server.listen(port, host, () => {
  console.log(`Developer Launchpad running at http://${host}:${port}`);
});
  • Leave the debug server running in the JavaScript Debug Terminal.

That is the complete debugging loop working. Visual Studio Code can now pause your Node.js server while Microsoft Edge waits for the response.

Secret mission

Add a Server Status Endpoint

Your Developer Launchpad already serves its front-end files through a local Node.js server. Extend that server with a dedicated status endpoint that confirms it is running without changing the page.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your Windows computer, so there are no ongoing cloud costs. Decide whether to keep your local resources running, pause them for later, or delete them entirely.

Resources you used:

  • A local Node.js server process for the Developer Launchpad.
  • A local developer-launchpad project folder containing the saved webpage and server files.

Keep everything running

No action is needed. Choose this option if you are still testing or extending the Developer Launchpad.

  • Keep the local server running while you continue using the Developer Launchpad.
  • Keep the developer-launchpad folder so every project file remains available.
  • Leave your development tools installed so you can reuse them for future projects.

Pause - I'll come back to this later

Shut down the running server to free local memory. Your saved project files remain ready for your next session.

  • Stop the local server by pressing Ctrl+C in the debug terminal from earlier.
  • Keep the developer-launchpad folder on your computer.

You should see the PowerShell prompt return. Your server is now paused without changing any project files.

Delete - I don't want to use this again

Remove the local server process and project files to start fresh. This deletion is permanent, so use this option only when you no longer need your code.

  • Stop the local server by pressing Ctrl+C in the debug terminal from earlier.
  • Remove the developer-launchpad folder from its parent directory by running these PowerShell commands:
Set-Location ..
Remove-Item -Recurse -Force .\developer-launchpad

What Do These Commands Do?

  • The first line moves PowerShell to the folder that contains developer-launchpad.
  • The second line permanently removes the project folder and every file inside it.

Cleanup complete. PowerShell returns to its prompt without an error because the local project folder is gone.

Folder Won't Delete?

  • Confirm the Node.js server has stopped before trying the removal again.
  • Close any other app that has a file from developer-launchpad open.
  • Help me diagnose this PowerShell folder removal problem.

Nice Work!

Nice Work!

You made it! Your Developer Launchpad now runs as an interactive local web app with a debugged server.

You've learned how to:

  • Built an interactive Developer Launchpad inside a Visual Studio Code workspace that responds to button clicks in Microsoft Edge.
  • Served the page from a local Node.js HTTP server through npm start at http://127.0.0.1:3000.
  • Paused a live browser request at a breakpoint to inspect request.url in the Visual Studio Code debugger.
  • Completed the optional Secret Mission by adding a /status endpoint that confirms the server is running.

Ready to quiz yourself?