Mastering Monorepo Deployment: Angular & Astro on GitHub Pages for Enhanced Software Project Metrics
In today's fast-paced development environment, monorepos have become a cornerstone for managing complex projects, offering benefits like shared codebases and simplified dependency management. However, deploying multiple static sites from a single monorepo to platforms like GitHub Pages often presents unique challenges. When not handled correctly, these deployment hurdles can directly impact software project metrics, leading to delays, increased debugging time, and a dip in team productivity.
This article delves into a common scenario: deploying an Angular application to the root path (/) and an Astro Starlight documentation site to a subpath (/wiki) from a single GitHub repository. We'll explore the pitfalls that lead to frustrating 404 errors and provide a robust, step-by-step solution that ensures seamless deployment and contributes positively to your team's delivery efficiency.
The Monorepo Deployment Challenge: Angular & Astro on GitHub Pages
Consider a developer, binder-badge, who aimed to deploy two distinct static sites from a .github.io monorepo using GitHub Pages. The setup involved:
- An Angular site intended for the root domain (e.g.,
domain.com/). - An Astro Starlight site, used for personal documentation, intended for a subpath (e.g.,
domain.com/wiki).
Despite a seemingly logical GitHub Actions workflow that built both projects and attempted to consolidate their outputs into a dist folder for artifact upload, both target URLs were returning 404 errors. This situation highlights a critical gap in understanding how GitHub Pages interprets deployment artifacts and how different frameworks structure their build outputs.
Why the 404s? Unpacking the Root Causes
The core of the problem stemmed from a combination of GitHub Pages' serving mechanism and the default build behaviors of Angular and Astro:
- GitHub Pages' Serving Mechanism: GitHub Pages is designed to serve content directly from the root of the uploaded artifact. If your main
index.htmlisn't immediately at the artifact's root, it won't be found. - Angular's Output Structure: By default, an Angular build (especially for browser-based applications) places its main static assets, including
index.html, within abrowser/subdirectory inside itsdistfolder (e.g.,dist/portfolio/browser/). This means the critical files aren't directly at the root of the desired deployment path. - Astro's Base Path Configuration: Astro, by default, generates asset URLs relative to the root (
/). Even if you meticulously place Astro's compiled files under a/wikidirectory within your deployment artifact, its internal links and asset references (e.g., to CSS, JS, images) might still point to/styles.cssinstead of/wiki/styles.css. This leads to broken links and further 404 errors for resources, even if the mainindex.htmlfor the wiki is found.
Understanding these nuances is crucial for any team looking to optimize their tooling and improve delivery metrics.
The Working Solution: A Step-by-Step Guide for Seamless Monorepo Deployment
The path to a working solution involved precise configuration adjustments and a careful consolidation of build outputs. Here’s how to achieve a robust deployment for your Angular and Astro monorepo:
1. Configure Astro's Base Path
The most critical step for the Astro site is to explicitly tell it where it will be hosted. Edit your wiki/astro.config.mjs file:
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://your-custom-domain.com',
base: '/wiki/',
});
Setting site ensures correct absolute URLs for sitemaps and canonical links, while base: '/wiki/' instructs Astro to generate all internal asset paths and links relative to the /wiki/ subdirectory. This is fundamental for Astro to function correctly under a subpath.
2. Build Both Projects
Your build commands remain largely standard. Ensure Angular is built with the correct base href and Astro is built after its configuration update:
# Angular build
npm run build -- --configuration production --base-href "/"
# Astro build
npm run build
3. The Crucial Final Artifact Structure
The key to success lies in creating a dist/ folder that GitHub Pages can correctly interpret. The final structure of your uploaded artifact must look exactly like this:
dist/
├── index.html <-- Angular's main index.html
├── main-XXXX.js <-- Angular's JS
├── styles-XXXX.css <-- Angular's CSS
├── favicon.ico <-- Angular's favicon
├── 404.html <-- Global 404 page
├── CNAME <-- Custom domain configuration
└── wiki/
├── index.html <-- Astro's main index.html
├── _astro/ <-- Astro's internal assets
├── assets/ <-- Astro's static assets
├── guides/ <-- Astro's content (example)
└── sitemap-index.xml <-- Astro's sitemap
Notice that Angular's output is directly at the root of dist/, while Astro's output resides entirely within dist/wiki/. This structure directly addresses GitHub Pages' serving mechanism.
4. Precision in Copy Commands
To achieve the desired artifact structure, your GitHub Actions workflow needs precise copy commands. This is where many initial attempts go wrong. Replace your existing consolidation step with these commands:
# Create the target directory for Astro
mkdir -p dist/wiki
# Copy Angular's browser contents directly to the root of 'dist/'
cp -r ./portfolio/dist/portfolio/browser/* ./dist/
# Copy all of Astro's build output into 'dist/wiki/'
cp -r ./wiki/dist/* ./dist/wiki/
# (Optional) Copy CNAME and a global 404.html to the root of 'dist/'
# cp ./CNAME ./dist/
# cp ./404.html ./dist/
Key points here:
./portfolio/dist/portfolio/browser/*: We specifically target thebrowsersubdirectory of Angular's output to get the actual static files../dist/: Angular's files are copied directly to the root of the final deployment artifact../wiki/dist/*: All of Astro's output is copied../dist/wiki/: Astro's files are placed within thewikisubdirectory, respecting its configured base path.
5. Refined GitHub Actions Workflow
With the build and copy steps correctly defined, the final GitHub Actions workflow for uploading and deploying remains straightforward:
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Setup NodeJS
uses: actions/setup-node@v4
with:
node-version: "22"
# ... (Install dependencies for portfolio and wiki)
# Build portfolio (Angular)
- name: Build portfolio
working-directory: portfolio
run: npm run build -- --configuration production --base-href "/"
# Build wiki (Astro)
- name: Build wiki
working-directory: wiki
run: npm run build
# Consolidate compiled files into the correct structure
- name: Consolidate dists for GitHub Pages
run: |
mkdir -p dist/wiki
cp -r ./portfolio/dist/portfolio/browser/* ./dist/
cp -r ./wiki/dist/* ./dist/wiki/
# Optional: Copy global CNAME and 404.html to root of dist
# cp ./CNAME ./dist/
# cp ./404.html ./dist/
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: ./dist
deploy:
needs: build
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@v4
After these adjustments, https://your-custom-domain.com/ will correctly serve your Angular application, and https://your-custom-domain.com/wiki will display your Astro Starlight documentation, with all assets resolving as expected.
Key Takeaways for Technical Leaders
This scenario offers several valuable lessons for dev teams, product managers, and CTOs focused on improving software project metrics and delivery pipelines:
- Understand Your Deployment Target: Never assume how a platform like GitHub Pages will serve files. Always verify its expectations regarding artifact structure.
- Framework-Specific Nuances: Be aware of how different frameworks (Angular's
browser/output, Astro'sbasepath) handle their build outputs and adjust configurations accordingly. This understanding is crucial for efficient tooling. - Precision in CI/CD: The copy commands are not trivial. Small errors in pathing can lead to significant debugging time. Investing in robust CI/CD practices and thorough testing of deployment artifacts can drastically improve delivery speed.
- Impact on Productivity: Streamlining deployment workflows directly influences how to measure performance of software developers. Fewer deployment failures mean more time spent on feature development and less on infrastructure firefighting.
- Leverage GitHub Analytics: Post-deployment, utilize github analytics to monitor page access, error rates, and overall site performance. This data can provide insights into user experience and validate the success of your deployment strategy.
By meticulously addressing these details, teams can transform complex monorepo deployments from a source of frustration into a streamlined, reliable process, ultimately enhancing overall project health and accelerating time to market.
