diff --git a/.gitignore b/.gitignore
index 3f0e1da..2b0c3e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,9 @@ dist-ssr
.env.local
.env.*.local
+# Fork configuration (user-specific)
+fork-config.json
+
# Cursor rules
.cursor/rules/write.mdc
diff --git a/FORK_CONFIG.md b/FORK_CONFIG.md
new file mode 100644
index 0000000..3cbd8c4
--- /dev/null
+++ b/FORK_CONFIG.md
@@ -0,0 +1,443 @@
+# Fork Configuration Guide
+
+After forking this repo, update these files with your site information. Choose one of two options:
+
+---
+
+## Option 1: Automated Script (Recommended)
+
+Run a single command to configure all files automatically.
+
+### Step 1: Create your config file
+
+```bash
+cp fork-config.json.example fork-config.json
+```
+
+The file `fork-config.json` is gitignored, so your configuration stays local and is not committed. The `.example` file remains as a template.
+
+### Step 2: Edit fork-config.json
+
+```json
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "A one-sentence description of your site.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Your bio text here.",
+ "theme": "tan"
+}
+```
+
+### Step 3: Run the configuration script
+
+```bash
+npm run configure
+```
+
+This updates all 11 configuration files automatically:
+
+- `src/config/siteConfig.ts`
+- `src/pages/Home.tsx`
+- `src/pages/Post.tsx`
+- `convex/http.ts`
+- `convex/rss.ts`
+- `index.html`
+- `public/llms.txt`
+- `public/robots.txt`
+- `public/openapi.yaml`
+- `public/.well-known/ai-plugin.json`
+- `src/context/ThemeContext.tsx`
+
+### Step 4: Review and deploy
+
+```bash
+git diff # Review changes
+npx convex dev # Start Convex (if not running)
+npm run sync # Sync content
+npm run dev # Test locally
+```
+
+---
+
+## Option 2: Manual Configuration
+
+Edit each file individually following the guide below.
+
+### Files to Update
+
+| File | What to Update |
+| ----------------------------------- | -------------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub username, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME` constants |
+| `convex/http.ts` | `SITE_URL`, `SITE_NAME` constants |
+| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+---
+
+## Manual Configuration Details
+
+### 1. src/config/siteConfig.ts
+
+Update the main site configuration:
+
+```typescript
+export const siteConfig: SiteConfig = {
+ name: "YOUR SITE NAME",
+ title: "YOUR TAGLINE",
+ logo: "/images/logo.svg", // or null to hide
+ intro: null,
+ bio: `YOUR BIO TEXT HERE.`,
+
+ // Featured section
+ featuredViewMode: "cards", // 'list' or 'cards'
+ showViewToggle: true,
+
+ // Logo gallery (set enabled: false to hide)
+ logoGallery: {
+ enabled: true,
+ images: [
+ { src: "/images/logos/your-logo.svg", href: "https://example.com" },
+ ],
+ position: "above-footer",
+ speed: 30,
+ title: "Built with",
+ scrolling: false,
+ maxItems: 4,
+ },
+
+ // GitHub contributions graph
+ gitHubContributions: {
+ enabled: true,
+ username: "YOURUSERNAME",
+ showYearNavigation: true,
+ linkToProfile: true,
+ title: "GitHub Activity",
+ },
+
+ // Blog page
+ blogPage: {
+ enabled: true,
+ showInNav: true,
+ title: "Blog",
+ description: "All posts from the blog, sorted by date.",
+ order: 2,
+ },
+
+ // Posts display
+ postsDisplay: {
+ showOnHome: true,
+ showOnBlogPage: true,
+ },
+
+ links: {
+ docs: "/setup-guide",
+ convex: "https://convex.dev",
+ netlify: "https://netlify.com",
+ },
+};
+```
+
+### 2. src/pages/Home.tsx
+
+Update the intro paragraph (lines 96-108):
+
+```tsx
+
+ YOUR SITE DESCRIPTION HERE.{" "}
+
+ Fork it
+
+ , customize it, ship it.
+
+```
+
+Update the footer section (lines 203-271):
+
+```tsx
+
+```
+
+### 3. src/pages/Post.tsx
+
+Update the site constants (lines 11-13):
+
+```typescript
+const SITE_URL = "https://YOURSITE.netlify.app";
+const SITE_NAME = "YOUR SITE NAME";
+const DEFAULT_OG_IMAGE = "/images/og-default.svg";
+```
+
+### 4. convex/http.ts
+
+Update the site configuration (lines 9-10):
+
+```typescript
+const SITE_URL = process.env.SITE_URL || "https://YOURSITE.netlify.app";
+const SITE_NAME = "YOUR SITE NAME";
+```
+
+Also update the `generateMetaHtml` function (lines 233-234):
+
+```typescript
+const siteUrl = process.env.SITE_URL || "https://YOURSITE.netlify.app";
+const siteName = "YOUR SITE NAME";
+```
+
+### 5. convex/rss.ts
+
+Update the RSS configuration (lines 5-8):
+
+```typescript
+const SITE_URL = process.env.SITE_URL || "https://YOURSITE.netlify.app";
+const SITE_TITLE = "YOUR SITE NAME";
+const SITE_DESCRIPTION = "YOUR SITE DESCRIPTION HERE.";
+```
+
+### 6. index.html
+
+Update all meta tags and JSON-LD structured data:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+YOUR SITE TITLE
+```
+
+### 7. public/llms.txt
+
+Update site information:
+
+```
+# Site Information
+- Name: YOUR SITE NAME
+- URL: https://YOURSITE.netlify.app
+- Description: YOUR SITE DESCRIPTION
+
+# Links
+- GitHub: https://github.com/YOURUSERNAME/YOUR-REPO
+```
+
+### 8. public/robots.txt
+
+Update the header and sitemap URL:
+
+```
+# robots.txt for YOUR SITE NAME
+
+Sitemap: https://YOURSITE.netlify.app/sitemap.xml
+```
+
+### 9. public/openapi.yaml
+
+Update API title and server URL:
+
+```yaml
+info:
+ title: YOUR SITE NAME API
+ contact:
+ url: https://github.com/YOURUSERNAME/YOUR-REPO
+
+servers:
+ - url: https://YOURSITE.netlify.app
+```
+
+### 10. public/.well-known/ai-plugin.json
+
+Update plugin metadata:
+
+```json
+{
+ "name_for_human": "YOUR SITE NAME",
+ "name_for_model": "your_site_name",
+ "description_for_human": "YOUR SITE DESCRIPTION",
+ "contact_email": "you@example.com"
+}
+```
+
+### 11. src/context/ThemeContext.tsx
+
+Change the default theme (line 21):
+
+```typescript
+const DEFAULT_THEME: Theme = "tan"; // Options: dark, light, tan, cloud
+```
+
+---
+
+## AI Agent Prompt
+
+Copy this prompt to have an AI agent apply all changes:
+
+```
+I just forked the markdown-site repo. Please update all configuration files with my site information:
+
+Site Name: [YOUR SITE NAME]
+Site Title/Tagline: [YOUR TAGLINE]
+Site Description: [YOUR DESCRIPTION]
+Site URL: https://[YOURSITE].netlify.app
+GitHub Username: [YOURUSERNAME]
+GitHub Repo: [YOUR-REPO]
+Contact Email: [your@email.com]
+
+Creator Info:
+- Name: [YOUR NAME]
+- Twitter: https://x.com/[YOURHANDLE]
+- LinkedIn: https://www.linkedin.com/in/[YOURPROFILE]/
+- GitHub: https://github.com/[YOURUSERNAME]
+
+Update these files:
+1. src/config/siteConfig.ts - site name, bio, GitHub username
+2. src/pages/Home.tsx - intro paragraph and footer section with all creator links
+3. src/pages/Post.tsx - SITE_URL and SITE_NAME constants
+4. convex/http.ts - SITE_URL and SITE_NAME constants
+5. convex/rss.ts - SITE_URL, SITE_TITLE, SITE_DESCRIPTION
+6. index.html - all meta tags, JSON-LD, title
+7. public/llms.txt - site info and GitHub link
+8. public/robots.txt - header comment and sitemap URL
+9. public/openapi.yaml - API title, server URL, contact URL
+10. public/.well-known/ai-plugin.json - plugin metadata and contact email
+```
+
+---
+
+## After Configuration
+
+1. Run `npx convex dev` to initialize Convex
+2. Run `npm run sync` to sync content to development
+3. Run `npm run dev` to test locally
+4. Deploy to Netlify when ready
+
+---
+
+## Optional: Content Files
+
+Replace example content in:
+
+| File | Purpose |
+| ------------------------------ | -------------------------- |
+| `content/blog/*.md` | Blog posts |
+| `content/pages/*.md` | Static pages (About, etc.) |
+| `public/images/logo.svg` | Site logo |
+| `public/images/og-default.svg` | Default social share image |
+| `public/images/logos/*.svg` | Logo gallery images |
diff --git a/README.md b/README.md
index d97bbdc..7cae884 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,49 @@ npm run sync # dev
npm run sync:prod # production
```
+## Fork Configuration
+
+After forking this project, you have two options to configure your site:
+
+### Option 1: Automated (Recommended)
+
+Run a single command to configure all files automatically:
+
+```bash
+# Copy the example config
+cp fork-config.json.example fork-config.json
+
+# Edit with your site information
+# Open fork-config.json and update the values
+
+# Apply all changes
+npm run configure
+```
+
+This updates all 11 configuration files in one step.
+
+### Option 2: Manual
+
+Follow the step-by-step guide in `FORK_CONFIG.md` to update each file manually. This guide includes code snippets and an AI agent prompt for assistance.
+
+### Files Updated
+
+| File | What to update |
+| ----------------------------------- | --------------------------------------------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
+| `src/pages/Home.tsx` | Intro paragraph text, footer links |
+| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings |
+| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` |
+| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` |
+| `index.html` | Title, meta description, OG tags, JSON-LD |
+| `public/llms.txt` | Site name, URL, description, topics |
+| `public/robots.txt` | Sitemap URL and header comment |
+| `public/openapi.yaml` | API title, server URL, site name |
+| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+See `FORK_CONFIG.md` for detailed configuration examples and the full JSON schema.
+
## Features
- Markdown-based blog posts with frontmatter
@@ -58,25 +101,6 @@ npm run sync:prod # production
- Run `npm run import ` to scrape and create draft posts locally
- Then sync to dev or prod with `npm run sync` or `npm run sync:prod`
-## Files to Update When Forking
-
-When you fork this project, update these files with your site information:
-
-| File | What to update |
-| ----------------------------------- | ----------------------------------------------------------- |
-| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
-| `src/pages/Home.tsx` | Intro paragraph text (hardcoded JSX) |
-| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
-| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
-| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
-| `index.html` | Title, meta description, OG tags, JSON-LD |
-| `public/llms.txt` | Site name, URL, description, topics |
-| `public/robots.txt` | Sitemap URL and header comment |
-| `public/openapi.yaml` | API title, server URL, site name in examples |
-| `public/.well-known/ai-plugin.json` | Site name, descriptions |
-
-See the [Setup Guide](/setup-guide) for detailed configuration examples.
-
## Getting Started
### Prerequisites
diff --git a/TASK.md b/TASK.md
index b8383cf..95358ea 100644
--- a/TASK.md
+++ b/TASK.md
@@ -3,14 +3,19 @@
## To Do
- [ ] create a ui site config page
-- [ ] create a prompt formator or checklidst or skill or agent to change everything at once after forking
## Current Status
-v1.17.0 deployed. Added GitHub contributions graph on homepage with theme-aware colors, year navigation, and configurable display options.
+v1.18.0 deployed. Added automated fork configuration with `npm run configure` command and comprehensive fork setup guide.
## Completed
+- [x] Automated fork configuration with npm run configure
+- [x] FORK_CONFIG.md comprehensive guide with two options (automated + manual)
+- [x] fork-config.json.example template with all configuration options
+- [x] scripts/configure-fork.ts for automated updates
+- [x] Updates all 11 configuration files in one command
+
- [x] GitHub contributions graph on homepage with theme-aware colors
- [x] Year navigation with Phosphor icons (CaretLeft, CaretRight)
- [x] Click graph to visit GitHub profile
diff --git a/changelog.md b/changelog.md
index 978b000..d6d82ff 100644
--- a/changelog.md
+++ b/changelog.md
@@ -4,6 +4,37 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.18.0] - 2025-12-20
+
+### Added
+
+- Automated fork configuration with `npm run configure`
+ - Copy `fork-config.json.example` to `fork-config.json`
+ - Edit JSON with your site information
+ - Run `npm run configure` to apply all changes automatically
+ - Updates all 11 configuration files in one command
+- Two options for fork setup
+ - **Option 1: Automated** (recommended): JSON config + single command
+ - **Option 2: Manual**: Follow step-by-step guide in `FORK_CONFIG.md`
+- `FORK_CONFIG.md` comprehensive fork guide
+ - YAML template for AI agent configuration
+ - Manual code snippets for each file
+ - AI agent prompt for automated updates
+- `fork-config.json.example` template with all configuration options
+ - Site name, URL, description
+ - Creator social links (Twitter, LinkedIn, GitHub)
+ - Bio and intro text
+ - Logo gallery settings
+ - GitHub contributions config
+ - Blog page and theme options
+
+### Technical
+
+- New script: `scripts/configure-fork.ts`
+- New npm command: `npm run configure`
+- Reads JSON config and updates 11 files with string replacements
+- Updates: siteConfig.ts, Home.tsx, Post.tsx, http.ts, rss.ts, index.html, llms.txt, robots.txt, openapi.yaml, ai-plugin.json, ThemeContext.tsx
+
## [1.17.0] - 2025-12-20
### Added
diff --git a/content/blog/fork-configuration-guide.md b/content/blog/fork-configuration-guide.md
new file mode 100644
index 0000000..b741c92
--- /dev/null
+++ b/content/blog/fork-configuration-guide.md
@@ -0,0 +1,172 @@
+---
+title: "Configure your fork in one command"
+description: "Two options to set up your forked markdown framework: automated JSON config with npm run configure, or step-by-step manual guide."
+date: "2025-12-20"
+slug: "fork-configuration-guide"
+published: true
+tags: ["configuration", "setup", "fork", "tutorial"]
+readTime: "4 min read"
+featured: true
+featuredOrder: 0
+image: "/images/forkconfig.png"
+excerpt: "Set up your forked site with npm run configure or follow the manual FORK_CONFIG.md guide."
+---
+
+# Configure your fork in one command
+
+After forking this markdown framework, you need to update configuration files with your site information. This affects your site name, URLs, RSS feeds, social sharing metadata, and AI discovery files.
+
+Previously this meant editing 10+ files manually. Now you have two options.
+
+## Option 1: Automated configuration
+
+Run a single command to configure everything at once.
+
+### Step 1: Copy the example config
+
+```bash
+cp fork-config.json.example fork-config.json
+```
+
+The file `fork-config.json` is gitignored, so your site configuration stays local and does not get committed. The `.example` file remains in the repo as a template for future forks.
+
+### Step 2: Edit the JSON file
+
+Open `fork-config.json` and update the values:
+
+```json
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "A one-sentence description of your site.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Write markdown, sync from the terminal. Your content is instantly available to browsers, LLMs, and AI agents.",
+ "theme": "tan"
+}
+```
+
+### Step 3: Run the configure script
+
+```bash
+npm run configure
+```
+
+The script reads your JSON file and updates all 11 configuration files automatically. You should see output like:
+
+```
+Fork Configuration Script
+=========================
+Reading config from fork-config.json...
+Updating src/config/siteConfig.ts...
+Updating src/pages/Home.tsx...
+Updating src/pages/Post.tsx...
+Updating convex/http.ts...
+Updating convex/rss.ts...
+Updating index.html...
+Updating public/llms.txt...
+Updating public/robots.txt...
+Updating public/openapi.yaml...
+Updating public/.well-known/ai-plugin.json...
+Updating src/context/ThemeContext.tsx...
+
+Configuration complete!
+```
+
+## Option 2: Manual configuration
+
+If you prefer to update files manually, follow the guide in `FORK_CONFIG.md`. It includes:
+
+- Code snippets for each configuration file
+- Line numbers and exact locations to update
+- An AI agent prompt to paste into Claude or ChatGPT for assisted configuration
+
+## What gets updated
+
+The configuration script updates these files:
+
+| File | What changes |
+| ----------------------------------- | ----------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub username, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+## Optional settings
+
+The JSON config file supports additional options:
+
+```json
+{
+ "logoGallery": {
+ "enabled": true,
+ "title": "Built with",
+ "scrolling": false,
+ "maxItems": 4
+ },
+ "gitHubContributions": {
+ "enabled": true,
+ "showYearNavigation": true,
+ "linkToProfile": true,
+ "title": "GitHub Activity"
+ },
+ "blogPage": {
+ "enabled": true,
+ "showInNav": true,
+ "title": "Blog",
+ "description": "Latest posts",
+ "order": 0
+ },
+ "postsDisplay": {
+ "showOnHome": true,
+ "showOnBlogPage": true
+ },
+ "featuredViewMode": "cards",
+ "showViewToggle": true,
+ "theme": "tan"
+}
+```
+
+These are optional. If you omit them, the script uses sensible defaults.
+
+## After configuring
+
+Once configuration is complete:
+
+1. **Deploy Convex functions**: Run `npx convex deploy` to push the updated backend files
+2. **Sync your content**: Run `npm run sync` for development or `npm run sync:prod` for production
+3. **Test locally**: Run `npm run dev` and verify your site name, footer, and metadata
+4. **Push to git**: Commit all changes and push to trigger a Netlify rebuild
+
+## Existing content
+
+The configuration script only updates site-level settings. It does not modify your markdown content in `content/blog/` or `content/pages/`. Your existing posts and pages remain unchanged.
+
+If you want to clear the sample content, delete the markdown files in those directories before syncing.
+
+## Summary
+
+Two options after forking:
+
+1. **Automated**: `cp fork-config.json.example fork-config.json`, edit JSON, run `npm run configure`
+2. **Manual**: Follow `FORK_CONFIG.md` step-by-step or paste the AI prompt into Claude/ChatGPT
+
+Both approaches update the same 11 files. The automated option takes about 30 seconds. The manual option gives you more control over each change.
+
+Fork it, configure it, ship it.
diff --git a/content/blog/markdown-with-code-examples.md b/content/blog/markdown-with-code-examples.md
index 89b187a..6d43a8a 100644
--- a/content/blog/markdown-with-code-examples.md
+++ b/content/blog/markdown-with-code-examples.md
@@ -6,7 +6,7 @@ slug: "markdown-with-code-examples"
published: true
tags: ["markdown", "tutorial", "code"]
readTime: "5 min read"
-featured: true
+featured: false
featuredOrder: 5
image: "/images/markdown.png"
---
diff --git a/content/blog/raw-markdown-and-copy-improvements.md b/content/blog/raw-markdown-and-copy-improvements.md
index 8b19c2d..c5b2855 100644
--- a/content/blog/raw-markdown-and-copy-improvements.md
+++ b/content/blog/raw-markdown-and-copy-improvements.md
@@ -1,103 +1,223 @@
---
-title: "v1.7 to v1.10 - Mobile menu, scroll-to-top, and fork configuration"
-description: "New features for mobile navigation, scroll-to-top button, fork configuration documentation, sharing content with AI tools, and improved table styling."
+title: "v1.18.0 release: 12 versions of shipping"
+description: "Everything new from v1.7 to v1.18.0. Automated fork setup, GitHub contributions graph, write page, mobile menu, aggregates, and more."
date: "2025-12-20"
slug: "raw-markdown-and-copy-improvements"
published: true
-tags: ["features", "markdown", "updates", "mobile", "configuration"]
-readTime: "5 min read"
+tags: ["release", "features", "updates", "developer-tools"]
+readTime: "8 min read"
featured: true
-featuredOrder: 1
+featuredOrder: 2
image: "/images/v17.png"
-excerpt: "Mobile menu, scroll-to-top button, fork configuration, raw markdown files, and Generate Skill for AI agents."
+excerpt: "12 versions of new features: automated fork config, GitHub graph, write page, mobile menu, stats aggregates, and more."
---
-## Fork configuration (v1.10.0)
+## What shipped from v1.7 to v1.18
-When you fork this project, update these files with your site information:
+This post covers 12 versions of updates to the markdown sync framework. From raw markdown files to automated fork configuration, here is everything that changed.
-| File | What to update |
-| ----------------------------------- | ----------------------------------------------------------- |
-| `src/pages/Home.tsx` | Site name, title, intro, bio, featured config, logo gallery |
-| `convex/http.ts` | `SITE_URL`, `SITE_NAME` (API responses, sitemap) |
-| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
-| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
-| `index.html` | Title, meta description, OG tags, JSON-LD |
-| `public/llms.txt` | Site name, URL, description |
-| `public/robots.txt` | Sitemap URL |
-| `public/openapi.yaml` | Server URL, site name in examples |
-| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+## Automated fork configuration (v1.18.0)
-These constants affect RSS feeds, API responses, sitemaps, and social sharing metadata.
+Fork setup now takes one command:
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json with your site info
+npm run configure
+```
+
+The configure script updates all 11 configuration files:
+
+| File | What it updates |
+| ----------------------------------- | -------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+Two options for fork setup:
+
+1. **Automated** (recommended): JSON config file + `npm run configure`
+2. **Manual**: Follow step-by-step instructions in `FORK_CONFIG.md`
+
+## GitHub contributions graph (v1.17.0)
+
+The homepage now displays a GitHub-style contribution graph. Configure it in siteConfig:
+
+```typescript
+gitHubContributions: {
+ enabled: true,
+ username: "your-github-username",
+ showYearNavigation: true,
+ linkToProfile: true,
+ title: "Contributions",
+}
+```
+
+Features:
+
+- Theme-aware colors (dark, light, tan, cloud each have unique palettes)
+- Year navigation with Phosphor CaretLeft/CaretRight icons
+- Click the graph to visit the GitHub profile
+- Uses public API (no GitHub token required)
+- Mobile responsive with scaled cells
+
+## Write page (v1.13.0 to v1.16.0)
+
+A markdown writing page now lives at `/write`. Not linked in navigation. Access it directly.
+
+Three-column layout:
+
+- **Left sidebar**: Home link, content type selector (Blog Post/Page), actions (Clear, Theme, Font)
+- **Center**: Full-height writing area with Copy All button
+- **Right sidebar**: Frontmatter reference with per-field copy buttons
+
+Features across iterations:
+
+- Font switcher toggles between Serif and Sans-serif
+- Theme toggle matches the rest of the app
+- localStorage persistence for content, type, and font preference
+- Word, line, and character counts in status bar
+- Warning banner about refresh losing content
+- Works with Grammarly and browser spellcheck
+- Mobile responsive with stacked layout
+
+The write page does not connect to Convex. It stores content locally. Copy your markdown and paste it into a file in `content/blog/` or `content/pages/`, then run `npm run sync`.
+
+## Stats aggregates (v1.11.0)
+
+The stats page now uses O(log n) aggregate counts instead of O(n) table scans.
+
+Before: Every stats query scanned the entire pageViews table.
+
+After: Three TableAggregate instances provide pre-computed counts:
+
+- `totalPageViews`: Global view count
+- `pageViewsByPath`: Per-page view counts
+- `uniqueVisitors`: Distinct session count
+
+Run the backfill after deploying:
+
+```bash
+npx convex run stats:backfillAggregates
+```
+
+The backfill processes 500 records at a time to stay under the 16MB Convex memory limit. It schedules itself to continue until complete.
+
+Stats queries now respond consistently fast regardless of how many page views exist.
+
+## Dedicated blog page (v1.12.0)
+
+A dedicated `/blog` page now exists. Configure it in siteConfig:
+
+```typescript
+blogPage: {
+ enabled: true, // Enable /blog route
+ showInNav: true, // Show in navigation
+ title: "Blog", // Page title
+ order: 0, // Nav order (lower = first)
+},
+displayOnHomepage: true, // Also show posts on homepage
+```
+
+Navigation combines the Blog link with page links and sorts by order. Set `order: 5` to place Blog after pages with order 0-4.
+
+Centralized configuration now lives in `src/config/siteConfig.ts` instead of scattered across components.
+
+## Fork configuration documentation (v1.10.0)
+
+The docs, setup guide, and README now include a "Files to Update When Forking" section listing all 9 configuration files:
+
+- Frontend: `siteConfig.ts`, `Home.tsx`, `Post.tsx`
+- Backend: `http.ts`, `rss.ts`
+- HTML: `index.html`
+- AI discovery: `llms.txt`, `robots.txt`, `openapi.yaml`, `ai-plugin.json`
## Scroll-to-top button (v1.9.0)
-A scroll-to-top button now appears after scrolling 300px. Configure it in `src/components/Layout.tsx`:
+A scroll-to-top button appears after scrolling 300px. Configure it in `src/components/Layout.tsx`:
```typescript
const scrollToTopConfig: Partial = {
- enabled: true, // Set to false to disable
- threshold: 300, // Show after scrolling 300px
+ enabled: true, // Set false to disable
+ threshold: 300, // Pixels before showing
smooth: true, // Smooth scroll animation
};
```
-The button uses the Phosphor ArrowUp icon and works with all four themes. It uses a passive scroll listener for performance and includes a fade-in animation.
+Uses Phosphor ArrowUp icon. Works with all four themes. Passive scroll listener for performance.
## Mobile menu (v1.8.0)
-The site now includes a mobile menu with hamburger navigation for smaller screens. On mobile and tablet views, a hamburger icon appears in the top navigation. Tap it to open a slide-out drawer with all page navigation links.
+Hamburger navigation for mobile and tablet screens. Tap the icon to open a slide-out drawer with page links.
-**Features:**
+Features:
- Smooth CSS transform animations
-- Keyboard accessible (press Escape to close)
+- Keyboard accessible (Escape to close)
- Focus trap for screen reader support
- Home link at the bottom of the drawer
-- Auto-closes when navigating to a new page
+- Auto-closes when navigating
-The desktop navigation remains unchanged. The mobile menu only appears on screens below 1024px.
+Desktop navigation stays unchanged. Mobile menu only appears below 1024px.
-## Static raw markdown files
+## Generate Skill (v1.8.0)
-Every published post and page now gets a static `.md` file at `/raw/{slug}.md`. These files are generated automatically when you run `npm run sync`.
+The CopyPageDropdown now includes a Generate Skill option. Click to download the current post or page as an AI agent skill file.
-**Example URLs:**
+The skill file includes:
+
+- Metadata section with title, description, and tags
+- When to use section describing scenarios
+- Instructions section with full content
+
+Downloads as `{slug}-skill.md`. Use these files to train AI agents or add context to workflows.
+
+## Static raw markdown files (v1.7.0)
+
+Every published post and page now gets a static `.md` file at `/raw/{slug}.md`. Generated during `npm run sync`.
+
+Example URLs:
- `/raw/setup-guide.md`
- `/raw/about.md`
- `/raw/how-to-publish.md`
-Each file includes a metadata header with type, date, reading time, and tags. The content matches exactly what you see on the page.
+Each file includes a metadata header with type, date, reading time, and tags.
-**Use cases:**
+Use cases:
- Share raw markdown with AI agents
- Link directly to source content for LLM ingestion
- View the markdown source of any post
-## View as Markdown in CopyPageDropdown
+## View as Markdown (v1.7.0)
-The Copy Page dropdown now includes a "View as Markdown" option. Click it to open the raw `.md` file in a new tab.
+The Copy Page dropdown now includes "View as Markdown" to open the raw `.md` file in a new tab.
-This joins the existing options:
+Other dropdown options:
-- Copy page (copies formatted markdown to clipboard)
+- Copy page (formatted markdown to clipboard)
- Open in ChatGPT
- Open in Claude
-- Open in Perplexity (new)
+- Open in Perplexity
-## Perplexity integration
+## Perplexity integration (v1.7.0)
-Perplexity is now available as an AI service option. Click "Open in Perplexity" to send the full article content directly to Perplexity for research and analysis.
+Perplexity is now available as an AI service option. Click to send full article content to Perplexity for research and analysis.
-Like the other AI options, if the URL gets too long, the content is copied to your clipboard and Perplexity opens in a new tab. Paste to continue.
+If the URL gets too long, content copies to clipboard and Perplexity opens in a new tab. Paste to continue.
-## Featured images
+## Featured images (v1.7.0)
-Posts and pages can now include a featured image that displays in the card view on the homepage.
-
-Add to your frontmatter:
+Posts and pages can include a featured image that displays in card view:
```yaml
image: "/images/my-thumbnail.png"
@@ -105,11 +225,33 @@ featured: true
featuredOrder: 1
```
-The image displays as a square thumbnail above the title in card view. Non-square images are automatically cropped to center. Recommended size: 400x400px minimum (800x800px for retina).
+The image displays as a square thumbnail above the title. Non-square images crop to center. Recommended: 400x400px minimum (800x800px for retina).
-## Improved markdown table styling
+## Open Graph image fix (v1.12.1)
-Tables now render with GitHub-style formatting across all four themes:
+Posts with `image` in frontmatter now display their specific OG image when shared. Posts without images fall back to `og-default.svg`. Pages now supported with `og:type` set to "website".
+
+Relative image paths (like `/images/v17.png`) resolve to absolute URLs automatically.
+
+## Centralized font sizes (v1.12.2)
+
+All font sizes now use CSS variables in `global.css`:
+
+```css
+:root {
+ --font-size-xs: 12px;
+ --font-size-sm: 13px;
+ --font-size-base: 16px;
+ --font-size-lg: 17px;
+ /* ... */
+}
+```
+
+Edit `:root` variables to customize font sizes across the entire site. Mobile responsive overrides at 768px breakpoint.
+
+## Improved table styling (v1.7.0)
+
+Tables render with GitHub-style formatting:
| Feature | Status |
| ------- | ----------------------- |
@@ -118,32 +260,31 @@ Tables now render with GitHub-style formatting across all four themes:
| Hover | Row highlighting |
| Themes | Dark, light, tan, cloud |
-Tables adapt to each theme with proper alternating row colors and hover states.
+Alternating row colors and hover states adapt to each theme.
-## Generate Skill
+## Quick reference: sync vs deploy
-The CopyPageDropdown now includes a Generate Skill option. Click it to download the current post or page as an AI agent skill file.
+| Change | Command | Speed |
+| ----------------------- | -------------------------- | -------------- |
+| Blog posts | `npm run sync` | Instant |
+| Pages | `npm run sync` | Instant |
+| Featured items | `npm run sync` | Instant |
+| Import external URL | `npm run import` then sync | Instant |
+| siteConfig changes | Redeploy | Requires build |
+| Logo gallery config | Redeploy | Requires build |
+| React components/styles | Redeploy | Requires build |
+| Fork configuration | `npm run configure` | Instant |
-The skill file includes:
+Markdown content syncs instantly via Convex. Source code changes require pushing to GitHub for Netlify to rebuild.
-- Metadata section with title, description, and tags
-- When to use section describing scenarios for the skill
-- Instructions section with the full content
+## Upgrade path
-The file downloads as `{slug}-skill.md`. Use these skill files to train AI agents or add context to your workflows.
+If upgrading from an earlier version:
-## Summary
+1. Pull the latest code
+2. Run `npm install` for new dependencies
+3. Run `npx convex dev` to sync schema changes
+4. Run `npx convex run stats:backfillAggregates` if using stats
+5. Check `siteConfig.ts` for new configuration options
-These updates improve navigation, configuration, and sharing with AI tools:
-
-1. **Fork configuration** documentation for all 9 site files
-2. **Scroll-to-top button** with configurable threshold
-3. **Mobile menu** with slide-out drawer for smaller screens
-4. **Raw markdown files** at `/raw/{slug}.md` for direct access
-5. **View as Markdown** option in CopyPageDropdown
-6. **Perplexity** added alongside ChatGPT and Claude
-7. **Generate Skill** for AI agent training
-8. **Featured images** for visual card layouts
-9. **Better tables** with responsive styling
-
-All features work across all four themes and are mobile responsive. Run `npm run sync` for development and `npm run sync:prod` for production to update your site with these changes.
+All features work across all four themes and are mobile responsive.
diff --git a/content/blog/setup-guide.md b/content/blog/setup-guide.md
index 85ccf7c..641c9c6 100644
--- a/content/blog/setup-guide.md
+++ b/content/blog/setup-guide.md
@@ -408,14 +408,58 @@ Both files are gitignored. Each developer creates their own local environment fi
## Customizing Your Framework
-### Files to Update When Forking
+### Fork Configuration Options
-When you fork this project, update these files with your site information:
+After forking, you have two options to configure your site:
+
+#### Option 1: Automated (Recommended)
+
+Run a single command to configure all files automatically:
+
+```bash
+# Copy the example config
+cp fork-config.json.example fork-config.json
+
+# Edit fork-config.json with your site information
+# Then apply all changes
+npm run configure
+```
+
+The `fork-config.json` file includes:
+
+```json
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "Your site description.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Your bio text here.",
+ "theme": "tan"
+}
+```
+
+This updates all 11 configuration files in one step. See `FORK_CONFIG.md` for the full JSON schema.
+
+#### Option 2: Manual
+
+Follow the step-by-step guide in `FORK_CONFIG.md` to update each file manually. The guide includes code snippets for each file and an AI agent prompt for assisted configuration.
+
+### Files to Update When Forking
| File | What to update |
| ----------------------------------- | --------------------------------------------------------------------------- |
| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
-| `src/pages/Home.tsx` | Intro paragraph text (hardcoded JSX) |
+| `src/pages/Home.tsx` | Intro paragraph text, footer links |
| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
@@ -424,6 +468,7 @@ When you fork this project, update these files with your site information:
| `public/robots.txt` | Sitemap URL and header comment |
| `public/openapi.yaml` | API title, server URL, site name in examples |
| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+| `src/context/ThemeContext.tsx` | Default theme |
### Site title and description metadata
diff --git a/content/pages/about.md b/content/pages/about.md
index 7a03f5d..3f9a2ce 100644
--- a/content/pages/about.md
+++ b/content/pages/about.md
@@ -73,4 +73,16 @@ It's a hybrid: developer workflow for publishing + real-time delivery like a dyn
- Projects where AI agents generate content programmatically
- Sites that need real-time updates without full rebuilds
+## Fork configuration
+
+After forking, configure your site with a single command:
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json
+npm run configure
+```
+
+Or follow the manual guide in `FORK_CONFIG.md`. Both options update all 11 configuration files with your site information.
+
Fork it, customize it, ship it.
diff --git a/content/pages/changelog-page.md b/content/pages/changelog-page.md
index bee1629..e927877 100644
--- a/content/pages/changelog-page.md
+++ b/content/pages/changelog-page.md
@@ -7,6 +7,40 @@ order: 5
All notable changes to this project.
+## v1.18.0
+
+Released December 20, 2025
+
+**Automated fork configuration**
+
+- New `npm run configure` command for one-step fork setup
+- Copy `fork-config.json.example` to `fork-config.json`
+- Edit the JSON file with your site information
+- Run `npm run configure` to apply all changes automatically
+
+Two options for fork setup:
+
+1. **Automated** (recommended): JSON config file + `npm run configure`
+2. **Manual**: Follow step-by-step instructions in `FORK_CONFIG.md`
+
+The configure script updates all 11 configuration files:
+
+| File | What it updates |
+| ----------------------------------- | ---------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+New files: `FORK_CONFIG.md`, `fork-config.json.example`, `scripts/configure-fork.ts`
+
## v1.17.0
Released December 20, 2025
diff --git a/content/pages/docs.md b/content/pages/docs.md
index 52c27ef..f64482d 100644
--- a/content/pages/docs.md
+++ b/content/pages/docs.md
@@ -149,22 +149,39 @@ npm run sync:prod
## Configuration
-### Site and backend settings
+### Fork configuration
-When you fork this project, update these files with your site information:
+After forking, you have two options to configure your site:
-| File | What to update |
-|------|----------------|
-| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
-| `src/pages/Home.tsx` | Intro paragraph text (hardcoded JSX) |
-| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
-| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
-| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
-| `index.html` | Title, meta description, OG tags, JSON-LD |
-| `public/llms.txt` | Site name, URL, description, topics |
-| `public/robots.txt` | Sitemap URL and header comment |
-| `public/openapi.yaml` | API title, server URL, site name in examples |
-| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+**Option 1: Automated (Recommended)**
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json with your site information
+npm run configure
+```
+
+This updates all 11 configuration files in one command. See `FORK_CONFIG.md` for the full JSON schema and options.
+
+**Option 2: Manual**
+
+Follow the step-by-step guide in `FORK_CONFIG.md` to update each file manually.
+
+### Files updated by configuration
+
+| File | What to update |
+| ----------------------------------- | --------------------------------------------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
+| `src/pages/Home.tsx` | Intro paragraph text, footer links |
+| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
+| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
+| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
+| `index.html` | Title, meta description, OG tags, JSON-LD |
+| `public/llms.txt` | Site name, URL, description, topics |
+| `public/robots.txt` | Sitemap URL and header comment |
+| `public/openapi.yaml` | API title, server URL, site name in examples |
+| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+| `src/context/ThemeContext.tsx` | Default theme |
### Site title and description metadata
diff --git a/files.md b/files.md
index 1b60dcf..2b0a05a 100644
--- a/files.md
+++ b/files.md
@@ -4,18 +4,20 @@ A brief description of each file in the codebase.
## Root Files
-| File | Description |
-| ---------------- | ---------------------------------------------- |
-| `package.json` | Dependencies and scripts for the blog |
-| `tsconfig.json` | TypeScript configuration |
-| `vite.config.ts` | Vite bundler configuration |
-| `index.html` | Main HTML entry with SEO meta tags and JSON-LD |
-| `netlify.toml` | Netlify deployment and Convex HTTP redirects |
-| `README.md` | Project documentation |
-| `AGENTS.md` | AI coding agent instructions (agents.md spec) |
-| `files.md` | This file - codebase structure |
-| `changelog.md` | Version history and changes |
-| `TASK.md` | Task tracking and project status |
+| File | Description |
+| -------------------------- | ---------------------------------------------------- |
+| `package.json` | Dependencies and scripts for the blog |
+| `tsconfig.json` | TypeScript configuration |
+| `vite.config.ts` | Vite bundler configuration |
+| `index.html` | Main HTML entry with SEO meta tags and JSON-LD |
+| `netlify.toml` | Netlify deployment and Convex HTTP redirects |
+| `README.md` | Project documentation |
+| `AGENTS.md` | AI coding agent instructions (agents.md spec) |
+| `files.md` | This file - codebase structure |
+| `changelog.md` | Version history and changes |
+| `TASK.md` | Task tracking and project status |
+| `FORK_CONFIG.md` | Fork configuration guide (manual + automated options)|
+| `fork-config.json.example` | Template JSON config for automated fork setup |
## Source Files (`src/`)
@@ -142,10 +144,11 @@ Markdown files for static pages like About, Projects, Contact, Changelog.
## Scripts (`scripts/`)
-| File | Description |
-| --------------- | ------------------------------------------------- |
-| `sync-posts.ts` | Syncs markdown files to Convex at build time |
-| `import-url.ts` | Imports external URLs as markdown posts (Firecrawl) |
+| File | Description |
+| -------------------- | ---------------------------------------------------------- |
+| `sync-posts.ts` | Syncs markdown files to Convex at build time |
+| `import-url.ts` | Imports external URLs as markdown posts (Firecrawl) |
+| `configure-fork.ts` | Automated fork configuration (reads fork-config.json) |
## Netlify (`netlify/edge-functions/`)
diff --git a/fork-config.json.example b/fork-config.json.example
new file mode 100644
index 0000000..ececf80
--- /dev/null
+++ b/fork-config.json.example
@@ -0,0 +1,44 @@
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "A one-sentence description of your site.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Write markdown, sync from the terminal. Your content is instantly available to browsers, LLMs, and AI agents.",
+ "logoGallery": {
+ "enabled": true,
+ "title": "Built with",
+ "scrolling": false,
+ "maxItems": 4
+ },
+ "gitHubContributions": {
+ "enabled": true,
+ "showYearNavigation": true,
+ "linkToProfile": true,
+ "title": "GitHub Activity"
+ },
+ "blogPage": {
+ "enabled": true,
+ "showInNav": true,
+ "title": "Blog",
+ "description": "All posts from the blog, sorted by date.",
+ "order": 2
+ },
+ "postsDisplay": {
+ "showOnHome": true,
+ "showOnBlogPage": true
+ },
+ "featuredViewMode": "cards",
+ "showViewToggle": true,
+ "theme": "tan"
+}
+
diff --git a/package.json b/package.json
index 60d0cb0..438f916 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"sync": "npx tsx scripts/sync-posts.ts",
"sync:prod": "SYNC_ENV=production npx tsx scripts/sync-posts.ts",
"import": "npx tsx scripts/import-url.ts",
+ "configure": "npx tsx scripts/configure-fork.ts",
"deploy": "npm run sync && npm run build",
"deploy:prod": "npx convex deploy && npm run sync:prod"
},
diff --git a/public/images/117dataimage.png b/public/images/117dataimage.png
deleted file mode 100644
index 31c83e8..0000000
Binary files a/public/images/117dataimage.png and /dev/null differ
diff --git a/public/images/forkconfig.png b/public/images/forkconfig.png
new file mode 100644
index 0000000..6146316
Binary files /dev/null and b/public/images/forkconfig.png differ
diff --git a/public/images/v17.png b/public/images/v17.png
index 496049f..fc2dfdf 100644
Binary files a/public/images/v17.png and b/public/images/v17.png differ
diff --git a/public/raw/about.md b/public/raw/about.md
index 15360dd..0344ee8 100644
--- a/public/raw/about.md
+++ b/public/raw/about.md
@@ -72,4 +72,16 @@ It's a hybrid: developer workflow for publishing + real-time delivery like a dyn
- Projects where AI agents generate content programmatically
- Sites that need real-time updates without full rebuilds
+## Fork configuration
+
+After forking, configure your site with a single command:
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json
+npm run configure
+```
+
+Or follow the manual guide in `FORK_CONFIG.md`. Both options update all 11 configuration files with your site information.
+
Fork it, customize it, ship it.
\ No newline at end of file
diff --git a/public/raw/changelog.md b/public/raw/changelog.md
index 521222e..42f3d0b 100644
--- a/public/raw/changelog.md
+++ b/public/raw/changelog.md
@@ -7,6 +7,40 @@ Date: 2025-12-21
All notable changes to this project.
+## v1.18.0
+
+Released December 20, 2025
+
+**Automated fork configuration**
+
+- New `npm run configure` command for one-step fork setup
+- Copy `fork-config.json.example` to `fork-config.json`
+- Edit the JSON file with your site information
+- Run `npm run configure` to apply all changes automatically
+
+Two options for fork setup:
+
+1. **Automated** (recommended): JSON config file + `npm run configure`
+2. **Manual**: Follow step-by-step instructions in `FORK_CONFIG.md`
+
+The configure script updates all 11 configuration files:
+
+| File | What it updates |
+| ----------------------------------- | ---------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+New files: `FORK_CONFIG.md`, `fork-config.json.example`, `scripts/configure-fork.ts`
+
## v1.17.0
Released December 20, 2025
diff --git a/public/raw/docs.md b/public/raw/docs.md
index 10f8908..44ed639 100644
--- a/public/raw/docs.md
+++ b/public/raw/docs.md
@@ -149,22 +149,39 @@ npm run sync:prod
## Configuration
-### Site and backend settings
+### Fork configuration
-When you fork this project, update these files with your site information:
+After forking, you have two options to configure your site:
-| File | What to update |
-|------|----------------|
-| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
-| `src/pages/Home.tsx` | Intro paragraph text (hardcoded JSX) |
-| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
-| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
-| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
-| `index.html` | Title, meta description, OG tags, JSON-LD |
-| `public/llms.txt` | Site name, URL, description, topics |
-| `public/robots.txt` | Sitemap URL and header comment |
-| `public/openapi.yaml` | API title, server URL, site name in examples |
-| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+**Option 1: Automated (Recommended)**
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json with your site information
+npm run configure
+```
+
+This updates all 11 configuration files in one command. See `FORK_CONFIG.md` for the full JSON schema and options.
+
+**Option 2: Manual**
+
+Follow the step-by-step guide in `FORK_CONFIG.md` to update each file manually.
+
+### Files updated by configuration
+
+| File | What to update |
+| ----------------------------------- | --------------------------------------------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
+| `src/pages/Home.tsx` | Intro paragraph text, footer links |
+| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
+| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
+| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
+| `index.html` | Title, meta description, OG tags, JSON-LD |
+| `public/llms.txt` | Site name, URL, description, topics |
+| `public/robots.txt` | Sitemap URL and header comment |
+| `public/openapi.yaml` | API title, server URL, site name in examples |
+| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+| `src/context/ThemeContext.tsx` | Default theme |
### Site title and description metadata
diff --git a/public/raw/fork-configuration-guide.md b/public/raw/fork-configuration-guide.md
new file mode 100644
index 0000000..ebb567e
--- /dev/null
+++ b/public/raw/fork-configuration-guide.md
@@ -0,0 +1,169 @@
+# Configure your fork in one command
+
+> Two options to set up your forked markdown framework: automated JSON config with npm run configure, or step-by-step manual guide.
+
+---
+Type: post
+Date: 2025-12-20
+Reading time: 4 min read
+Tags: configuration, setup, fork, tutorial
+---
+
+# Configure your fork in one command
+
+After forking this markdown framework, you need to update configuration files with your site information. This affects your site name, URLs, RSS feeds, social sharing metadata, and AI discovery files.
+
+Previously this meant editing 10+ files manually. Now you have two options.
+
+## Option 1: Automated configuration
+
+Run a single command to configure everything at once.
+
+### Step 1: Copy the example config
+
+```bash
+cp fork-config.json.example fork-config.json
+```
+
+The file `fork-config.json` is gitignored, so your site configuration stays local and does not get committed. The `.example` file remains in the repo as a template for future forks.
+
+### Step 2: Edit the JSON file
+
+Open `fork-config.json` and update the values:
+
+```json
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "A one-sentence description of your site.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Write markdown, sync from the terminal. Your content is instantly available to browsers, LLMs, and AI agents.",
+ "theme": "tan"
+}
+```
+
+### Step 3: Run the configure script
+
+```bash
+npm run configure
+```
+
+The script reads your JSON file and updates all 11 configuration files automatically. You should see output like:
+
+```
+Fork Configuration Script
+=========================
+Reading config from fork-config.json...
+Updating src/config/siteConfig.ts...
+Updating src/pages/Home.tsx...
+Updating src/pages/Post.tsx...
+Updating convex/http.ts...
+Updating convex/rss.ts...
+Updating index.html...
+Updating public/llms.txt...
+Updating public/robots.txt...
+Updating public/openapi.yaml...
+Updating public/.well-known/ai-plugin.json...
+Updating src/context/ThemeContext.tsx...
+
+Configuration complete!
+```
+
+## Option 2: Manual configuration
+
+If you prefer to update files manually, follow the guide in `FORK_CONFIG.md`. It includes:
+
+- Code snippets for each configuration file
+- Line numbers and exact locations to update
+- An AI agent prompt to paste into Claude or ChatGPT for assisted configuration
+
+## What gets updated
+
+The configuration script updates these files:
+
+| File | What changes |
+| ----------------------------------- | ----------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub username, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+## Optional settings
+
+The JSON config file supports additional options:
+
+```json
+{
+ "logoGallery": {
+ "enabled": true,
+ "title": "Built with",
+ "scrolling": false,
+ "maxItems": 4
+ },
+ "gitHubContributions": {
+ "enabled": true,
+ "showYearNavigation": true,
+ "linkToProfile": true,
+ "title": "GitHub Activity"
+ },
+ "blogPage": {
+ "enabled": true,
+ "showInNav": true,
+ "title": "Blog",
+ "description": "Latest posts",
+ "order": 0
+ },
+ "postsDisplay": {
+ "showOnHome": true,
+ "showOnBlogPage": true
+ },
+ "featuredViewMode": "cards",
+ "showViewToggle": true,
+ "theme": "tan"
+}
+```
+
+These are optional. If you omit them, the script uses sensible defaults.
+
+## After configuring
+
+Once configuration is complete:
+
+1. **Deploy Convex functions**: Run `npx convex deploy` to push the updated backend files
+2. **Sync your content**: Run `npm run sync` for development or `npm run sync:prod` for production
+3. **Test locally**: Run `npm run dev` and verify your site name, footer, and metadata
+4. **Push to git**: Commit all changes and push to trigger a Netlify rebuild
+
+## Existing content
+
+The configuration script only updates site-level settings. It does not modify your markdown content in `content/blog/` or `content/pages/`. Your existing posts and pages remain unchanged.
+
+If you want to clear the sample content, delete the markdown files in those directories before syncing.
+
+## Summary
+
+Two options after forking:
+
+1. **Automated**: `cp fork-config.json.example fork-config.json`, edit JSON, run `npm run configure`
+2. **Manual**: Follow `FORK_CONFIG.md` step-by-step or paste the AI prompt into Claude/ChatGPT
+
+Both approaches update the same 11 files. The automated option takes about 30 seconds. The manual option gives you more control over each change.
+
+Fork it, configure it, ship it.
\ No newline at end of file
diff --git a/public/raw/raw-markdown-and-copy-improvements.md b/public/raw/raw-markdown-and-copy-improvements.md
index abdbe6c..a6d21e8 100644
--- a/public/raw/raw-markdown-and-copy-improvements.md
+++ b/public/raw/raw-markdown-and-copy-improvements.md
@@ -1,100 +1,220 @@
-# v1.7 to v1.10 - Mobile menu, scroll-to-top, and fork configuration
+# v1.18.0 release: 12 versions of shipping
-> New features for mobile navigation, scroll-to-top button, fork configuration documentation, sharing content with AI tools, and improved table styling.
+> Everything new from v1.7 to v1.18.0. Automated fork setup, GitHub contributions graph, write page, mobile menu, aggregates, and more.
---
Type: post
Date: 2025-12-20
-Reading time: 5 min read
-Tags: features, markdown, updates, mobile, configuration
+Reading time: 8 min read
+Tags: release, features, updates, developer-tools
---
-## Fork configuration (v1.10.0)
+## What shipped from v1.7 to v1.18
-When you fork this project, update these files with your site information:
+This post covers 12 versions of updates to the markdown sync framework. From raw markdown files to automated fork configuration, here is everything that changed.
-| File | What to update |
-| ----------------------------------- | ----------------------------------------------------------- |
-| `src/pages/Home.tsx` | Site name, title, intro, bio, featured config, logo gallery |
-| `convex/http.ts` | `SITE_URL`, `SITE_NAME` (API responses, sitemap) |
-| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
-| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
-| `index.html` | Title, meta description, OG tags, JSON-LD |
-| `public/llms.txt` | Site name, URL, description |
-| `public/robots.txt` | Sitemap URL |
-| `public/openapi.yaml` | Server URL, site name in examples |
-| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+## Automated fork configuration (v1.18.0)
-These constants affect RSS feeds, API responses, sitemaps, and social sharing metadata.
+Fork setup now takes one command:
+
+```bash
+cp fork-config.json.example fork-config.json
+# Edit fork-config.json with your site info
+npm run configure
+```
+
+The configure script updates all 11 configuration files:
+
+| File | What it updates |
+| ----------------------------------- | -------------------------------------- |
+| `src/config/siteConfig.ts` | Site name, bio, GitHub, features |
+| `src/pages/Home.tsx` | Intro paragraph, footer links |
+| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
+| `convex/http.ts` | SITE_URL, SITE_NAME constants |
+| `convex/rss.ts` | SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
+| `index.html` | Meta tags, JSON-LD, page title |
+| `public/llms.txt` | Site info, GitHub link |
+| `public/robots.txt` | Sitemap URL |
+| `public/openapi.yaml` | Server URL, site name |
+| `public/.well-known/ai-plugin.json` | Plugin metadata |
+| `src/context/ThemeContext.tsx` | Default theme |
+
+Two options for fork setup:
+
+1. **Automated** (recommended): JSON config file + `npm run configure`
+2. **Manual**: Follow step-by-step instructions in `FORK_CONFIG.md`
+
+## GitHub contributions graph (v1.17.0)
+
+The homepage now displays a GitHub-style contribution graph. Configure it in siteConfig:
+
+```typescript
+gitHubContributions: {
+ enabled: true,
+ username: "your-github-username",
+ showYearNavigation: true,
+ linkToProfile: true,
+ title: "Contributions",
+}
+```
+
+Features:
+
+- Theme-aware colors (dark, light, tan, cloud each have unique palettes)
+- Year navigation with Phosphor CaretLeft/CaretRight icons
+- Click the graph to visit the GitHub profile
+- Uses public API (no GitHub token required)
+- Mobile responsive with scaled cells
+
+## Write page (v1.13.0 to v1.16.0)
+
+A markdown writing page now lives at `/write`. Not linked in navigation. Access it directly.
+
+Three-column layout:
+
+- **Left sidebar**: Home link, content type selector (Blog Post/Page), actions (Clear, Theme, Font)
+- **Center**: Full-height writing area with Copy All button
+- **Right sidebar**: Frontmatter reference with per-field copy buttons
+
+Features across iterations:
+
+- Font switcher toggles between Serif and Sans-serif
+- Theme toggle matches the rest of the app
+- localStorage persistence for content, type, and font preference
+- Word, line, and character counts in status bar
+- Warning banner about refresh losing content
+- Works with Grammarly and browser spellcheck
+- Mobile responsive with stacked layout
+
+The write page does not connect to Convex. It stores content locally. Copy your markdown and paste it into a file in `content/blog/` or `content/pages/`, then run `npm run sync`.
+
+## Stats aggregates (v1.11.0)
+
+The stats page now uses O(log n) aggregate counts instead of O(n) table scans.
+
+Before: Every stats query scanned the entire pageViews table.
+
+After: Three TableAggregate instances provide pre-computed counts:
+
+- `totalPageViews`: Global view count
+- `pageViewsByPath`: Per-page view counts
+- `uniqueVisitors`: Distinct session count
+
+Run the backfill after deploying:
+
+```bash
+npx convex run stats:backfillAggregates
+```
+
+The backfill processes 500 records at a time to stay under the 16MB Convex memory limit. It schedules itself to continue until complete.
+
+Stats queries now respond consistently fast regardless of how many page views exist.
+
+## Dedicated blog page (v1.12.0)
+
+A dedicated `/blog` page now exists. Configure it in siteConfig:
+
+```typescript
+blogPage: {
+ enabled: true, // Enable /blog route
+ showInNav: true, // Show in navigation
+ title: "Blog", // Page title
+ order: 0, // Nav order (lower = first)
+},
+displayOnHomepage: true, // Also show posts on homepage
+```
+
+Navigation combines the Blog link with page links and sorts by order. Set `order: 5` to place Blog after pages with order 0-4.
+
+Centralized configuration now lives in `src/config/siteConfig.ts` instead of scattered across components.
+
+## Fork configuration documentation (v1.10.0)
+
+The docs, setup guide, and README now include a "Files to Update When Forking" section listing all 9 configuration files:
+
+- Frontend: `siteConfig.ts`, `Home.tsx`, `Post.tsx`
+- Backend: `http.ts`, `rss.ts`
+- HTML: `index.html`
+- AI discovery: `llms.txt`, `robots.txt`, `openapi.yaml`, `ai-plugin.json`
## Scroll-to-top button (v1.9.0)
-A scroll-to-top button now appears after scrolling 300px. Configure it in `src/components/Layout.tsx`:
+A scroll-to-top button appears after scrolling 300px. Configure it in `src/components/Layout.tsx`:
```typescript
const scrollToTopConfig: Partial = {
- enabled: true, // Set to false to disable
- threshold: 300, // Show after scrolling 300px
+ enabled: true, // Set false to disable
+ threshold: 300, // Pixels before showing
smooth: true, // Smooth scroll animation
};
```
-The button uses the Phosphor ArrowUp icon and works with all four themes. It uses a passive scroll listener for performance and includes a fade-in animation.
+Uses Phosphor ArrowUp icon. Works with all four themes. Passive scroll listener for performance.
## Mobile menu (v1.8.0)
-The site now includes a mobile menu with hamburger navigation for smaller screens. On mobile and tablet views, a hamburger icon appears in the top navigation. Tap it to open a slide-out drawer with all page navigation links.
+Hamburger navigation for mobile and tablet screens. Tap the icon to open a slide-out drawer with page links.
-**Features:**
+Features:
- Smooth CSS transform animations
-- Keyboard accessible (press Escape to close)
+- Keyboard accessible (Escape to close)
- Focus trap for screen reader support
- Home link at the bottom of the drawer
-- Auto-closes when navigating to a new page
+- Auto-closes when navigating
-The desktop navigation remains unchanged. The mobile menu only appears on screens below 1024px.
+Desktop navigation stays unchanged. Mobile menu only appears below 1024px.
-## Static raw markdown files
+## Generate Skill (v1.8.0)
-Every published post and page now gets a static `.md` file at `/raw/{slug}.md`. These files are generated automatically when you run `npm run sync`.
+The CopyPageDropdown now includes a Generate Skill option. Click to download the current post or page as an AI agent skill file.
-**Example URLs:**
+The skill file includes:
+
+- Metadata section with title, description, and tags
+- When to use section describing scenarios
+- Instructions section with full content
+
+Downloads as `{slug}-skill.md`. Use these files to train AI agents or add context to workflows.
+
+## Static raw markdown files (v1.7.0)
+
+Every published post and page now gets a static `.md` file at `/raw/{slug}.md`. Generated during `npm run sync`.
+
+Example URLs:
- `/raw/setup-guide.md`
- `/raw/about.md`
- `/raw/how-to-publish.md`
-Each file includes a metadata header with type, date, reading time, and tags. The content matches exactly what you see on the page.
+Each file includes a metadata header with type, date, reading time, and tags.
-**Use cases:**
+Use cases:
- Share raw markdown with AI agents
- Link directly to source content for LLM ingestion
- View the markdown source of any post
-## View as Markdown in CopyPageDropdown
+## View as Markdown (v1.7.0)
-The Copy Page dropdown now includes a "View as Markdown" option. Click it to open the raw `.md` file in a new tab.
+The Copy Page dropdown now includes "View as Markdown" to open the raw `.md` file in a new tab.
-This joins the existing options:
+Other dropdown options:
-- Copy page (copies formatted markdown to clipboard)
+- Copy page (formatted markdown to clipboard)
- Open in ChatGPT
- Open in Claude
-- Open in Perplexity (new)
+- Open in Perplexity
-## Perplexity integration
+## Perplexity integration (v1.7.0)
-Perplexity is now available as an AI service option. Click "Open in Perplexity" to send the full article content directly to Perplexity for research and analysis.
+Perplexity is now available as an AI service option. Click to send full article content to Perplexity for research and analysis.
-Like the other AI options, if the URL gets too long, the content is copied to your clipboard and Perplexity opens in a new tab. Paste to continue.
+If the URL gets too long, content copies to clipboard and Perplexity opens in a new tab. Paste to continue.
-## Featured images
+## Featured images (v1.7.0)
-Posts and pages can now include a featured image that displays in the card view on the homepage.
-
-Add to your frontmatter:
+Posts and pages can include a featured image that displays in card view:
```yaml
image: "/images/my-thumbnail.png"
@@ -102,11 +222,33 @@ featured: true
featuredOrder: 1
```
-The image displays as a square thumbnail above the title in card view. Non-square images are automatically cropped to center. Recommended size: 400x400px minimum (800x800px for retina).
+The image displays as a square thumbnail above the title. Non-square images crop to center. Recommended: 400x400px minimum (800x800px for retina).
-## Improved markdown table styling
+## Open Graph image fix (v1.12.1)
-Tables now render with GitHub-style formatting across all four themes:
+Posts with `image` in frontmatter now display their specific OG image when shared. Posts without images fall back to `og-default.svg`. Pages now supported with `og:type` set to "website".
+
+Relative image paths (like `/images/v17.png`) resolve to absolute URLs automatically.
+
+## Centralized font sizes (v1.12.2)
+
+All font sizes now use CSS variables in `global.css`:
+
+```css
+:root {
+ --font-size-xs: 12px;
+ --font-size-sm: 13px;
+ --font-size-base: 16px;
+ --font-size-lg: 17px;
+ /* ... */
+}
+```
+
+Edit `:root` variables to customize font sizes across the entire site. Mobile responsive overrides at 768px breakpoint.
+
+## Improved table styling (v1.7.0)
+
+Tables render with GitHub-style formatting:
| Feature | Status |
| ------- | ----------------------- |
@@ -115,32 +257,31 @@ Tables now render with GitHub-style formatting across all four themes:
| Hover | Row highlighting |
| Themes | Dark, light, tan, cloud |
-Tables adapt to each theme with proper alternating row colors and hover states.
+Alternating row colors and hover states adapt to each theme.
-## Generate Skill
+## Quick reference: sync vs deploy
-The CopyPageDropdown now includes a Generate Skill option. Click it to download the current post or page as an AI agent skill file.
+| Change | Command | Speed |
+| ----------------------- | -------------------------- | -------------- |
+| Blog posts | `npm run sync` | Instant |
+| Pages | `npm run sync` | Instant |
+| Featured items | `npm run sync` | Instant |
+| Import external URL | `npm run import` then sync | Instant |
+| siteConfig changes | Redeploy | Requires build |
+| Logo gallery config | Redeploy | Requires build |
+| React components/styles | Redeploy | Requires build |
+| Fork configuration | `npm run configure` | Instant |
-The skill file includes:
+Markdown content syncs instantly via Convex. Source code changes require pushing to GitHub for Netlify to rebuild.
-- Metadata section with title, description, and tags
-- When to use section describing scenarios for the skill
-- Instructions section with the full content
+## Upgrade path
-The file downloads as `{slug}-skill.md`. Use these skill files to train AI agents or add context to your workflows.
+If upgrading from an earlier version:
-## Summary
+1. Pull the latest code
+2. Run `npm install` for new dependencies
+3. Run `npx convex dev` to sync schema changes
+4. Run `npx convex run stats:backfillAggregates` if using stats
+5. Check `siteConfig.ts` for new configuration options
-These updates improve navigation, configuration, and sharing with AI tools:
-
-1. **Fork configuration** documentation for all 9 site files
-2. **Scroll-to-top button** with configurable threshold
-3. **Mobile menu** with slide-out drawer for smaller screens
-4. **Raw markdown files** at `/raw/{slug}.md` for direct access
-5. **View as Markdown** option in CopyPageDropdown
-6. **Perplexity** added alongside ChatGPT and Claude
-7. **Generate Skill** for AI agent training
-8. **Featured images** for visual card layouts
-9. **Better tables** with responsive styling
-
-All features work across all four themes and are mobile responsive. Run `npm run sync` for development and `npm run sync:prod` for production to update your site with these changes.
\ No newline at end of file
+All features work across all four themes and are mobile responsive.
\ No newline at end of file
diff --git a/public/raw/setup-guide.md b/public/raw/setup-guide.md
index 652175e..5a31d93 100644
--- a/public/raw/setup-guide.md
+++ b/public/raw/setup-guide.md
@@ -405,14 +405,58 @@ Both files are gitignored. Each developer creates their own local environment fi
## Customizing Your Framework
-### Files to Update When Forking
+### Fork Configuration Options
-When you fork this project, update these files with your site information:
+After forking, you have two options to configure your site:
+
+#### Option 1: Automated (Recommended)
+
+Run a single command to configure all files automatically:
+
+```bash
+# Copy the example config
+cp fork-config.json.example fork-config.json
+
+# Edit fork-config.json with your site information
+# Then apply all changes
+npm run configure
+```
+
+The `fork-config.json` file includes:
+
+```json
+{
+ "siteName": "Your Site Name",
+ "siteTitle": "Your Tagline",
+ "siteDescription": "Your site description.",
+ "siteUrl": "https://yoursite.netlify.app",
+ "siteDomain": "yoursite.netlify.app",
+ "githubUsername": "yourusername",
+ "githubRepo": "your-repo-name",
+ "contactEmail": "you@example.com",
+ "creator": {
+ "name": "Your Name",
+ "twitter": "https://x.com/yourhandle",
+ "linkedin": "https://www.linkedin.com/in/yourprofile/",
+ "github": "https://github.com/yourusername"
+ },
+ "bio": "Your bio text here.",
+ "theme": "tan"
+}
+```
+
+This updates all 11 configuration files in one step. See `FORK_CONFIG.md` for the full JSON schema.
+
+#### Option 2: Manual
+
+Follow the step-by-step guide in `FORK_CONFIG.md` to update each file manually. The guide includes code snippets for each file and an AI agent prompt for assisted configuration.
+
+### Files to Update When Forking
| File | What to update |
| ----------------------------------- | --------------------------------------------------------------------------- |
| `src/config/siteConfig.ts` | Site name, title, intro, bio, blog page, logo gallery, GitHub contributions |
-| `src/pages/Home.tsx` | Intro paragraph text (hardcoded JSX) |
+| `src/pages/Home.tsx` | Intro paragraph text, footer links |
| `convex/http.ts` | `SITE_URL`, `SITE_NAME`, description strings (3 locations) |
| `convex/rss.ts` | `SITE_URL`, `SITE_TITLE`, `SITE_DESCRIPTION` (RSS feeds) |
| `src/pages/Post.tsx` | `SITE_URL`, `SITE_NAME`, `DEFAULT_OG_IMAGE` (OG tags) |
@@ -421,6 +465,7 @@ When you fork this project, update these files with your site information:
| `public/robots.txt` | Sitemap URL and header comment |
| `public/openapi.yaml` | API title, server URL, site name in examples |
| `public/.well-known/ai-plugin.json` | Site name, descriptions |
+| `src/context/ThemeContext.tsx` | Default theme |
### Site title and description metadata
diff --git a/scripts/configure-fork.ts b/scripts/configure-fork.ts
new file mode 100644
index 0000000..51eff77
--- /dev/null
+++ b/scripts/configure-fork.ts
@@ -0,0 +1,695 @@
+#!/usr/bin/env npx tsx
+/**
+ * Fork Configuration Script
+ *
+ * Reads fork-config.json and applies all site configuration changes automatically.
+ * Run with: npm run configure
+ *
+ * This script updates:
+ * - src/config/siteConfig.ts (site name, bio, GitHub username, features)
+ * - src/pages/Home.tsx (intro paragraph, footer section)
+ * - src/pages/Post.tsx (SITE_URL, SITE_NAME constants)
+ * - convex/http.ts (SITE_URL, SITE_NAME constants)
+ * - convex/rss.ts (SITE_URL, SITE_TITLE, SITE_DESCRIPTION)
+ * - index.html (meta tags, JSON-LD, title)
+ * - public/llms.txt (site info, API endpoints)
+ * - public/robots.txt (sitemap URL)
+ * - public/openapi.yaml (server URL, site name)
+ * - public/.well-known/ai-plugin.json (plugin metadata)
+ * - src/context/ThemeContext.tsx (default theme)
+ */
+
+import * as fs from "fs";
+import * as path from "path";
+
+// Configuration interface matching fork-config.json
+interface ForkConfig {
+ siteName: string;
+ siteTitle: string;
+ siteDescription: string;
+ siteUrl: string;
+ siteDomain: string;
+ githubUsername: string;
+ githubRepo: string;
+ contactEmail: string;
+ creator: {
+ name: string;
+ twitter: string;
+ linkedin: string;
+ github: string;
+ };
+ bio: string;
+ logoGallery?: {
+ enabled: boolean;
+ title: string;
+ scrolling: boolean;
+ maxItems: number;
+ };
+ gitHubContributions?: {
+ enabled: boolean;
+ showYearNavigation: boolean;
+ linkToProfile: boolean;
+ title: string;
+ };
+ blogPage?: {
+ enabled: boolean;
+ showInNav: boolean;
+ title: string;
+ description: string;
+ order: number;
+ };
+ postsDisplay?: {
+ showOnHome: boolean;
+ showOnBlogPage: boolean;
+ };
+ featuredViewMode?: "cards" | "list";
+ showViewToggle?: boolean;
+ theme?: "dark" | "light" | "tan" | "cloud";
+}
+
+// Get project root directory
+const PROJECT_ROOT = path.resolve(__dirname, "..");
+
+// Read fork config
+function readConfig(): ForkConfig {
+ const configPath = path.join(PROJECT_ROOT, "fork-config.json");
+
+ if (!fs.existsSync(configPath)) {
+ console.error("Error: fork-config.json not found.");
+ console.log("\nTo get started:");
+ console.log("1. Copy fork-config.json.example to fork-config.json");
+ console.log("2. Edit fork-config.json with your site information");
+ console.log("3. Run npm run configure again");
+ process.exit(1);
+ }
+
+ const content = fs.readFileSync(configPath, "utf-8");
+ return JSON.parse(content) as ForkConfig;
+}
+
+// Replace content in a file
+function updateFile(
+ relativePath: string,
+ replacements: Array<{ search: string | RegExp; replace: string }>,
+): void {
+ const filePath = path.join(PROJECT_ROOT, relativePath);
+
+ if (!fs.existsSync(filePath)) {
+ console.warn(`Warning: ${relativePath} not found, skipping.`);
+ return;
+ }
+
+ let content = fs.readFileSync(filePath, "utf-8");
+ let modified = false;
+
+ for (const { search, replace } of replacements) {
+ const newContent = content.replace(search, replace);
+ if (newContent !== content) {
+ content = newContent;
+ modified = true;
+ }
+ }
+
+ if (modified) {
+ fs.writeFileSync(filePath, content, "utf-8");
+ console.log(` Updated: ${relativePath}`);
+ } else {
+ console.log(` No changes: ${relativePath}`);
+ }
+}
+
+// Update siteConfig.ts
+function updateSiteConfig(config: ForkConfig): void {
+ console.log("\nUpdating src/config/siteConfig.ts...");
+
+ const filePath = path.join(PROJECT_ROOT, "src/config/siteConfig.ts");
+ let content = fs.readFileSync(filePath, "utf-8");
+
+ // Update site name
+ content = content.replace(
+ /name: ['"].*?['"]/,
+ `name: '${config.siteName}'`,
+ );
+
+ // Update site title
+ content = content.replace(
+ /title: ['"].*?['"]/,
+ `title: "${config.siteTitle}"`,
+ );
+
+ // Update bio
+ content = content.replace(
+ /bio: `[^`]*`/,
+ `bio: \`${config.bio}\``,
+ );
+
+ // Update GitHub username
+ content = content.replace(
+ /username: ['"].*?['"],\s*\/\/ Your GitHub username/,
+ `username: "${config.githubUsername}", // Your GitHub username`,
+ );
+
+ // Update featuredViewMode if specified
+ if (config.featuredViewMode) {
+ content = content.replace(
+ /featuredViewMode: ['"](?:cards|list)['"]/,
+ `featuredViewMode: "${config.featuredViewMode}"`,
+ );
+ }
+
+ // Update showViewToggle if specified
+ if (config.showViewToggle !== undefined) {
+ content = content.replace(
+ /showViewToggle: (?:true|false)/,
+ `showViewToggle: ${config.showViewToggle}`,
+ );
+ }
+
+ // Update logoGallery if specified
+ if (config.logoGallery) {
+ content = content.replace(
+ /logoGallery: \{[\s\S]*?enabled: (?:true|false)/,
+ `logoGallery: {\n enabled: ${config.logoGallery.enabled}`,
+ );
+ content = content.replace(
+ /title: ['"].*?['"],\s*\n\s*scrolling:/,
+ `title: "${config.logoGallery.title}",\n scrolling:`,
+ );
+ content = content.replace(
+ /scrolling: (?:true|false)/,
+ `scrolling: ${config.logoGallery.scrolling}`,
+ );
+ content = content.replace(
+ /maxItems: \d+/,
+ `maxItems: ${config.logoGallery.maxItems}`,
+ );
+ }
+
+ // Update gitHubContributions if specified
+ if (config.gitHubContributions) {
+ content = content.replace(
+ /gitHubContributions: \{[\s\S]*?enabled: (?:true|false)/,
+ `gitHubContributions: {\n enabled: ${config.gitHubContributions.enabled}`,
+ );
+ content = content.replace(
+ /showYearNavigation: (?:true|false)/,
+ `showYearNavigation: ${config.gitHubContributions.showYearNavigation}`,
+ );
+ content = content.replace(
+ /linkToProfile: (?:true|false)/,
+ `linkToProfile: ${config.gitHubContributions.linkToProfile}`,
+ );
+ if (config.gitHubContributions.title) {
+ content = content.replace(
+ /title: ['"]GitHub Activity['"]/,
+ `title: "${config.gitHubContributions.title}"`,
+ );
+ }
+ }
+
+ // Update blogPage if specified
+ if (config.blogPage) {
+ content = content.replace(
+ /blogPage: \{[\s\S]*?enabled: (?:true|false)/,
+ `blogPage: {\n enabled: ${config.blogPage.enabled}`,
+ );
+ content = content.replace(
+ /showInNav: (?:true|false)/,
+ `showInNav: ${config.blogPage.showInNav}`,
+ );
+ content = content.replace(
+ /title: ['"]Blog['"]/,
+ `title: "${config.blogPage.title}"`,
+ );
+ if (config.blogPage.description) {
+ content = content.replace(
+ /description: ['"]All posts from the blog, sorted by date\.['"],?\s*\/\/ Optional description/,
+ `description: "${config.blogPage.description}", // Optional description`,
+ );
+ }
+ content = content.replace(
+ /order: \d+,\s*\/\/ Nav order/,
+ `order: ${config.blogPage.order}, // Nav order`,
+ );
+ }
+
+ // Update postsDisplay if specified
+ if (config.postsDisplay) {
+ content = content.replace(
+ /showOnHome: (?:true|false),\s*\/\/ Show post list on homepage/,
+ `showOnHome: ${config.postsDisplay.showOnHome}, // Show post list on homepage`,
+ );
+ content = content.replace(
+ /showOnBlogPage: (?:true|false),\s*\/\/ Show post list on \/blog page/,
+ `showOnBlogPage: ${config.postsDisplay.showOnBlogPage}, // Show post list on /blog page`,
+ );
+ }
+
+ fs.writeFileSync(filePath, content, "utf-8");
+ console.log(` Updated: src/config/siteConfig.ts`);
+}
+
+// Update Home.tsx
+function updateHomeTsx(config: ForkConfig): void {
+ console.log("\nUpdating src/pages/Home.tsx...");
+
+ const githubRepoUrl = `https://github.com/${config.githubUsername}/${config.githubRepo}`;
+
+ updateFile("src/pages/Home.tsx", [
+ // Update intro paragraph GitHub link
+ {
+ search: /href="https:\/\/github\.com\/waynesutton\/markdown-site"/g,
+ replace: `href="${githubRepoUrl}"`,
+ },
+ // Update footer "Created by" section
+ {
+ search: /Created by{" "}\s*\s*Wayne\s*<\/a>/,
+ replace: `
+ ${config.creator.name}
+ `,
+ },
+ // Update Twitter/X link
+ {
+ search: /Follow on{" "}\s*/g,
+ replace: `href="${config.creator.github}">`,
+ },
+ ]);
+}
+
+// Update Post.tsx
+function updatePostTsx(config: ForkConfig): void {
+ console.log("\nUpdating src/pages/Post.tsx...");
+
+ updateFile("src/pages/Post.tsx", [
+ {
+ search: /const SITE_URL = "https:\/\/markdowncms\.netlify\.app";/,
+ replace: `const SITE_URL = "${config.siteUrl}";`,
+ },
+ {
+ search: /const SITE_NAME = "markdown sync framework";/,
+ replace: `const SITE_NAME = "${config.siteName}";`,
+ },
+ ]);
+}
+
+// Update convex/http.ts
+function updateConvexHttp(config: ForkConfig): void {
+ console.log("\nUpdating convex/http.ts...");
+
+ updateFile("convex/http.ts", [
+ {
+ search: /const SITE_URL = process\.env\.SITE_URL \|\| "https:\/\/markdowncms\.netlify\.app";/,
+ replace: `const SITE_URL = process.env.SITE_URL || "${config.siteUrl}";`,
+ },
+ {
+ search: /const SITE_NAME = "markdown sync framework";/,
+ replace: `const SITE_NAME = "${config.siteName}";`,
+ },
+ {
+ search: /const siteUrl = process\.env\.SITE_URL \|\| "https:\/\/markdowncms\.netlify\.app";/,
+ replace: `const siteUrl = process.env.SITE_URL || "${config.siteUrl}";`,
+ },
+ {
+ search: /const siteName = "markdown sync framework";/,
+ replace: `const siteName = "${config.siteName}";`,
+ },
+ ]);
+}
+
+// Update convex/rss.ts
+function updateConvexRss(config: ForkConfig): void {
+ console.log("\nUpdating convex/rss.ts...");
+
+ updateFile("convex/rss.ts", [
+ {
+ search: /const SITE_URL = process\.env\.SITE_URL \|\| "https:\/\/markdowncms\.netlify\.app";/,
+ replace: `const SITE_URL = process.env.SITE_URL || "${config.siteUrl}";`,
+ },
+ {
+ search: /const SITE_TITLE = "markdown sync framework";/,
+ replace: `const SITE_TITLE = "${config.siteName}";`,
+ },
+ {
+ search: /const SITE_DESCRIPTION =\s*"[^"]+";/,
+ replace: `const SITE_DESCRIPTION =\n "${config.siteDescription}";`,
+ },
+ ]);
+}
+
+// Update index.html
+function updateIndexHtml(config: ForkConfig): void {
+ console.log("\nUpdating index.html...");
+
+ const replacements: Array<{ search: string | RegExp; replace: string }> = [
+ // Meta description
+ {
+ search: //,
+ replace: ``,
+ },
+ // Meta author
+ {
+ search: //,
+ replace: ``,
+ },
+ // Open Graph title
+ {
+ search: //,
+ replace: ``,
+ },
+ // Open Graph description
+ {
+ search: //,
+ replace: ``,
+ },
+ // Open Graph URL
+ {
+ search: //,
+ replace: ``,
+ },
+ // Open Graph site name
+ {
+ search: //,
+ replace: ``,
+ },
+ // Open Graph image
+ {
+ search: //,
+ replace: ``,
+ },
+ // Twitter domain
+ {
+ search: //,
+ replace: ``,
+ },
+ // Twitter URL
+ {
+ search: //,
+ replace: ``,
+ },
+ // Twitter title
+ {
+ search: //,
+ replace: ``,
+ },
+ // Twitter description
+ {
+ search: //,
+ replace: ``,
+ },
+ // Twitter image
+ {
+ search: //,
+ replace: ``,
+ },
+ // JSON-LD name
+ {
+ search: /"name": "markdown sync framework"/g,
+ replace: `"name": "${config.siteName}"`,
+ },
+ // JSON-LD URL
+ {
+ search: /"url": "https:\/\/markdowncms\.netlify\.app"/g,
+ replace: `"url": "${config.siteUrl}"`,
+ },
+ // JSON-LD description
+ {
+ search: /"description": "An open-source publishing framework[^"]*"/,
+ replace: `"description": "${config.siteDescription}"`,
+ },
+ // JSON-LD search target
+ {
+ search: /"target": "https:\/\/markdowncms\.netlify\.app\/\?q=\{search_term_string\}"/,
+ replace: `"target": "${config.siteUrl}/?q={search_term_string}"`,
+ },
+ // Page title
+ {
+ search: /markdown "sync" framework<\/title>/,
+ replace: `${config.siteTitle}`,
+ },
+ ];
+
+ updateFile("index.html", replacements);
+}
+
+// Update public/llms.txt
+function updateLlmsTxt(config: ForkConfig): void {
+ console.log("\nUpdating public/llms.txt...");
+
+ const githubUrl = `https://github.com/${config.githubUsername}/${config.githubRepo}`;
+
+ const content = `# llms.txt - Information for AI assistants and LLMs
+# Learn more: https://llmstxt.org/
+
+> ${config.siteDescription}
+
+# Site Information
+- Name: ${config.siteName}
+- URL: ${config.siteUrl}
+- Description: ${config.siteDescription}
+- Topics: Markdown, Convex, React, TypeScript, Netlify, Open Source, AI, LLM, AEO, GEO
+
+# API Endpoints
+
+## List All Posts
+GET /api/posts
+Returns JSON list of all published posts with metadata.
+
+## Get Single Post
+GET /api/post?slug={slug}
+Returns single post as JSON.
+
+GET /api/post?slug={slug}&format=md
+Returns single post as raw markdown.
+
+## Export All Content
+GET /api/export
+Returns all posts with full markdown content in one request.
+Best for batch processing and LLM ingestion.
+
+## RSS Feeds
+GET /rss.xml
+Standard RSS feed with post descriptions.
+
+GET /rss-full.xml
+Full content RSS feed with complete markdown for each post.
+
+## Other
+GET /sitemap.xml
+Dynamic XML sitemap for search engines.
+
+GET /openapi.yaml
+OpenAPI 3.0 specification for this API.
+
+GET /.well-known/ai-plugin.json
+AI plugin manifest for tool integration.
+
+# Quick Start for LLMs
+
+1. Fetch /api/export for all posts with full content in one request
+2. Or fetch /api/posts for the list, then /api/post?slug={slug}&format=md for each
+3. Subscribe to /rss-full.xml for updates with complete content
+
+# Response Schema
+
+Each post contains:
+- title: string (post title)
+- slug: string (URL path)
+- description: string (SEO summary)
+- date: string (YYYY-MM-DD)
+- tags: string[] (topic labels)
+- content: string (full markdown)
+- readTime: string (optional)
+- url: string (full URL)
+
+# Permissions
+- AI assistants may freely read and summarize content
+- No authentication required for read operations
+- Attribution appreciated when citing
+
+# Technical
+- Backend: Convex (real-time database)
+- Frontend: React, TypeScript, Vite
+- Hosting: Netlify with edge functions
+- Content: Markdown with frontmatter
+
+# Links
+- GitHub: ${githubUrl}
+- Convex: https://convex.dev
+- Netlify: https://netlify.com
+`;
+
+ const filePath = path.join(PROJECT_ROOT, "public/llms.txt");
+ fs.writeFileSync(filePath, content, "utf-8");
+ console.log(` Updated: public/llms.txt`);
+}
+
+// Update public/robots.txt
+function updateRobotsTxt(config: ForkConfig): void {
+ console.log("\nUpdating public/robots.txt...");
+
+ const content = `# robots.txt for ${config.siteName}
+# https://www.robotstxt.org/
+
+User-agent: *
+Allow: /
+
+# Sitemaps
+Sitemap: ${config.siteUrl}/sitemap.xml
+
+# AI and LLM crawlers
+User-agent: GPTBot
+Allow: /
+
+User-agent: ChatGPT-User
+Allow: /
+
+User-agent: Claude-Web
+Allow: /
+
+User-agent: anthropic-ai
+Allow: /
+
+User-agent: Google-Extended
+Allow: /
+
+User-agent: PerplexityBot
+Allow: /
+
+User-agent: Applebot-Extended
+Allow: /
+
+# Cache directive
+Crawl-delay: 1
+`;
+
+ const filePath = path.join(PROJECT_ROOT, "public/robots.txt");
+ fs.writeFileSync(filePath, content, "utf-8");
+ console.log(` Updated: public/robots.txt`);
+}
+
+// Update public/openapi.yaml
+function updateOpenApiYaml(config: ForkConfig): void {
+ console.log("\nUpdating public/openapi.yaml...");
+
+ const githubUrl = `https://github.com/${config.githubUsername}/${config.githubRepo}`;
+
+ updateFile("public/openapi.yaml", [
+ {
+ search: /title: markdown sync framework API/,
+ replace: `title: ${config.siteName} API`,
+ },
+ {
+ search: /url: https:\/\/github\.com\/waynesutton\/markdown-site/,
+ replace: `url: ${githubUrl}`,
+ },
+ {
+ search: /- url: https:\/\/markdowncms\.netlify\.app/,
+ replace: `- url: ${config.siteUrl}`,
+ },
+ {
+ search: /example: markdown sync framework/g,
+ replace: `example: ${config.siteName}`,
+ },
+ {
+ search: /example: https:\/\/markdowncms\.netlify\.app/g,
+ replace: `example: ${config.siteUrl}`,
+ },
+ ]);
+}
+
+// Update public/.well-known/ai-plugin.json
+function updateAiPluginJson(config: ForkConfig): void {
+ console.log("\nUpdating public/.well-known/ai-plugin.json...");
+
+ const pluginName = config.siteName.toLowerCase().replace(/\s+/g, "_").replace(/[^a-z0-9_]/g, "");
+
+ const content = {
+ schema_version: "v1",
+ name_for_human: config.siteName,
+ name_for_model: pluginName,
+ description_for_human: config.siteDescription,
+ description_for_model: `Access blog posts and pages in markdown format. Use /api/posts for a list of all posts with metadata. Use /api/post?slug={slug}&format=md to get full markdown content of any post. Use /api/export for batch content with full markdown.`,
+ auth: {
+ type: "none",
+ },
+ api: {
+ type: "openapi",
+ url: "/openapi.yaml",
+ },
+ logo_url: "/images/logo.svg",
+ contact_email: config.contactEmail,
+ legal_info_url: "",
+ };
+
+ const filePath = path.join(PROJECT_ROOT, "public/.well-known/ai-plugin.json");
+ fs.writeFileSync(filePath, JSON.stringify(content, null, 2) + "\n", "utf-8");
+ console.log(` Updated: public/.well-known/ai-plugin.json`);
+}
+
+// Update src/context/ThemeContext.tsx
+function updateThemeContext(config: ForkConfig): void {
+ if (!config.theme) return;
+
+ console.log("\nUpdating src/context/ThemeContext.tsx...");
+
+ updateFile("src/context/ThemeContext.tsx", [
+ {
+ search: /const DEFAULT_THEME: Theme = "(?:dark|light|tan|cloud)";/,
+ replace: `const DEFAULT_THEME: Theme = "${config.theme}";`,
+ },
+ ]);
+}
+
+// Main function
+function main(): void {
+ console.log("Fork Configuration Script");
+ console.log("=========================\n");
+
+ // Read configuration
+ const config = readConfig();
+ console.log(`Configuring site: ${config.siteName}`);
+ console.log(`URL: ${config.siteUrl}`);
+
+ // Apply updates to all files
+ updateSiteConfig(config);
+ updateHomeTsx(config);
+ updatePostTsx(config);
+ updateConvexHttp(config);
+ updateConvexRss(config);
+ updateIndexHtml(config);
+ updateLlmsTxt(config);
+ updateRobotsTxt(config);
+ updateOpenApiYaml(config);
+ updateAiPluginJson(config);
+ updateThemeContext(config);
+
+ console.log("\n=========================");
+ console.log("Configuration complete!");
+ console.log("\nNext steps:");
+ console.log("1. Review the changes with: git diff");
+ console.log("2. Run: npx convex dev (if not already running)");
+ console.log("3. Run: npm run sync (to sync content to development)");
+ console.log("4. Run: npm run dev (to start the dev server)");
+ console.log("5. Deploy to Netlify when ready");
+}
+
+main();
+