A documentation website built with Python + Flask and zero JavaScript. PDFs are fetched live from a separate GitHub repository via the GitHub API and served through the jsDelivr CDN for reliable inline viewing.
- On every page load the Flask backend calls the GitHub Contents API to list all
.pdffiles in your configured repository/directory. - Each PDF card links to a viewer page that embeds the file through jsDelivr CDN (
cdn.jsdelivr.net/gh/...), which correctly setsContent-Type: application/pdfso browsers display it inline. - Optional
metadata.jsonin the PDF repository allows you to customise titles, descriptions, tags, and categories without touching this codebase. - Server-side search filters results before the HTML is rendered — no JavaScript required.
docs_website/
├── api/
│ └── index.py # Flask app — Vercel serverless entry point
├── templates/
│ ├── index.html # Main page (grid of PDF cards)
│ └── viewer.html # Full-screen PDF viewer
├── static/
│ └── style.css # All styles — dark theme, responsive
├── vercel.json # Vercel deployment configuration
├── requirements.txt # Python dependencies (Flask + Requests)
└── README.md
All settings are passed via environment variables (locally in .env, on Vercel via Project Settings → Environment Variables).
| Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_PDF_OWNER |
Yes | — | GitHub username or organisation that owns the PDF repo |
GITHUB_PDF_REPO |
Yes | — | Repository name that contains the PDFs |
GITHUB_PDF_PATH |
No | "" |
Sub-directory path inside the repo (e.g. docs/pdfs) |
GITHUB_PDF_BRANCH |
No | main |
Branch to read from |
GITHUB_TOKEN |
No | — | Personal access token — raises API rate limit 60→5000/hr |
The defaults are already set to the open-crs/pdf_docs repository. You only need to set these if you want to override them:
GITHUB_PDF_OWNER=open-crs
GITHUB_PDF_REPO=pdf_docs
GITHUB_PDF_PATH=
GITHUB_PDF_BRANCH=main
Place a metadata.json file in the same directory as your PDFs to override the auto-generated titles, descriptions, tags, and categories:
{
"devcontainer_guide.pdf": {
"title": "Dev Container Guide",
"description": "Complete walkthrough for setting up Docker-based dev containers.",
"tags": ["docker", "devcontainer", "tooling"],
"category": "Infrastructure"
},
"api_reference.pdf": {
"title": "API Reference v2",
"description": "Full REST API specification.",
"tags": ["api", "rest", "reference"],
"category": "API"
}
}Keys are the raw filenames (including .pdf). Any PDF without an entry uses auto-generated values.
Prerequisites: Python 3.10+
# 1. Clone this repo
git clone https://github.com/YOUR_USERNAME/docs_website.git
cd docs_website
# 2. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install dependencies
pip install -r requirements.txt
# 4. Set environment variables
export GITHUB_PDF_OWNER=MyOrg
export GITHUB_PDF_REPO=my-docs
export GITHUB_PDF_PATH=pdfs
export GITHUB_TOKEN=ghp_... # optional but recommended
# 5. Run the dev server
python api/index.pyOpen http://localhost:5000 in your browser.
Prerequisites: Vercel CLI or a Vercel account connected to GitHub.
# Install Vercel CLI globally (once)
npm install -g vercel
# Authenticate
vercel login
# Deploy from the project root
cd docs_website
vercelFollow the interactive prompts:
- Set up and deploy? → Y
- Which scope? → select your account/team
- Link to existing project? → N (first time)
- Project name →
docs-website(or any name) - In which directory is your code located? →
./(current dir) - Override settings? → N (vercel.json handles everything)
After the build finishes Vercel prints a preview URL. To promote to production:
vercel --prod- Push this repository to GitHub.
- Go to vercel.com → Add New Project.
- Import your GitHub repository.
- Vercel auto-detects
vercel.json— no framework preset needed. - Click Deploy.
After creating the project:
- Go to Vercel Dashboard → your project → Settings → Environment Variables.
- Add each variable from the table above.
- Set the target to Production (and optionally Preview/Development).
- Click Save and then Redeploy to apply.
Or via CLI:
vercel env add GITHUB_PDF_OWNER production
vercel env add GITHUB_PDF_REPO production
vercel env add GITHUB_PDF_PATH production
vercel env add GITHUB_TOKEN production # paste your token when prompted# Check recent deployment logs
vercel logs https://YOUR-DEPLOYMENT-URL.vercel.app
# Or list recent deployments and inspect
vercel ls
# Redeploy the last working version
vercel rollbackIf rollback is not enough, redeploy from source:
vercel --prod --force# Re-link the CLI to a new or existing project
vercel link
# Then deploy
vercel --prodIf the project was deleted from the dashboard, just run vercel again from the project folder — it will create a new Vercel project automatically.
Re-add them via the dashboard (Settings → Environment Variables) or via CLI:
vercel env add GITHUB_PDF_OWNER production
vercel env add GITHUB_PDF_REPO production
vercel env add GITHUB_PDF_PATH production
vercel env add GITHUB_TOKEN productionThen redeploy:
vercel --prodThe site shows a clear error message when rate-limited. Fix:
- Create a GitHub Personal Access Token (PAT) at
GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
Scopes needed:
public_repo(or none for public repos — a token alone raises the limit). - Add it to Vercel:
vercel env add GITHUB_TOKEN production
- Redeploy:
vercel --prod
jsDelivr serves PDFs with the correct Content-Type: application/pdf header, so inline display works in all modern browsers. If you are linking to raw GitHub URLs instead, they may force a download. Ensure the cdn_url in the viewer uses the jsDelivr format:
https://cdn.jsdelivr.net/gh/{owner}/{repo}@{branch}/{path/to/file.pdf}
jsDelivr caches files for up to 7 days. If you updated a PDF but still see the old version, purge the cache at:
https://purge.jsdelivr.net/gh/{owner}/{repo}@{branch}/{path/to/file.pdf}
| Resource | Free Limit |
|---|---|
| Serverless functions | 100 GB-hrs/month |
| Bandwidth | 100 GB/month |
| Build time | 6000 min/month |
| Function timeout | 10 seconds |
| Response size | 4.5 MB |
For a documentation site with moderate traffic these limits are more than sufficient.
The function timeout (10 s) is the most likely constraint — if your PDF directory has hundreds of files and the GitHub API is slow, requests may time out. Mitigation: set a GITHUB_TOKEN (faster API) and keep the PDF directory to a reasonable size (< 200 files).
| Symptom | Likely Cause | Fix |
|---|---|---|
| Blank page / 500 error | Missing env vars | Check Vercel env vars, redeploy |
| "Repository not found" error | Wrong owner/repo/path | Verify env var values |
| "Rate limit exceeded" error | No GITHUB_TOKEN set | Add token, redeploy |
| PDFs not loading | jsDelivr cache delay | Wait a few minutes; purge if needed |
| Viewer shows download prompt | Wrong Content-Type | Ensure CDN URL uses jsDelivr format |
| Old PDF still showing | jsDelivr cache | Purge the specific CDN URL |
| Function timeout on Vercel | Too many files / slow API | Add GITHUB_TOKEN; reduce files per path |