Web Publishing with Quartz
Quartz transforms your Obsidian vault into a fast, searchable static website. This guide covers setup, configuration, and deployment.
Why Quartz?
Quartz is a static site generator designed specifically for Obsidian vaults.
Benefits:
- No modifications to your markdown files required
- Respects Obsidian syntax: Wikilinks, embeddings, frontmatter
- Fast and lightweight: Static HTML, no database
- Full-text search: Client-side, no server needed
- Graph view: Visual document relationships
- Free hosting: GitHub Pages, Netlify, Vercel
- Mobile-friendly: Responsive design
- Dark mode: Built-in theme switching
Garage Project: Published at https://yourdomain.github.io/garage
Prerequisites
Before starting:
- Obsidian vault set up and organized
- Git installed (https://git-scm.com)
- Node.js v18.14+ installed (https://nodejs.org)
- GitHub account (for hosting)
- Basic terminal/command line familiarity
Installation
1. Initialize Git Repository
If not already done:
cd /path/to/your/vault
git init
git add .
git commit -m "Initial commit"2. Create GitHub Repository
- Go to https://github.com/new
- Repository name:
garage(or your project name) - Public or Private (your choice)
- Don’t initialize with README (you already have content)
- Create repository
3. Connect Local to GitHub
git remote add origin https://github.com/yourusername/garage.git
git branch -M main
git push -u origin main4. Install Quartz
In your vault directory:
npx quartz@latest create contentWhen prompted:
- “Choose how Quartz should resolve links”: Shortest path (matches Obsidian)
- “Choose how to initialize content”: Empty Quartz (you already have content)
This creates:
quartz/directory with Quartz configurationquartz.config.ts- Main configuration filequartz.layout.ts- Layout configuration
5. Verify Structure
Your vault should now look like:
your-vault/
├── content/ # Your existing content
│ ├── index.md
│ ├── 10-Planning/
│ ├── 20-Design/
│ └── ...
├── quartz/ # Quartz framework
│ ├── components/
│ ├── plugins/
│ └── ...
├── quartz.config.ts # Quartz configuration
├── quartz.layout.ts # Layout configuration
├── package.json
└── .git/
Configuration
Basic Configuration
Edit quartz.config.ts:
import { QuartzConfig } from "./quartz/cfg"
import * as Plugin from "./quartz/plugins"
const config: QuartzConfig = {
configuration: {
pageTitle: "Garage Construction Project", // Site title
enableSPA: true,
enablePopovers: true,
analytics: {
provider: "google", // Optional: Google Analytics
tagId: "G-XXXXXXXXXX",
},
baseUrl: "yourusername.github.io/garage", // Your GitHub Pages URL
ignorePatterns: [
"private",
"Templates",
".obsidian",
"ChatGPT Summaries", // Exclude from web
],
theme: {
typography: {
header: "Schibsted Grotesk",
body: "Source Sans Pro",
code: "IBM Plex Mono",
},
colors: {
lightMode: {
light: "#faf8f8",
lightgray: "#e5e5e5",
gray: "#b8b8b8",
darkgray: "#4e4e4e",
dark: "#2b2b2b",
secondary: "#284b63",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
darkMode: {
light: "#161618",
lightgray: "#393639",
gray: "#646464",
darkgray: "#d4d4d4",
dark: "#ebebec",
secondary: "#7b97aa",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
},
},
},
plugins: {
transformers: [
Plugin.FrontMatter(),
Plugin.TableOfContents(),
Plugin.CreatedModifiedDate({
priority: ["frontmatter", "filesystem"],
}),
Plugin.SyntaxHighlighting(),
Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }),
Plugin.GitHubFlavoredMarkdown(),
Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }),
Plugin.Latex({ renderEngine: "katex" }),
Plugin.Description(),
],
filters: [Plugin.RemoveDrafts()],
emitters: [
Plugin.AliasRedirects(),
Plugin.ComponentResources({ fontOrigin: "googleFonts" }),
Plugin.ContentPage(),
Plugin.FolderPage(),
Plugin.TagPage(),
Plugin.ContentIndex({
enableSiteMap: true,
enableRSS: true,
}),
Plugin.Assets(),
Plugin.Static(),
Plugin.NotFoundPage(),
],
},
}
export default configLayout Configuration
Edit quartz.layout.ts to customize page layout:
import { PageLayout, SharedLayout } from "./quartz/cfg"
import * as Component from "./quartz/components"
// Components shared across all pages
export const sharedPageComponents: SharedLayout = {
head: Component.Head(),
header: [],
footer: Component.Footer({
links: {
GitHub: "https://github.com/yourusername/garage",
},
}),
}
// Components for pages displaying a single page
export const defaultContentPageLayout: PageLayout = {
beforeBody: [
Component.Breadcrumbs(),
Component.ArticleTitle(),
Component.ContentMeta(),
Component.TagList(),
],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
Component.DesktopOnly(Component.Explorer()),
],
right: [
Component.Graph(),
Component.DesktopOnly(Component.TableOfContents()),
Component.Backlinks(),
],
}
// Components for pages that list multiple pages
export const defaultListPageLayout: PageLayout = {
beforeBody: [Component.ArticleTitle()],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
],
right: [],
}.gitignore Configuration
Create/update .gitignore:
# Obsidian
.obsidian/workspace*
.obsidian/cache
.trash/
# Quartz
node_modules/
public/
.quartz-cache/
# OS
.DS_Store
Thumbs.db
# Private
private/
Templates/
Building Your Site
Local Preview
Test your site locally before publishing:
npx quartz build --serveThen open http://localhost:8080 in your browser.
What to check:
- All pages render correctly
- Links work (especially wikilinks)
- Images display
- Search works
- Graph view shows relationships
- Mobile view looks good
Build for Production
When ready to publish:
npx quartz buildThis generates static files in the public/ directory.
Deployment to GitHub Pages
Option 1: GitHub Actions (Recommended)
Automatic deployment on every push:
- Create workflow file:
.github/workflows/deploy.yml
name: Deploy Quartz site to GitHub Pages
on:
push:
branches:
- main # or your default branch
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for git info
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Build Quartz
run: npx quartz build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: public
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4-
Enable GitHub Pages:
- Go to repository Settings → Pages
- Source: GitHub Actions
-
Push to GitHub:
git add .
git commit -m "Add Quartz configuration and GitHub Actions workflow"
git push- Monitor deployment:
- Go to Actions tab in GitHub
- Watch deployment progress
- Site will be live at
https://yourusername.github.io/garage
Option 2: Manual Deployment
If you prefer manual control:
# Build the site
npx quartz build
# Deploy to gh-pages branch
npx quartz deployCustomization
Homepage Customization
Create a clean content/index.md for web visitors:
---
title: Garage Project Index
type: index
---
# Garage Construction Project
Documentation for a 24'x40'x10' three-car garage with second-floor workshop.
## Current Build Status
**Latest milestone (Oct 22, 2025):**
- ✓ Under-slab insulation complete (2" Creatherm R-10)
- ✓ PEX radiant heating loops installed
- ⧗ Pressure testing in progress
- Pending: Concrete pour
**🎥 [[50-Build/Construction Videos]]** — Watch time-lapse videos!
## Quick Links
- [[10-Planning/Timeline]] - Project timeline
- [[50-Build/Initial Build]] - Build progress
- [[30-Vendors & Contacts/Products Used]] - Product specifications
- [[10-Planning/Decisions Log]] - Major decisions
## Project Overview
- **Size**: 24' x 40' x 10' (960 sq ft main floor)
- **Features**: 2-post lift bay, radiant floor heat, second-floor workshop
- **Timeline**: Started October 2025
- **Budget**: $68,400 contract + additional
---
*For full project details, browse the sections in the sidebar.*Custom CSS
Create quartz/styles/custom.scss:
// Custom styles for your site
// Wider content area
.center {
max-width: 900px; // Default is 750px
}
// Highlight boxes for important info
.callout {
background: var(--lightgray);
border-left: 4px solid var(--secondary);
padding: 1rem;
margin: 1rem 0;
}
// Photo galleries
.photo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
margin: 2rem 0;
img {
width: 100%;
height: 250px;
object-fit: cover;
border-radius: 8px;
}
}Import in quartz/styles/base.scss:
@import "custom";Excluding Content from Web
Use ignorePatterns in quartz.config.ts:
ignorePatterns: [
"private", // Entire folder
"Templates", // Template files
".obsidian", // Obsidian config
"**/*-private.md", // Files matching pattern
"ChatGPT Summaries", // AI drafts
],Or use frontmatter in individual files:
---
title: Private Planning Notes
draft: true # Excluded from build
---Updating Your Site
Regular Updates
Your workflow:
- Make changes in Obsidian (update documents, add photos, etc.)
- Commit changes:
git add .
git commit -m "docs: add concrete pour progress photos"
git push- GitHub Actions automatically rebuilds and deploys
- Site updates in 2-3 minutes
Monitoring
- Check Actions tab for build status
- Review build logs if errors occur
- Test locally first for major changes
Advanced Features
Custom Domain
Use your own domain instead of username.github.io:
- Purchase domain (e.g., from Namecheap, Google Domains)
- Configure DNS:
- Add CNAME record pointing to
yourusername.github.io
- Add CNAME record pointing to
- Update GitHub:
- Settings → Pages → Custom domain
- Enter your domain
- Update
quartz.config.ts:
baseUrl: "garageproject.com",Password Protection
GitHub Pages doesn’t support password protection natively.
Options:
- Private repository: Only collaborators can see
- Deploy to Netlify/Vercel: Offers password protection
- Use CloudFlare Access: Add authentication layer
Analytics
Track visitors with Google Analytics:
analytics: {
provider: "google",
tagId: "G-XXXXXXXXXX",
},Or Plausible (privacy-focused):
analytics: {
provider: "plausible",
},Search Customization
Quartz includes client-side search. Customize in layout:
Component.Search({
enablePreview: true, // Show content preview
}),Troubleshooting
Build Fails
Check:
- Node.js version (must be v18.14+)
- No special characters in filenames
- All images referenced exist
- Frontmatter YAML is valid
Common fix:
rm -rf node_modules .quartz-cache
npm install
npx quartz buildLinks Not Working
Problem: Wikilinks not resolving
Solution: Verify quartz.config.ts:
markdownLinkResolution: "shortest"Problem: Links to sections broken
Solution: Use proper heading anchors:
[[Document Name#section-heading|Section Heading]]Images Not Displaying
Check:
- Images in
content/directory (not.obsidian/) - Correct relative paths
- No spaces in image filenames (or use
%20)
Fix:
Slow Build Times
For large vaults:
// Exclude large folders from graph
ignorePatterns: [
"private",
"archive",
"ChatGPT Summaries",
],Best Practices
Content Strategy
Separate Obsidian and Web content if needed:
00-Index.md: Full Obsidian dashboard with Dataviewcontent/index.md: Clean web homepage
Use frontmatter for web-specific settings:
---
title: Clean Web Title
description: SEO-friendly description
tags: [public, important]
---Link strategy:
- Internal links: Use wikilinks
[[Document]] - External links: Standard markdown
[Text](URL)
Performance
- Optimize images: Resize large photos
- Limit embedding: Don’t embed entire documents unnecessarily
- Use excerpts: Long documents load slowly
SEO
---
title: Garage Construction - 24x40 Workshop Build
description: Complete documentation of custom garage construction with photos and specifications
tags: [garage, construction, diy, workshop]
---Example: Garage Project Setup
The actual Garage Project setup:
// quartz.config.ts
const config: QuartzConfig = {
configuration: {
pageTitle: "Garage Project",
baseUrl: "yourusername.github.io/garage",
ignorePatterns: [
"Templates",
".obsidian",
"ChatGPT Summaries",
],
},
}Result: Clean, fast documentation site with:
- All construction progress
- Photo documentation
- Time-lapse videos
- Product specifications
- Decision history
- Searchable content
Next Steps
With your site published:
05 - AI Integration and Automation - Use AI to accelerate documentation
06 - Advanced Features and Best Practices - Master advanced techniques
Resources
- Quartz Documentation: https://quartz.jzhao.xyz
- GitHub Pages Docs: https://docs.github.com/pages
- Obsidian Publish Alternative: Quartz is free, Obsidian Publish is $10/month
The Garage Project site is built and deployed using these exact steps.