ยท hands on
Deploy your TypeScript Website on GitHub Pages
Learn how to automatically deploy your TypeScript website to GitHub Pages using GitHub Actions. This step-by-step guide shows you how to set up a CI/CD pipeline that builds and deploys your site whenever you push to the main branch.
GitHub Pages offers free hosting for static websites, making it an excellent choice for documentation sites, portfolios, and project pages. Combined with GitHub Actions, you can automate your TypeScript website deployment so that every push to your main branch triggers a fresh build and deployment.
In this guide, you'll learn how to set up a GitHub Actions workflow that automatically builds your TypeScript project and deploys it to GitHub Pages.
Contents
- Prerequisites
- Enabling GitHub Pages
- Creating the Deployment Workflow
- Understanding the Workflow
- Customizing the Build Directory
- Testing the Workflow
- Adding a Build Badge
- Best Practices
Prerequisites
Before setting up automated deployment, you need a TypeScript project with a build script configured in package.json, a GitHub repository for your project, and GitHub Pages enabled in your repository settings.
Enabling GitHub Pages
Before creating the workflow, you need to enable GitHub Pages in your repository. Navigate to your repository on GitHub and click on Settings. In the left sidebar, find and click on Pages. Under "Build and deployment", you'll see a Source dropdown menu. Select GitHub Actions from this dropdown. This configuration tells GitHub to use GitHub Actions workflows for deployments instead of deploying from a branch directly.
Creating the Deployment Workflow
Create a new file in your repository at .github/workflows/deploy.yml with the following content:
name: 'Deploy Website'
# Trigger Configuration
on:
push:
branches: ['main']
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Build Job
build:
name: 'Build'
runs-on: ubuntu-latest
steps:
- name: 'Checkout Code'
uses: actions/checkout@v5
- name: 'Setup Node'
uses: actions/setup-node@v6
with:
node-version: '22'
- name: 'Build Website'
run: npm ci && npm run build
- name: 'Upload artifact'
uses: actions/upload-pages-artifact@v4
with:
path: ./doc
# Deploy Job
deploy:
name: 'Deploy'
needs: build
permissions:
pages: write
id-token: write
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: 'Deploy to GitHub Pages'
id: deployment
uses: actions/deploy-pages@v4Understanding the Workflow
Let's break down what each part of this workflow does:
Trigger Configuration
on:
push:
branches: ['main']This configuration triggers the workflow automatically whenever code is pushed to the main branch. You can modify this to use a different branch like production or gh-pages if needed.
Build Job
The build job handles compiling your TypeScript code and preparing it for deployment:
build:
name: 'Build'
runs-on: ubuntu-latest
steps:
- name: 'Checkout Code'
uses: actions/checkout@v5
- name: 'Setup Node'
uses: actions/setup-node@v6
with:
node-version: '22'
- name: 'Build Website'
run: npm ci && npm run build
- name: 'Upload artifact'
uses: actions/upload-pages-artifact@v4
with:
path: ./docThe workflow starts by checking out your repository code to the runner, then sets up Node.js version 22 (adjust this to match your project requirements or reference a node-version-file).
Next, it runs npm ci for a clean install followed by npm run build to compile your TypeScript code. Finally, it packages the build output from the ./doc directory as a deployment artifact.
Make sure to update the path: ./doc to match your project's build output directory. Common alternatives include ./dist, ./build, or ./public.
Deploy Job
The deploy job takes the build artifact and publishes it to GitHub Pages:
deploy:
name: 'Deploy'
needs: build
permissions:
pages: write
id-token: write
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: 'Deploy to GitHub Pages'
id: deployment
uses: actions/deploy-pages@v4The deploy job includes several important configurations. The needs: build directive ensures the deploy job only runs after the build job completes successfully.
The permissions section is crucial for GitHub Pages deployments. It grants the workflow two specific permissions: pages: write allows the workflow to deploy content to GitHub Pages, while id-token: write enables the workflow to request an OpenID Connect (OIDC) token for secure authentication with GitHub's deployment service. Without these permissions, the deployment step would fail with authorization errors.
The environment configuration associates the deployment with the github-pages environment, which enables deployment protection rules and displays the live URL.
Customizing the Build Directory
If your build output goes to a different directory, update the path in the upload step. For example:
- name: 'Upload artifact'
uses: actions/upload-pages-artifact@v4
with:
path: ./distDifferent frameworks use different build output directories. Astro and Vite typically output to ./dist, Next.js uses ./out when configured for static export, and Create React App outputs to ./build. For custom TypeScript projects, check your tsconfig.json or build script to determine the correct output directory.
Testing the Workflow
Once you've committed the workflow file, push your changes to the main branch and navigate to the Actions tab in your GitHub repository. You'll see the "Deploy Website" workflow running. After successful completion, your site will be live at https://<username>.github.io/<repository>/. If the workflow fails, click on the failed run to see detailed logs and identify the issue.
Adding a Build Badge
You can add a status badge to your README.md to show the deployment status:
This badge will display whether your latest deployment succeeded or failed, giving visitors confidence in your site's status.
Best Practices
To maintain a robust deployment pipeline, consider implementing dependency caching to speed up your builds. You can do this by adding a cache: 'npm' configuration to the Setup Node step:
- name: 'Setup Node'
uses: actions/setup-node@v6
with:
node-version: '22'
cache: 'npm'Always pin action versions to specific releases (like @v5) instead of using @latest to ensure reproducible builds. Additionally, you can add a test job that runs before the build job to catch errors early:
test:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Code'
uses: actions/checkout@v5
- name: 'Setup Node'
uses: actions/setup-node@v6
with:
# Reads Node.js version from .nvmrc file
node-version-file: '.nvmrc'
- name: 'Install dependencies'
run: npm ci
- name: 'Test project'
run: npm test
build:
needs: test
# ... rest of build jobFor projects that require API keys or other sensitive values, store them in GitHub Secrets and reference them in your workflow to keep credentials secure.
