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 +
+

+ Built with{" "} + + Convex + {" "} + for real-time sync and deployed on{" "} + + Netlify + + . Read the{" "} + + project on GitHub + {" "} + to fork and deploy your own. View{" "} + + real-time site stats + + . +

+

+

+

+ Created by{" "} + + YOUR NAME + {" "} + with Convex, Cursor, and Claude. Follow on{" "} + + Twitter/X + + ,{" "} + + LinkedIn + + , and{" "} + + GitHub + + . +

+
+``` + +### 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: `<title>${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(); +