mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-11 20:08:57 +00:00
feat(fork-config): add automated fork configuration with npm run configure
Add a complete fork configuration system that allows users to set up their forked site with a single command or follow manual instructions. ## New files - FORK_CONFIG.md: Comprehensive guide with two setup options - Option 1: Automated JSON config + npm run configure - Option 2: Manual step-by-step instructions with code snippets - AI agent prompt for automated updates - fork-config.json.example: JSON template with all configuration fields - Site info (name, title, description, URL, domain) - GitHub and contact details - Creator section for footer links - Optional feature toggles (logo gallery, GitHub graph, blog page) - Theme selection - scripts/configure-fork.ts: Automated configuration script - Reads fork-config.json and applies changes to all files - Updates 11 configuration files in one command - Type-safe with ForkConfig interface - Detailed console output showing each file updated ## Updated files - package.json: Added configure script (npm run configure) - .gitignore: Added fork-config.json to keep user config local - files.md: Added new fork configuration files - changelog.md: Added v1.18.0 entry - changelog-page.md: Added v1.18.0 section with full details - TASK.md: Updated status and completed tasks - README.md: Replaced Files to Update section with Fork Configuration - content/blog/setup-guide.md: Added Fork Configuration Options section - content/pages/docs.md: Added Fork Configuration section - content/pages/about.md: Added fork configuration mention - content/blog/fork-configuration-guide.md: New featured blog post ## Files updated by configure script | 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 | ## Usage Automated: cp fork-config.json.example fork-config.json # Edit fork-config.json npm run configure Manual: Follow FORK_CONFIG.md step-by-step guide
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -28,6 +28,9 @@ dist-ssr
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Fork configuration (user-specific)
|
||||
fork-config.json
|
||||
|
||||
# Cursor rules
|
||||
.cursor/rules/write.mdc
|
||||
|
||||
|
||||
443
FORK_CONFIG.md
Normal file
443
FORK_CONFIG.md
Normal file
@@ -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
|
||||
<p className="home-intro">
|
||||
YOUR SITE DESCRIPTION HERE.{" "}
|
||||
<a
|
||||
href="https://github.com/YOURUSERNAME/YOUR-REPO"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="home-text-link"
|
||||
>
|
||||
Fork it
|
||||
</a>
|
||||
, customize it, ship it.
|
||||
</p>
|
||||
```
|
||||
|
||||
Update the footer section (lines 203-271):
|
||||
|
||||
```tsx
|
||||
<section className="home-footer">
|
||||
<p className="home-footer-text">
|
||||
Built with{" "}
|
||||
<a href={siteConfig.links.convex} target="_blank" rel="noopener noreferrer">
|
||||
Convex
|
||||
</a>{" "}
|
||||
for real-time sync and deployed on{" "}
|
||||
<a
|
||||
href={siteConfig.links.netlify}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Netlify
|
||||
</a>
|
||||
. Read the{" "}
|
||||
<a
|
||||
href="https://github.com/YOURUSERNAME/YOUR-REPO"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
project on GitHub
|
||||
</a>{" "}
|
||||
to fork and deploy your own. View{" "}
|
||||
<a href="/stats" className="home-text-link">
|
||||
real-time site stats
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p></p>
|
||||
<br></br>
|
||||
<p className="home-footer-text">
|
||||
Created by{" "}
|
||||
<a
|
||||
href="https://x.com/YOURHANDLE"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
YOUR NAME
|
||||
</a>{" "}
|
||||
with Convex, Cursor, and Claude. Follow on{" "}
|
||||
<a
|
||||
href="https://x.com/YOURHANDLE"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Twitter/X
|
||||
</a>
|
||||
,{" "}
|
||||
<a
|
||||
href="https://www.linkedin.com/in/YOURPROFILE/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
LinkedIn
|
||||
</a>
|
||||
, and{" "}
|
||||
<a
|
||||
href="https://github.com/YOURUSERNAME"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</section>
|
||||
```
|
||||
|
||||
### 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
|
||||
<!-- SEO Meta Tags -->
|
||||
<meta name="description" content="YOUR SITE DESCRIPTION" />
|
||||
<meta name="author" content="YOUR SITE NAME" />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:title" content="YOUR SITE NAME" />
|
||||
<meta property="og:description" content="YOUR SITE DESCRIPTION" />
|
||||
<meta property="og:url" content="https://YOURSITE.netlify.app/" />
|
||||
<meta property="og:site_name" content="YOUR SITE NAME" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://YOURSITE.netlify.app/images/og-default.svg"
|
||||
/>
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta property="twitter:domain" content="YOURSITE.netlify.app" />
|
||||
<meta property="twitter:url" content="https://YOURSITE.netlify.app/" />
|
||||
<meta name="twitter:title" content="YOUR SITE NAME" />
|
||||
<meta name="twitter:description" content="YOUR SITE DESCRIPTION" />
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://YOURSITE.netlify.app/images/og-default.svg"
|
||||
/>
|
||||
|
||||
<!-- JSON-LD -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"name": "YOUR SITE NAME",
|
||||
"url": "https://YOURSITE.netlify.app",
|
||||
"description": "YOUR SITE DESCRIPTION"
|
||||
}
|
||||
</script>
|
||||
|
||||
<title>YOUR SITE TITLE</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 |
|
||||
62
README.md
62
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 <url>` 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
|
||||
|
||||
9
TASK.md
9
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
|
||||
|
||||
31
changelog.md
31
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
|
||||
|
||||
172
content/blog/fork-configuration-guide.md
Normal file
172
content/blog/fork-configuration-guide.md
Normal file
@@ -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.
|
||||
@@ -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"
|
||||
---
|
||||
|
||||
@@ -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<ScrollToTopConfig> = {
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
35
files.md
35
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/`)
|
||||
|
||||
|
||||
44
fork-config.json.example
Normal file
44
fork-config.json.example
Normal file
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
BIN
public/images/forkconfig.png
Normal file
BIN
public/images/forkconfig.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
169
public/raw/fork-configuration-guide.md
Normal file
169
public/raw/fork-configuration-guide.md
Normal file
@@ -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.
|
||||
@@ -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<ScrollToTopConfig> = {
|
||||
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.
|
||||
All features work across all four themes and are mobile responsive.
|
||||
@@ -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
|
||||
|
||||
|
||||
695
scripts/configure-fork.ts
Normal file
695
scripts/configure-fork.ts
Normal file
@@ -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*<a\s*href="https:\/\/x\.com\/waynesutton"/,
|
||||
replace: `Created by{" "}\n <a\n href="${config.creator.twitter}"`,
|
||||
},
|
||||
{
|
||||
search: /<a\s*href="https:\/\/x\.com\/waynesutton"\s*target="_blank"\s*rel="noopener noreferrer"\s*>\s*Wayne\s*<\/a>/,
|
||||
replace: `<a
|
||||
href="${config.creator.twitter}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
${config.creator.name}
|
||||
</a>`,
|
||||
},
|
||||
// Update Twitter/X link
|
||||
{
|
||||
search: /Follow on{" "}\s*<a\s*href="https:\/\/x\.com\/waynesutton"/,
|
||||
replace: `Follow on{" "}\n <a\n href="${config.creator.twitter}"`,
|
||||
},
|
||||
// Update LinkedIn link
|
||||
{
|
||||
search: /href="https:\/\/www\.linkedin\.com\/in\/waynesutton\/"/g,
|
||||
replace: `href="${config.creator.linkedin}"`,
|
||||
},
|
||||
// Update GitHub profile link
|
||||
{
|
||||
search: /href="https:\/\/github\.com\/waynesutton"\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: /<meta\s*name="description"\s*content="[^"]*"\s*\/>/,
|
||||
replace: `<meta\n name="description"\n content="${config.siteDescription}"\n />`,
|
||||
},
|
||||
// Meta author
|
||||
{
|
||||
search: /<meta name="author" content="[^"]*" \/>/,
|
||||
replace: `<meta name="author" content="${config.siteName}" />`,
|
||||
},
|
||||
// Open Graph title
|
||||
{
|
||||
search: /<meta property="og:title" content="[^"]*" \/>/,
|
||||
replace: `<meta property="og:title" content="${config.siteName}" />`,
|
||||
},
|
||||
// Open Graph description
|
||||
{
|
||||
search: /<meta\s*property="og:description"\s*content="[^"]*"\s*\/>/,
|
||||
replace: `<meta\n property="og:description"\n content="${config.siteDescription}"\n />`,
|
||||
},
|
||||
// Open Graph URL
|
||||
{
|
||||
search: /<meta property="og:url" content="https:\/\/markdowncms\.netlify\.app\/" \/>/,
|
||||
replace: `<meta property="og:url" content="${config.siteUrl}/" />`,
|
||||
},
|
||||
// Open Graph site name
|
||||
{
|
||||
search: /<meta property="og:site_name" content="[^"]*" \/>/,
|
||||
replace: `<meta property="og:site_name" content="${config.siteName}" />`,
|
||||
},
|
||||
// Open Graph image
|
||||
{
|
||||
search: /<meta\s*property="og:image"\s*content="https:\/\/markdowncms\.netlify\.app[^"]*"\s*\/>/,
|
||||
replace: `<meta\n property="og:image"\n content="${config.siteUrl}/images/og-default.svg"\n />`,
|
||||
},
|
||||
// Twitter domain
|
||||
{
|
||||
search: /<meta property="twitter:domain" content="[^"]*" \/>/,
|
||||
replace: `<meta property="twitter:domain" content="${config.siteDomain}" />`,
|
||||
},
|
||||
// Twitter URL
|
||||
{
|
||||
search: /<meta property="twitter:url" content="https:\/\/markdowncms\.netlify\.app\/" \/>/,
|
||||
replace: `<meta property="twitter:url" content="${config.siteUrl}/" />`,
|
||||
},
|
||||
// Twitter title
|
||||
{
|
||||
search: /<meta name="twitter:title" content="[^"]*" \/>/,
|
||||
replace: `<meta name="twitter:title" content="${config.siteName}" />`,
|
||||
},
|
||||
// Twitter description
|
||||
{
|
||||
search: /<meta\s*name="twitter:description"\s*content="[^"]*"\s*\/>/,
|
||||
replace: `<meta\n name="twitter:description"\n content="${config.siteDescription}"\n />`,
|
||||
},
|
||||
// Twitter image
|
||||
{
|
||||
search: /<meta\s*name="twitter:image"\s*content="https:\/\/markdowncms\.netlify\.app[^"]*"\s*\/>/,
|
||||
replace: `<meta\n name="twitter:image"\n content="${config.siteUrl}/images/og-default.svg"\n />`,
|
||||
},
|
||||
// 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: /<title>markdown "sync" framework<\/title>/,
|
||||
replace: `<title>${config.siteTitle}</title>`,
|
||||
},
|
||||
];
|
||||
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user