Skip to content

Repository files navigation

📝 Google Drive → Static Blog (SSG)

A dependency-light Static Site Generator that turns a folder of Google Docs into a fast, modern, deployable website — no CMS, no database.

Write an article in Google Docs → drop it in a Drive folder → run two commands → get a polished static site (images included).

Demo theme: UroCare UK — a fictional association of urology specialists. Clean, clinical, trustworthy design. Perfect as a tutorial you can clone, rebrand and reuse.


✨ Features

  • 🔌 Pulls Google Docs from a shared Drive folder (post/ + img/).
  • 🧼 "Forced" styling — strips all the noise Word/Google Docs add and keeps only structure (h1–h4, p, lists, links, images), so every article looks consistent and modern via one stylesheet.
  • ✍️ Typography pre-formatter — fixes common typing mistakes (double spaces, spacing around punctuation, smart quotes, em dashes, ellipses).
  • 🖼️ Image support — images from the img/ folder (matched to a post by file name) are downloaded and appended to the article. The first matching image becomes the post thumbnail on the landing and blog pages.
  • 🏠 Landing page + blog + per-article pages, fully responsive.
  • 🎬 Subtle motion — sticky header, scroll-reveal animations (respects prefers-reduced-motion).
  • 🚀 Static output in dist/ — host it anywhere (GitHub Pages, Netlify, etc.).

🏗️ Architecture

Google Drive (shared folder)
   ├── post/   ← Google Docs (one file = one article)
   └── img/    ← images, matched to a post by file name
        │  (1) npm run sync   →  sync-drive.js
        ▼
content/articles/*.json   ← Docs exported to HTML + downloaded images
        │  (2) npm run build  →  build.js
        ▼
dist/  ← landing + blog + article pages (ready to deploy)

Google Drive folder structure

Create a shared folder and add two sub-folders inside it:

<shared folder>          ← GOOGLE_DRIVE_FOLDER_ID points here
├── post/
│   └── test-1           ← Google Doc (the article title = the file name)
└── img/
    ├── test-1.jpg       ← cover / thumbnail (first match)
    ├── test-1-2.jpg     ← appended after the cover, at the end of the post
    └── test-1-3.png     ← more images, in order …

Share the shared folder (not just the sub-folders) with your service account email, with Viewer access.

How images are matched

Images in img/ are linked to a post when their file name matches the post name. A separator is required before any number suffix, so test-10 is not confused with test-1.

Post (in post/) Images (in img/) Result
test-1 test-1.jpg thumbnail on cards and shown at end of post
test-1 test-1.jpg, test-1-2.jpg all appended at the end of the article, in order
test-1 test-10.jpg not matched (different post)

Accepted separators between the post name and the number: space, -, _, (). Examples that all match post test-1: test-1, test-1-2, test-1_3, test-1 (4).

The first matching image is the thumbnail (landing + blog cards). All matching images are appended at the end of the article body — the cover is not duplicated at the top of the page.

Project layout

.
├── sync-drive.js              # Extraction engine (Drive → JSON + images)
├── build.js                   # SSG: JSON + templates → dist/
├── templates/
│   ├── landing.html           # Home page
│   ├── blog.html              # Blog listing
│   ├── article.html           # Single article
│   └── partials/              # Shared head / header / footer
├── assets/
│   ├── styles.css             # Single source of truth for styling
│   ├── app.js                 # Header + scroll-reveal + mobile menu
│   └── img/                   # Logo, hero, placeholder
├── content/articles/          # Synced JSON + images (from npm run sync)
└── dist/                      # Build output (generated, git-ignored)
File Role
sync-drive.js Extraction. Authenticates to Drive (JWT), exports Docs from post/, downloads matching images from img/, writes JSON.
build.js Hydration. Sanitises HTML, fixes typography, injects content into templates and writes dist/.
assets/styles.css One stylesheet that "forces" a consistent look on every page and article.

🚀 Quick start

# 1. Install dependencies
npm install

# 2. Build the site (uses synced content in content/articles/)
npm run build

# 3. Preview locally
npm run serve        # then open the printed URL

Connect your Google Drive

cp .env.example .env   # fill in GOOGLE_DRIVE_FOLDER_ID and GOOGLE_CREDENTIALS_JSON
npm run sync           # pull docs + images from Drive
npm run build          # regenerate the site

# or both in one step:
npm run generate

Day-to-day workflow

  1. Write or edit a Google Doc in the post/ folder.
  2. Add images to img/ using the same base name (e.g. my-post.jpg, my-post-2.jpg).
  3. Run npm run sync && npm run build (or npm run generate).
  4. Deploy dist/ or preview with npm run serve.

🔑 Google Drive setup (step by step)

  1. Go to the Google Cloud Console and create a project.
  2. Enable the Google Drive API.
  3. Create a Service Account and generate a JSON key.
  4. In Google Drive, create a shared folder with post/ and img/ sub-folders.
  5. Share the shared folder with the service account email (Viewer access).
  6. Put the shared folder ID and the JSON (single line) into .env:
GOOGLE_DRIVE_FOLDER_ID=1AbC...xyz
GOOGLE_CREDENTIALS_JSON='{"type":"service_account","client_email":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...","...":"..."}'

.env is git-ignored. Never commit your real credentials.


✍️ How content is processed

  • Headings (Heading 1/2/3 in the Doc) → real <h1>/<h2>/<h3> → styled automatically.
  • Paragraphs<p> with consistent spacing.
  • Bold / italic → converted to <strong> / <em>.
  • Typos → double spaces, spacing around punctuation, straight quotes, -- and ... are automatically corrected.
  • Images from img/ → downloaded to content/articles/images/<slug>/, appended at the end of the article; the first match is the thumbnail.
  • The document's own title block is removed (the site renders the title), and everything else (inline colours, fonts, custom classes) is stripped, so the site stays clean and on-brand no matter how the Doc was formatted.

🎨 Design

  • Style: clinical, minimal, trustworthy, modern.
  • Palette: white #FFFFFF, medical navy #1E3A8A, medical blue #3B82F6, light grey #F3F4F6.
  • Type: Inter (sans-serif).

📄 License

MIT — use it freely for your own tutorial, blog or client project.

About

Static blog using Google Drive API and GitHub Actions to automatically fetch and publish new Google Docs from a specific folder.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages