GitHub Pages blog for updates, additional resources and how-to guides related to the Fullstack Academy AI/ML program, cohort 2510-FTB-CT-AIM-PT.
This repository powers a Jekyll-based GitHub Pages site that serves as a central hub for bootcamp materials, including:
- Blog posts: Updates, announcements, and educational content
- Jupyter notebooks: Interactive coding exercises and demonstrations
- Datasets: CSV files and data resources for student activities
- DevOps guides: Setup instructions for Git, Python, and VS Code on Windows and macOS
- External resources: Curated links to documentation, tutorials, and tools
The project implements a data-driven architecture using YAML configuration files and Liquid templating to minimize maintenance overhead and enable rapid content updates.
FSA_devops/
├── .github/workflows/ # CI/CD pipeline definitions
│ ├── deploy-gh-pages.yml # Production deployment workflow
│ └── test-gh-pages.yml # PR preview workflow
├── site/ # Jekyll source files
│ ├── _config.yml # Jekyll configuration
│ ├── _data/ # YAML data files
│ │ ├── notebooks.yml # Notebook metadata
│ │ └── datasets.yml # Dataset metadata
│ ├── _includes/ # Reusable components
│ ├── _layouts/ # Page templates
│ ├── _posts/ # Blog posts (markdown)
│ ├── assets/ # Static assets (CSS, JS, images)
│ ├── devops_pages/ # Setup guides
│ ├── resource_pages/ # Resource documentation
│ ├── notebooks.md # Notebook listing page
│ ├── datasets.md # Dataset listing page
│ └── index.md # Homepage
├── notebooks/ # Jupyter notebook files
│ └── unit*/lesson*/ # Organized by unit and lesson
├── data/ # CSV datasets
├── scripts/ # Bash utilities (git-me, git-me-started)
└── resources.md # Resource links (copied to site/)
Theme: Uses the Minima theme via remote theme configuration for consistent styling and layout.
Data-Driven Content: The site leverages Jekyll's data files feature to separate content from presentation:
_data/notebooks.yml: Contains structured metadata for all Jupyter notebooks (units, lessons, GitHub links, Colab links)_data/datasets.yml: Defines dataset information including descriptions and download links- Liquid templating in
notebooks.mdanddatasets.mddynamically generates tables from YAML data
This approach reduces maintenance burden by significantly. Adding new content requires only YAML edits rather than manual HTML/Markdown updates.
Custom Components: The _includes/header.html file implements navigation filtering to exclude pages with nav_exclude: true in their front matter, enabling draft pages and hidden content.
The main branch has protections in place that prevent direct pushes without a pull request. To merge a pull request into main, a test build and preview deployment must first complete successfully.
When you open a PR from dev to main, two automated processes run:
- Trigger: PR opened/reopened/synchronized or manual dispatch
- Purpose: Validates that site builds successfully with the Makefile-based workflow
- Process:
- Checks out repository code
- Sets up Ruby environment
- Runs
make build-githubto build site with production config - Posts comment on PR with Render preview URL
- Output: Build status check on PR
- Trigger: PR opened from
devbranch (automatic via Render PR preview feature) - Purpose: Creates a live preview of changes before merging to production
- Process:
- Installs Ruby dependencies:
cd site && bundle install - Builds site with Render config:
make build-render(uses merged_config.yml+_config_render.yml) - Deploys to temporary preview URL:
fsa-devops-preview-pr-{NUMBER}.onrender.com
- Installs Ruby dependencies:
- URL Format: Each PR gets a unique preview URL (e.g.,
fsa-devops-preview-pr-42.onrender.com) - Lifecycle: Preview deployment is automatically deleted when PR is closed/merged
- Config Files:
site/_config.yml: Production config withbaseurl: "/FSA_devops"site/_config_render.yml: Override config with empty baseurl for root-level deployment
Why Two Configs?
- GitHub Pages deploys to a subpath:
gperdrizet.github.io/FSA_devops/ - Render deploys to root:
fsa-devops-preview-pr-42.onrender.com/ - Jekyll's
relative_urlfilter usesbaseurlto generate correct URLs for each environment
- Trigger: Pushes to
mainbranch or manual dispatch - Process:
- Checkout: Clones repository with full history
- Asset Staging: Copies notebooks, datasets, and configuration files into the Jekyll source directory (
site/)- Notebooks →
site/assets/notebooks/ - Datasets →
site/assets/data/ - YAML configs →
site/_data/ - Resources page →
site/
- Notebooks →
- Jekyll Build: Compiles site using
actions/jekyll-build-pages@v1with Minima theme - Artifact Upload: Packages the
_sitedirectory for deployment - Deployment: Publishes to GitHub Pages using
actions/deploy-pages@v4
- Catches Jekyll build errors early in the development cycle
- Validates YAML syntax and Liquid template logic
- Ensures asset copying and file structure integrity
- Provides build status checks on PRs via badges
- Enables visual review of changes before production deployment
- Supports collaborative review with live preview links
The repository uses a Makefile-based build system for consistent asset management and Jekyll compilation across environments.
make help # Show all available targets
make install # Install Ruby dependencies (bundle install)
make clean # Remove built site and copied assets
make copy-notebooks # Copy notebooks to site/assets/notebooks
make copy-data # Copy datasets to site/assets/data
make copy-resources # Copy resources.md to site/
make copy-all # Run all copy targets
make build-github # Build for GitHub Pages (with baseurl)
make build-render # Build for Render.com (without baseurl)
make serve-local # Start local Jekyll server
make validate-links # Check for broken internal linksThe build system supports two deployment targets:
GitHub Pages (make build-github):
- Uses
site/_config.ymlonly - Sets
baseurl: "/FSA_devops"for subpath deployment - URLs generated as:
/FSA_devops/path/to/resource
Render.com (make build-render):
- Merges
site/_config.yml+site/_config_render.yml - Overrides baseurl to empty string for root deployment
- URLs generated as:
/path/to/resource
All internal URLs use Jekyll's relative_url filter, which automatically adjusts based on the baseurl setting.
main: Production branch - triggers automatic deployment to GitHub Pagesdev: Development branch - used for feature work and testing- Feature branches: Created as needed for specific enhancements
- Create PR: Open pull request from
devtomainon GitHub - Automated Checks:
- GitHub Actions builds site and reports status
- Render creates preview deployment (link posted in PR comment)
- Review Changes: Visit preview URL to verify changes work correctly
- Merge: Once approved and checks pass, merge to
main - Deploy: Production deployment to GitHub Pages triggers automatically
- Cleanup: Render automatically deletes preview deployment
The repository includes a dev container configuration for consistent development environments.
Jekyll's live reload enables rapid iteration - most changes appear in your browser within seconds:
# Start local Jekyll server (matches GitHub Pages config)
make serve-local
# Site available at http://localhost:4000/FSA_devops
# Automatically rebuilds on file changesNote: Local server uses production config with baseurl, so URLs will include /FSA_devops prefix.
Adding Notebooks:
- Place
.ipynbfile in appropriatenotebooks/unit*/lesson*/directory - Add metadata entry to
notebooks/notebooks.yml - Commit and push - build process automatically copies to site assets
Adding Datasets:
- Place CSV file in
data/directory - Add metadata to
data/datasets.yml - Build process handles asset copying during deployment
Writing Blog Posts:
- Create markdown file in
site/_posts/using naming convention:YYYY-MM-DD-title.md - Include YAML front matter with
layout,title,date, and optionalcategories - Use
{{ '/path/to/resource' | relative_url }}for any internal links - Jekyll automatically includes posts in chronological order on homepage
Updating Resources:
- Edit
resources.mdin repository root - Use
{{ '/path' | relative_url }}filter for all internal links - Build process copies file to
site/directory