Intro
Credit to AliMark71 for developing this architecture and reviewing this article.
This document outlines an architecture useful for projects like hackathon proofs-of-concept (PoC), personal or work portfolios, and public data viewer websites.
Before continuing, it helps to be familiar with static engine generators (like Jekyll, Liquid, or Blade) and GitHub Workflows.
History
This architecture began in the informatics-sa/Website repository (Visit website):
01 May 2024: Started with standard HTML/Jekyll using manual_layouts.15 Aug 2024: Created abuild.pyscript to speed up the building process.18 Aug 2024: Added a workflow to automatically runbuild.pyon every commit.07 Sep 2024: Cleaned the repository root and moved served files to aroot/directory.13 Mar 2025: AliMark71 added a library tobuild.pyto reduce repeated code, such as reading JSON and writing frontmatter.14 Mar 2025: Improved internationalization (i18n) by adding atranslations.jsonfile.04 Oct 2025: Moved the_layout/folder into a Git submodule.18 May 2026: AliMark71 integrated a secret database feature.
Overview
This architecture replaces a traditional monolithic backend with a pre-compiled, serverless pipeline. It is built on three pillars:
- Data: Uses JSON (or SQLite/CSV) as the single source of truth instead of a runtime database.
- Builder: A script (often Python, Swift, PHP, Go, or JavaScript) that handles heavy calculations before the page loads.
- Engine: A tool like Jekyll (or Liquid/Blade) to compile Markdown and frontmatter into final HTML. This is optional, but useful for speed and aesthetics.
This guide focuses on a stack using JSON, Python, and Jekyll, all hosted on GitHub Pages.
Structure
The recommended folder structure separates core data, builders, and raw HTML/Markdown files to keep things organized:
.github/workflows/pages-deploy.yml: Handles the deployment automation.builder/: Contains all builder scripts, includinglib/andbuild.py.data/: Stores your raw data files, like*.json.root/: Holds the final output to be served, including_layouts/, compiled*.html, and*.mdfiles.
(Note: Some older examples place data/ and _layouts/ inside root/ and leave build.py in the main directory, but the structure above is cleaner).
Deployment
Updating the site requires no manual server administration. The automated lifecycle works like this:
- Edit data: A maintainer pushes updated JSON or CSV files directly to the GitHub repository.
- Trigger workflow: GitHub Actions detects the push and runs the
.github/workflows/*.ymlfile on an isolated runner. - Run builder script: The runner executes
build.py. This script reads the data files, checks them for errors, synthesizes the content, and writes the final pages and frontmatter into the./rootdirectory. - Host via engine: The workflow runs
bundle exec jekyll serve -s ./root, mapping the pre-calculated data into HTML layouts and pushing the final assets to GitHub Pages.
This setup is optimized for GitHub Pages, but it works just as well with Cloudflare Pages or similar services.
Best Practices
Public Data API
Since your raw data is in JSON format, expose it via endpoints like website.com/data/file.json. This gives users and AI tools direct access to the data without needing to scrape the site.
Data Validation
The builder script should verify your data format before compiling. If the data is invalid, the workflow should fail and log the error for easy debugging.
Balance Workflow and JavaScript
Do not rely on JavaScript to fetch all your data, as it slows down the experience for the end user. Precompute as much as possible during the workflow build. Reserve JavaScript for dynamic features like redirects, public API calls, timers, and animations.
As a rule of thumb: aim for a maximum of 3 seconds for JavaScript loading and 3–5 minutes for workflow building. (A base workflow with an empty build.py takes about 20–30 seconds).
Addons
Secrets Management
Use GitHub Secrets to securely pass keys if your builder script needs to fetch data from hidden external APIs during the build process.
Localization (i18n)
Support multiple languages (like Arabic and English) by centralizing your text in a translations.json file. The builder script can duplicate routing paths, and localized strings are mapped via Jekyll’s _data/ folder.
Encrypted Pages
For sensitive content, the builder can generate an AES-encrypted page (e.g., page.enc.html). Using a simple view.html interface, users can enter a password and decrypt the content directly in their browser—no backend server required.
Submodules
You can use Git Submodules (.gitmodules) to share core builders, layouts, and styles across multiple repositories. Proceed with caution: while this keeps your code DRY (Don’t Repeat Yourself), debugging can be tricky, and bugs often aren’t found until a migration commit is tested.
Website Updater
You can build a simple frontend page that asks for a GitHub API token. If the token is valid, it provides an easy interface to update the site’s content directly from the browser.
Pros & Cons
Pros
- Serverless: Host projects with a budget of exactly $0.
- Fast Editing: Updating a JSON file from your phone can deploy site-wide changes in minutes.
- Accessible Data: Easily manage and expose website data, even if it is sensitive.
- Traffic Analysis: Link seamlessly with Google Analytics to track statistics without needing a database.
- Version Control: Every change is an immutable Git commit, providing a perfect audit trail and instant rollbacks if mistakes happen.
- High Security: No runtime database means no risk of SQL injection. Removing the backend server drastically reduces exposure to XSS and DDoS attacks.
- Professional Polish: You can easily link a custom domain and set up email routing.
Cons
- Read-Only Database: Visitors cannot write data back to the server.
- Manual Setup: This architecture currently lacks extensive documentation, so initial setup requires manual work.
- Build-Time Limits: As your dataset grows over the years, the builder script will take longer to compute. You are bound by the processing limits of GitHub Actions.
- No Real-Time Features: Live chat, WebSockets, or instant leaderboards are impossible without relying on third-party external APIs.
Real-World Examples
You can use this Github template which is a basic website for poem lines in Arabic using (JSON + Python + Jekyll).
- muaath.dev: Features secrets management and encrypted pages. (GitHub Repo)
- sainformatics.org: Features localization, secrets management, and submodules. (GitHub Repo)