JOUR 73361
Coding the News
Learn how America's top news organizations escape rigid publishing systems to design beautiful data-driven stories on deadline.
Static-Site Frameworks
How to publish a website with Node.JS and GitHub Actions
Feb. 2, 2026
Part 1: Introduction to Frameworks
What's a framework? Nothing more than a fancy name for a set of software tools that can create and publish a website.
It takes dozens of different software tricks to pull a good site together. Frameworks aim to make the challenge easier by curating a set of time-saving tools that can work in harmony.
There are a lot of different frameworks out there. Maybe you've heard of some of them, like React, Next.js, Svelte, Django, or Ruby on Rails.
Each newsroom tends to go its own way, picking and choosing among the most popular tools. While the programming languages and the details vary from shop to shop, the fundamentals are almost all the same.
Many newsroom frameworks are published as open source software, including templates you can use to get started quickly.
Examples include:
- Reuters' graphics-kit
- The Los Angeles Times' baker
- The Pudding's svelte-starter
- The City's fullpage-react-template
- The Texas Tribune's data-visuals-create
- The Seattle Times' newsapp-template
- NPR's dailygraphics
While they were developed separately, they all have two things in common.
One, they follow a web development approach known as static-site generation. This means that, regardless of what tools they use, they ultimately build a set of static HTML, CSS, and JavaScript files that can be served by any web server. That's unlike dynamic sites that generate pages on the fly using server-side code and databases, like WordPress or Drupal.
It's a popular development pattern for simple sites, and it dominates newsroom projects. Static sites are cheaper, more secure, more stable and easier to archive than sites that rely on dynamic systems.
Two, they all use the Node.js programming system, which will be the first thing we need to install.
Part 2: Introduction to Node.js
Node.js is a system that lets you run JavaScript, the programming language of the web, on your computer, not just in a web browser. It's the engine that powers most modern web development tools, including all of the newsroom frameworks we just discussed.
Its massive ecosystem of open-source packages, accessible via the Node Package Manager, provides developers with a vast array of tools to build applications. Those tools include static-site frameworks invented and supported by major tech companies, as well as countless smaller projects maintained by individual developers.
You can learn more about it at nodejs.org.
Check if Node.js is already installed
Before we install anything, let's check if you already have Node.js on your computer. Some of you may have installed it for another class or project.
Open Visual Studio Code. If you don't have a project open, that's fine. Click Terminal in the menu bar and select New Terminal.
Type this command and press Enter:
node --version If Node.js is installed, you'll see a version number like v20.11.0 or similar. If you see a version starting with v18, v20, or higher, you're all set! You can skip ahead to Part 3.
If you see an error message like command not found: node, that means Node.js isn't installed yet.
We'll fix that with a tool called Node Version Manager.
Install nvm
Node Version Manager, also known as nvm, is a command-line tool that makes it easy to install and manage multiple versions of Node.js on your computer. It's especially useful for developers who need to switch between different Node.js versions for different projects.
Before we can use it to install Node.js, we need to install nvm itself.
Copy and paste this command into your terminal and press Enter:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash This downloads and runs the official nvm installation script. You'll see some output as it installs. It should look something like:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 16774 100 16774 0 0 45969 0 --:--:-- --:--:-- --:--:-- 45956
=> Downloading nvm from git to '/Users/U6122976/.nvm'
=> Cloning into '/Users/U6122976/.nvm'...
remote: Enumerating objects: 403, done.
remote: Counting objects: 100% (403/403), done.
remote: Compressing objects: 100% (332/332), done.
remote: Total 403 (delta 56), reused 168 (delta 43), pack-reused 0 (from 0)
Receiving objects: 100% (403/403), 404.19 KiB | 2.41 MiB/s, done.
Resolving deltas: 100% (56/56), done.
* (HEAD detached at FETCH_HEAD)
master
=> Compressing and cleaning up git repository
=> Appending nvm source string to /Users/U6122976/.zshrc
=> Appending bash_completion source string to /Users/U6122976/.zshrc
=> Close and reopen your terminal to start using nvm or run the following to use it now:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion At the very bottom there, you'll see a message about adding nvm to your terminal's configuration file. In my case, it's called the .zshrc file, because I'm using the Z shell terminal program. Yours might be called .bashrc or .bash_profile if you're using Bash, or another name if you're using a different terminal program.
This is important, because it is how nvm is booted up whenever you open a terminal. And it won't take effect until you restart your terminal, so do that now before you proceed.
In the new terminal you should verify nvm is installed by typing:
nvm --version You should see a version number like 0.40.4. Now you're ready to install Node.js.
Install Node.js with nvm
Now we can use nvm to install Node.js by typing this command:
nvm install --lts The --lts option tells nvm to install the "Long Term Support" version of Node.js. This is the stable, recommended version for most users. You'll see progress as it downloads and installs. It should look something like this:
Installing latest LTS version.
Downloading and installing node v24.13.0...
Downloading https://nodejs.org/dist/v24.13.0/node-v24.13.0-darwin-arm64.tar.xz...
################################################################################# 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v24.13.0 (npm v11.6.2)
Creating default alias: default -> lts/* (-> v24.13.0 *) Let's confirm everything worked by running the same command as before:
node --version You should now see a version number like v24.13.0, or whatever the current LTS version is.
You should also check that the Node Package Manager was installed alongside Node.js, which is the tool we'll use to install additional packages.
npm --version You should see a version number like 11.6.2.
You now have Node.js installed and ready to use. This is the foundation that will power all the web development tools we'll use throughout the rest of this course.
Part 3: Creating a page from a static-site template
Now that you have Node.js installed, let's put it to work. We're going to use a GitHub template I've created for this class. It's a minimal framework configured to build static websites in the style of CUNY's NYCity News Service.
Create a new repository from the template
Open your browser and navigate to github.com/palewire/cuny-jour-static-site-template.
Click the green "Use this template" button near the top right of the page. Select "Create a new repository" from the dropdown menu. You'll be taken to a page where you can name your new repository.
Select your account as the owner. Enter my-first-static-site as the repository name. Make sure "Public" is selected in the visibility options. Then click the green "Create repository" button.
After a moment, you'll be redirected to your new repository's page.
Clone the repository to your computer
Now let's get this code onto your computer using the techniques we covered in week one.
Open a new window in Visual Studio Code. Click on the "Source Control" icon in the left sidebar, the one that looks like a Y or a branch, and click the "Clone Repository" button.
A popup will appear at the top of the window asking for a repository URL. Go back to your browser, copy the URL to your new repository and paste it into the popup. Press enter.
A file dialog will open asking where to save the project. Navigate to your Code folder we made last week and click "Select Repository Location." After a few moments, VS Code will ask if you want to open the cloned repository. Click "Open."
You should now see the project files in the Explorer sidebar. Take a moment to look around. You'll see folders like src and static, and files like package.json and svelte.config.js.

Install the project dependencies
Before we can run the project, we need to install its dependencies. These are external packages of code that the project needs to work. They're listed in the package.json file.

Open a terminal in VS Code by clicking "Terminal" in the menu bar and selecting "New Terminal". Type the following command and press Enter:
npm install This tells Node Package Manager to read the package.json file and download all the packages listed there. You'll see a progress indicator as packages are downloaded. This may take a minute or two the first time.
When it's done, you'll see a summary of what was installed.

You'll notice a new node_modules folder has appeared in the Explorer. This contains all the downloaded packages. You don't need to look inside it and, in fact, it's best to ignore it entirely.
Another new file is called package-lock.json. This file locks the exact versions of the installed packages to ensure consistency across different environments. You also don't need to edit this file manually. It's for computers, not humans.
Start the development server
Now for the fun part. Type this command in the terminal:
npm run dev This starts a local development server on your computer. After a moment, you'll see a message saying the server is running, with a URL like http://localhost:5173.

Open your browser and navigate to that URL, http://localhost:5173. You should see the template homepage.
Congratulations! You're running a local web server. Unlike the demonstration page we saw earlier, this page you see is being generated by the code in your project folder.
Make your first edit
Let's change something. In VS Code's Explorer sidebar, navigate to src/routes/+page.svelte and click to open it.

This is the homepage of your site. There's a lot going on here. We'll cover it all in detail later. For now, just focus on the top part of the file, the part inside the script tags.
Find the line that says:
let headline = 'Become a force for good. Join our next class.'; Change it to something more personal, like:
let headline = 'Breaking News: This is my first static site!'; Save the file. Now look at your browser. Without refreshing, the page has automatically updated to show your new text!
Try making a few more changes. Edit the byline and publication date. Get a feel for how quickly you can see your changes reflected.
The project structure
We'll dig into more later, but let's pause briefly for an overview of the main files and folders in this project:
| Files | Description |
|---|---|
src/routes/+page.svelte | Your homepage. The +page.svelte file in any folder becomes a page on your site. |
src/routes/+layout.svelte | Wraps every page. It's where you'd put headers, footers, or navigation that appears on all pages. |
src/app.css | Global styles that apply to your entire site. |
src/app.html | The HTML shell that wraps everything. |
static/ | A folder for static files like images. Anything here is copied directly to your built site. |
package.json | Lists your project's dependencies and scripts. |
svelte.config.js | Configuration for SvelteKit, including how to build your site. |
You can ask Copilot to explain any of these files in more detail. Just open the file and ask in the chat panel, "What does this file do?"
Stop the development server
When you're done working, you can stop the development server by clicking in the terminal and pressing Ctrl + C. You'll see a message confirming the server has stopped.
You can restart it anytime by running npm run dev again.
Part 4: Publishing with GitHub Pages and Actions
You have a website running on your computer, but how do you share it with the world? That's where GitHub Pages comes in. It's a free hosting service that can publish static websites directly from any GitHub repository.
It might not sound like much, but this simple, generous service is used by developers to host a gigantic number of websites, ranging from personal portfolios and open-source documentation to highly sophisticated commercial sites.
I routinely use to publish hobby projects, like cummings.ee, moneyinpolitics.wtf and studs.show.
To take advantage of it, we need to tell GitHub to serve your repository as a website. Go to your my-first-static-site repository on GitHub in your browser.
Click on "Settings" in the top navigation bar and then select "Pages" from the left sidebar.
Under "Source," you'll see a dropdown that likely says "Deploy from a branch." Click it and select GitHub Actions instead.
That's it. GitHub will now look for a GitHub Actions workflow in your repository that builds and deploys your site whenever you push changes.
But, wait, what are GitHub Actions?
Introduction to GitHub Actions
GitHub Actions is a powerful automation platform built into GitHub. It allows you to create custom workflows that automate tasks like building, testing, and deploying code whenever certain events occur in your repository. It's yet another reason that GitHub is so popular.
We won't cover it in great detail in this class, but Actions is quickly becoming an essential tool in the data journalism toolbox. You can learn more about it in "Go big with GitHub Actions," an open-source textbook I developed with Iris Lee and Dana Chiueh.
GitHub Actions are configured by workflow files stored in your repository's .github/workflows/ folder. Each workflow is written in the YAML format, which is yet another arcane way that humans like to boss computers around.
Open the .github/workflows/deploy.yml file in your project. This file defines a workflow that builds and deploys your static site to GitHub Pages whenever you push changes.

Commit and push your changes
That means all you have to do to publish your page is commit and push the changes you made earlier to +page.svelte.
In Visual Studio Code, open the "Source Control" panel we learned about last week. Commit your changes with a message like "Updated headline" and push them to GitHub.
Watch the workflow run
Go back to your repository on GitHub in your browser. Click on the "Actions" tab.
You should see a workflow run with your commit message as its title. It's running through the same steps you ran locally, installing dependencies and building the site, but on GitHub's servers. It will spin for a few minutes and then, if all goes well, resolve as a green check mark.
The first commit's run at the bottom of the list will likely have failed, because Pages wasn't set up yet. Don't worry about that one. Focus on the most recent run at the top of the list.
View your published site
Click into the most recent workflow run to see its details. The "Deploy" step should have a URL to your live site.
You can also figure out your URL on your own by following GitHub's standard Pages URL format:
https://<your-username>.github.io/<your-repo-name>/ Hit the link to visit your site. You should see the same page you were editing locally, now available to anyone on the internet.
From now on, every time you push changes to your repository, GitHub Actions will automatically rebuild and redeploy your site. The whole process takes just a minute or two.
Homework Assignments
Task 1: Create three static sites
Create three different repositories using the class template. Each should have a different name and personalized content.
They don't have to do much. The point is to get practice. Swap out the image, rewrite the body text, change the byline to your own name, or whatever you like.
Deploy all three to GitHub Pages. Send me links to all three live sites before next Monday's class.
Task 2: Explore another newsroom's template
Find a static site template from a news organization and try to create a new project from it. Use Copilot to help you understand how it works and how to deploy it.
Don't spend more than an hour or two on it. It's okay if you fail. These tools are complex, and frequently undocumented. When you get stuck, ask Copilot for help.
Document your process in a README file. What worked? What didn't? What did you learn?
Task 3: Be prepared to present
Be ready to present one of your three static sites to the class and talk about your experience exploring another newsroom's template. What challenges did you face? What did you learn?
















