mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 04:09:14 +00:00
feat: add CLAUDE.md and skills documentation
Created CLAUDE.md for Claude Code instructions and .claude/skills/ directory with frontmatter, convex, and sync skill files. Updated sync-discovery-files.ts to auto-update CLAUDE.md during sync.
This commit is contained in:
199
.claude/skills/convex.md
Normal file
199
.claude/skills/convex.md
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# Convex skill
|
||||||
|
|
||||||
|
Convex patterns and conventions for this markdown-blog project.
|
||||||
|
|
||||||
|
## Function structure
|
||||||
|
|
||||||
|
Every Convex function needs argument and return validators:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { query } from "./_generated/server";
|
||||||
|
import { v } from "convex/values";
|
||||||
|
|
||||||
|
export const myQuery = query({
|
||||||
|
args: { slug: v.string() },
|
||||||
|
returns: v.union(v.object({...}), v.null()),
|
||||||
|
handler: async (ctx, args) => {
|
||||||
|
// implementation
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If a function returns nothing, use `returns: v.null()` and `return null;`.
|
||||||
|
|
||||||
|
## Always use indexes
|
||||||
|
|
||||||
|
Never use `.filter()` on queries. Define indexes in schema and use `.withIndex()`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Good
|
||||||
|
const post = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.withIndex("by_slug", (q) => q.eq("slug", args.slug))
|
||||||
|
.first();
|
||||||
|
|
||||||
|
// Bad - causes table scans
|
||||||
|
const post = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.filter((q) => q.eq(q.field("slug"), args.slug))
|
||||||
|
.first();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Make mutations idempotent
|
||||||
|
|
||||||
|
Mutations should be safe to call multiple times:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const heartbeat = mutation({
|
||||||
|
args: { sessionId: v.string(), currentPath: v.string() },
|
||||||
|
returns: v.null(),
|
||||||
|
handler: async (ctx, args) => {
|
||||||
|
const now = Date.now();
|
||||||
|
const existing = await ctx.db
|
||||||
|
.query("activeSessions")
|
||||||
|
.withIndex("by_sessionId", (q) => q.eq("sessionId", args.sessionId))
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
// Early return if recently updated with same data
|
||||||
|
if (existing.currentPath === args.currentPath &&
|
||||||
|
now - existing.lastSeen < 10000) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
await ctx.db.patch(existing._id, {
|
||||||
|
currentPath: args.currentPath,
|
||||||
|
lastSeen: now
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ctx.db.insert("activeSessions", { ...args, lastSeen: now });
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Patch directly without reading
|
||||||
|
|
||||||
|
When you only need to update fields, patch directly:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Good - patch directly
|
||||||
|
await ctx.db.patch(args.id, { content: args.content });
|
||||||
|
|
||||||
|
// Bad - unnecessary read creates conflict window
|
||||||
|
const doc = await ctx.db.get(args.id);
|
||||||
|
if (!doc) throw new Error("Not found");
|
||||||
|
await ctx.db.patch(args.id, { content: args.content });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use event records for counters
|
||||||
|
|
||||||
|
Never increment counters on documents. Use separate event records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Good - insert event record
|
||||||
|
await ctx.db.insert("pageViews", {
|
||||||
|
path,
|
||||||
|
sessionId,
|
||||||
|
timestamp: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bad - counter updates cause write conflicts
|
||||||
|
await ctx.db.patch(pageId, { views: page.views + 1 });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schema indexes in this project
|
||||||
|
|
||||||
|
Key indexes defined in `convex/schema.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
posts: defineTable({...})
|
||||||
|
.index("by_slug", ["slug"])
|
||||||
|
.index("by_published", ["published"])
|
||||||
|
.index("by_featured", ["featured"])
|
||||||
|
.searchIndex("search_title", { searchField: "title" })
|
||||||
|
.searchIndex("search_content", { searchField: "content" })
|
||||||
|
|
||||||
|
pages: defineTable({...})
|
||||||
|
.index("by_slug", ["slug"])
|
||||||
|
.index("by_published", ["published"])
|
||||||
|
.index("by_featured", ["featured"])
|
||||||
|
|
||||||
|
pageViews: defineTable({...})
|
||||||
|
.index("by_path", ["path"])
|
||||||
|
.index("by_timestamp", ["timestamp"])
|
||||||
|
.index("by_session_path", ["sessionId", "path"])
|
||||||
|
|
||||||
|
activeSessions: defineTable({...})
|
||||||
|
.index("by_sessionId", ["sessionId"])
|
||||||
|
.index("by_lastSeen", ["lastSeen"])
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common query patterns
|
||||||
|
|
||||||
|
### Get post by slug
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const post = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.withIndex("by_slug", (q) => q.eq("slug", args.slug))
|
||||||
|
.first();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get all published posts
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const posts = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.withIndex("by_published", (q) => q.eq("published", true))
|
||||||
|
.order("desc")
|
||||||
|
.collect();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get featured items
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const featured = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.withIndex("by_featured", (q) => q.eq("featured", true))
|
||||||
|
.collect();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full text search
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const results = await ctx.db
|
||||||
|
.query("posts")
|
||||||
|
.withSearchIndex("search_content", (q) => q.search("content", searchTerm))
|
||||||
|
.take(10);
|
||||||
|
```
|
||||||
|
|
||||||
|
## File locations
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `convex/schema.ts` | Database schema and indexes |
|
||||||
|
| `convex/posts.ts` | Post queries/mutations |
|
||||||
|
| `convex/pages.ts` | Page queries/mutations |
|
||||||
|
| `convex/stats.ts` | Analytics (heartbeat, pageViews) |
|
||||||
|
| `convex/search.ts` | Full text search |
|
||||||
|
| `convex/http.ts` | HTTP endpoints |
|
||||||
|
| `convex/rss.ts` | RSS feed generation |
|
||||||
|
| `convex/crons.ts` | Scheduled jobs |
|
||||||
|
|
||||||
|
## Write conflict prevention
|
||||||
|
|
||||||
|
This project uses specific patterns to avoid write conflicts:
|
||||||
|
|
||||||
|
**Backend (convex/stats.ts):**
|
||||||
|
- 10-second dedup window for heartbeats
|
||||||
|
- Early return when session was recently updated
|
||||||
|
- Indexed queries for efficient lookups
|
||||||
|
|
||||||
|
**Frontend (src/hooks/usePageTracking.ts):**
|
||||||
|
- 5-second debounce window using refs
|
||||||
|
- Pending state tracking prevents overlapping calls
|
||||||
|
- Path tracking skips redundant heartbeats
|
||||||
|
|
||||||
|
See `prds/howtoavoidwriteconflicts.md` for full documentation.
|
||||||
166
.claude/skills/frontmatter.md
Normal file
166
.claude/skills/frontmatter.md
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
# Frontmatter skill
|
||||||
|
|
||||||
|
How to write frontmatter for markdown-blog posts and pages.
|
||||||
|
|
||||||
|
## Blog post frontmatter
|
||||||
|
|
||||||
|
Location: `content/blog/*.md`
|
||||||
|
|
||||||
|
### Required fields
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| title | string | Post title |
|
||||||
|
| description | string | SEO description |
|
||||||
|
| date | string | YYYY-MM-DD format |
|
||||||
|
| slug | string | URL path (must be unique) |
|
||||||
|
| published | boolean | true to show publicly |
|
||||||
|
| tags | string[] | Array of topic tags |
|
||||||
|
|
||||||
|
### Optional fields
|
||||||
|
|
||||||
|
| Field | Type | Default | Description |
|
||||||
|
|-------|------|---------|-------------|
|
||||||
|
| featured | boolean | false | Show in featured section |
|
||||||
|
| featuredOrder | number | - | Display order (lower = first) |
|
||||||
|
| image | string | - | OG/header image path |
|
||||||
|
| showImageAtTop | boolean | false | Display image at top of post |
|
||||||
|
| excerpt | string | - | Short text for card view |
|
||||||
|
| readTime | string | auto | Reading time (auto-calculated if omitted) |
|
||||||
|
| authorName | string | - | Author display name |
|
||||||
|
| authorImage | string | - | Author avatar URL (round) |
|
||||||
|
| layout | string | - | "sidebar" for docs-style layout |
|
||||||
|
| rightSidebar | boolean | true | Show right sidebar |
|
||||||
|
| aiChat | boolean | false | Enable AI chat in sidebar |
|
||||||
|
| blogFeatured | boolean | false | Hero featured on /blog page |
|
||||||
|
| newsletter | boolean | - | Override newsletter signup |
|
||||||
|
| contactForm | boolean | false | Enable contact form |
|
||||||
|
| showFooter | boolean | - | Override footer display |
|
||||||
|
| footer | string | - | Custom footer markdown |
|
||||||
|
| showSocialFooter | boolean | - | Override social footer |
|
||||||
|
|
||||||
|
### Example blog post
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: "How to write a blog post"
|
||||||
|
description: "A guide to writing posts with frontmatter"
|
||||||
|
date: "2025-01-15"
|
||||||
|
slug: "how-to-write-a-blog-post"
|
||||||
|
published: true
|
||||||
|
tags: ["tutorial", "markdown"]
|
||||||
|
featured: true
|
||||||
|
featuredOrder: 1
|
||||||
|
image: "/images/my-post.png"
|
||||||
|
excerpt: "Learn how to create blog posts"
|
||||||
|
authorName: "Your Name"
|
||||||
|
authorImage: "/images/authors/you.png"
|
||||||
|
---
|
||||||
|
|
||||||
|
Your content here...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Page frontmatter
|
||||||
|
|
||||||
|
Location: `content/pages/*.md`
|
||||||
|
|
||||||
|
### Required fields
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| title | string | Page title |
|
||||||
|
| slug | string | URL path (must be unique) |
|
||||||
|
| published | boolean | true to show publicly |
|
||||||
|
|
||||||
|
### Optional fields
|
||||||
|
|
||||||
|
| Field | Type | Default | Description |
|
||||||
|
|-------|------|---------|-------------|
|
||||||
|
| order | number | - | Nav order (lower = first) |
|
||||||
|
| showInNav | boolean | true | Show in navigation menu |
|
||||||
|
| featured | boolean | false | Show in featured section |
|
||||||
|
| featuredOrder | number | - | Display order (lower = first) |
|
||||||
|
| image | string | - | Thumbnail/OG image for cards |
|
||||||
|
| showImageAtTop | boolean | false | Display image at top |
|
||||||
|
| excerpt | string | - | Short text for card view |
|
||||||
|
| authorName | string | - | Author display name |
|
||||||
|
| authorImage | string | - | Author avatar URL |
|
||||||
|
| layout | string | - | "sidebar" for docs-style |
|
||||||
|
| rightSidebar | boolean | true | Show right sidebar |
|
||||||
|
| aiChat | boolean | false | Enable AI chat |
|
||||||
|
| contactForm | boolean | false | Enable contact form |
|
||||||
|
| newsletter | boolean | - | Override newsletter signup |
|
||||||
|
| textAlign | string | "left" | "left", "center", "right" |
|
||||||
|
| showFooter | boolean | - | Override footer display |
|
||||||
|
| footer | string | - | Custom footer markdown |
|
||||||
|
| showSocialFooter | boolean | - | Override social footer |
|
||||||
|
|
||||||
|
### Example page
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: "About"
|
||||||
|
slug: "about"
|
||||||
|
published: true
|
||||||
|
order: 1
|
||||||
|
showInNav: true
|
||||||
|
featured: true
|
||||||
|
featuredOrder: 2
|
||||||
|
excerpt: "Learn about this site"
|
||||||
|
---
|
||||||
|
|
||||||
|
Page content here...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common patterns
|
||||||
|
|
||||||
|
### Featured post on homepage
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
featured: true
|
||||||
|
featuredOrder: 1 # Lower numbers appear first
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hero post on /blog page
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
blogFeatured: true
|
||||||
|
image: "/images/hero.png"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docs-style page with sidebar
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
layout: "sidebar"
|
||||||
|
rightSidebar: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hide from navigation
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
showInNav: false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enable contact form
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
contactForm: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom footer content
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
showFooter: true
|
||||||
|
footer: "Custom footer text in **markdown**"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
The sync script validates:
|
||||||
|
|
||||||
|
- Required fields must be present
|
||||||
|
- `slug` must be unique across all posts/pages
|
||||||
|
- `date` should be YYYY-MM-DD format
|
||||||
|
- `published` must be boolean
|
||||||
|
|
||||||
|
Missing required fields will cause the file to be skipped with a warning.
|
||||||
136
.claude/skills/sync.md
Normal file
136
.claude/skills/sync.md
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# Sync skill
|
||||||
|
|
||||||
|
How the content sync system works in this markdown-blog project.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Content flows from markdown files to Convex database via sync scripts. Changes appear instantly on the site because Convex provides real-time updates.
|
||||||
|
|
||||||
|
```
|
||||||
|
content/blog/*.md ──┐
|
||||||
|
├──▶ npm run sync ──▶ Convex DB ──▶ Site
|
||||||
|
content/pages/*.md ──┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sync commands
|
||||||
|
|
||||||
|
| Command | Environment | What it syncs |
|
||||||
|
|---------|-------------|---------------|
|
||||||
|
| `npm run sync` | Development | Posts + pages to dev Convex |
|
||||||
|
| `npm run sync:prod` | Production | Posts + pages to prod Convex |
|
||||||
|
| `npm run sync:discovery` | Development | AGENTS.md + llms.txt |
|
||||||
|
| `npm run sync:discovery:prod` | Production | AGENTS.md + llms.txt |
|
||||||
|
| `npm run sync:all` | Development | Everything |
|
||||||
|
| `npm run sync:all:prod` | Production | Everything |
|
||||||
|
|
||||||
|
## How sync works
|
||||||
|
|
||||||
|
### Content sync (sync-posts.ts)
|
||||||
|
|
||||||
|
1. Reads all `.md` files from `content/blog/` and `content/pages/`
|
||||||
|
2. Parses frontmatter with `gray-matter`
|
||||||
|
3. Validates required fields (title, slug, etc.)
|
||||||
|
4. Calculates reading time if not provided
|
||||||
|
5. Calls Convex mutations to upsert content
|
||||||
|
6. Generates raw markdown files in `public/raw/`
|
||||||
|
|
||||||
|
### Discovery sync (sync-discovery-files.ts)
|
||||||
|
|
||||||
|
1. Reads site configuration from `src/config/siteConfig.ts`
|
||||||
|
2. Queries Convex for post/page counts
|
||||||
|
3. Updates `AGENTS.md` with current status
|
||||||
|
4. Generates `public/llms.txt` with API info
|
||||||
|
|
||||||
|
## File locations
|
||||||
|
|
||||||
|
| Script | Purpose |
|
||||||
|
|--------|---------|
|
||||||
|
| `scripts/sync-posts.ts` | Syncs markdown content |
|
||||||
|
| `scripts/sync-discovery-files.ts` | Updates discovery files |
|
||||||
|
| `scripts/import-url.ts` | Imports external URLs |
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
The sync scripts use these environment files:
|
||||||
|
|
||||||
|
| File | Used by |
|
||||||
|
|------|---------|
|
||||||
|
| `.env.local` | Development sync (default) |
|
||||||
|
| `.env.production.local` | Production sync (with SYNC_ENV=production) |
|
||||||
|
|
||||||
|
Both files contain `VITE_CONVEX_URL` pointing to the Convex deployment.
|
||||||
|
|
||||||
|
## What gets synced
|
||||||
|
|
||||||
|
### Posts (content/blog/)
|
||||||
|
|
||||||
|
- Frontmatter fields (title, description, date, tags, etc.)
|
||||||
|
- Full markdown content
|
||||||
|
- Calculated reading time
|
||||||
|
|
||||||
|
### Pages (content/pages/)
|
||||||
|
|
||||||
|
- Frontmatter fields (title, slug, order, etc.)
|
||||||
|
- Full markdown content
|
||||||
|
|
||||||
|
### Generated files (public/raw/)
|
||||||
|
|
||||||
|
For each published post/page, a static markdown file is generated at `public/raw/{slug}.md`. Also generates `public/raw/index.md` listing all content.
|
||||||
|
|
||||||
|
## Sync mutations
|
||||||
|
|
||||||
|
The sync scripts call these Convex mutations:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Posts
|
||||||
|
api.posts.syncPostsPublic({ posts: ParsedPost[] })
|
||||||
|
|
||||||
|
// Pages
|
||||||
|
api.pages.syncPagesPublic({ pages: ParsedPage[] })
|
||||||
|
```
|
||||||
|
|
||||||
|
These mutations handle create/update/delete in a single transaction.
|
||||||
|
|
||||||
|
## Adding a new frontmatter field
|
||||||
|
|
||||||
|
1. Add to interface in `scripts/sync-posts.ts`
|
||||||
|
2. Add to Convex schema in `convex/schema.ts`
|
||||||
|
3. Add to sync mutation in `convex/posts.ts` or `convex/pages.ts`
|
||||||
|
4. Add to return validators in queries
|
||||||
|
5. Run `npm run sync` to apply
|
||||||
|
|
||||||
|
## Import from URL
|
||||||
|
|
||||||
|
Import external articles as markdown:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run import https://example.com/article
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires `FIRECRAWL_API_KEY` in `.env.local`. The script:
|
||||||
|
|
||||||
|
1. Fetches and converts HTML to markdown via Firecrawl
|
||||||
|
2. Generates frontmatter from page metadata
|
||||||
|
3. Creates file in `content/blog/`
|
||||||
|
4. You still need to run `npm run sync` after
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "VITE_CONVEX_URL not set"
|
||||||
|
|
||||||
|
Run `npx convex dev` first to create `.env.local`.
|
||||||
|
|
||||||
|
### Posts not appearing
|
||||||
|
|
||||||
|
1. Check `published: true` in frontmatter
|
||||||
|
2. Verify required fields are present
|
||||||
|
3. Check Convex dashboard for errors
|
||||||
|
4. Run `npm run sync` again
|
||||||
|
|
||||||
|
### Sync to wrong environment
|
||||||
|
|
||||||
|
Check which env file exists:
|
||||||
|
- `.env.local` for development
|
||||||
|
- `.env.production.local` for production
|
||||||
|
|
||||||
|
Use `SYNC_ENV=production` prefix for prod sync.
|
||||||
@@ -22,7 +22,7 @@ Your content is instantly available to browsers, LLMs, and AI agents.. Write mar
|
|||||||
- **Total Posts**: 17
|
- **Total Posts**: 17
|
||||||
- **Total Pages**: 5
|
- **Total Pages**: 5
|
||||||
- **Latest Post**: 2025-12-29
|
- **Latest Post**: 2025-12-29
|
||||||
- **Last Updated**: 2025-12-30T06:25:18.540Z
|
- **Last Updated**: 2025-12-30T08:48:17.735Z
|
||||||
|
|
||||||
## Tech stack
|
## Tech stack
|
||||||
|
|
||||||
|
|||||||
133
CLAUDE.md
Normal file
133
CLAUDE.md
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
Project instructions for Claude Code.
|
||||||
|
|
||||||
|
## Project context
|
||||||
|
|
||||||
|
Markdown sync framework. Write markdown in `content/`, run sync commands, content appears instantly via Convex real-time database. Built for developers and AI agents.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install # Install dependencies
|
||||||
|
npx convex dev # Start Convex (creates .env.local)
|
||||||
|
npm run dev # Dev server at localhost:5173
|
||||||
|
npm run sync # Sync markdown to Convex
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
| Command | Purpose |
|
||||||
|
|---------|---------|
|
||||||
|
| `npm run sync` | Sync markdown to dev Convex |
|
||||||
|
| `npm run sync:prod` | Sync markdown to prod Convex |
|
||||||
|
| `npm run sync:all` | Sync content + discovery files |
|
||||||
|
| `npm run sync:all:prod` | Sync all to production |
|
||||||
|
| `npm run dev` | Start Vite dev server |
|
||||||
|
| `npm run build` | Production build |
|
||||||
|
| `npx convex dev` | Start Convex dev watcher |
|
||||||
|
| `npx convex deploy` | Deploy Convex to production |
|
||||||
|
| `npm run import <url>` | Import external URL as post |
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
### Adding a blog post
|
||||||
|
|
||||||
|
1. Create `content/blog/my-post.md` with frontmatter (see `.claude/skills/frontmatter.md`)
|
||||||
|
2. Run `npm run sync`
|
||||||
|
3. Content appears at localhost:5173/my-post
|
||||||
|
|
||||||
|
### Adding a page
|
||||||
|
|
||||||
|
1. Create `content/pages/my-page.md` with frontmatter
|
||||||
|
2. Run `npm run sync`
|
||||||
|
3. Page appears at localhost:5173/my-page
|
||||||
|
|
||||||
|
### Modifying Convex functions
|
||||||
|
|
||||||
|
1. Edit files in `convex/`
|
||||||
|
2. `npx convex dev` watches and deploys automatically
|
||||||
|
3. Always add validators for args and returns (see `.claude/skills/convex.md`)
|
||||||
|
|
||||||
|
### Deploying to production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sync:all:prod # Sync all content to prod
|
||||||
|
npx convex deploy # Deploy Convex functions
|
||||||
|
```
|
||||||
|
|
||||||
|
Netlify build command: `npm ci --include=dev && npx convex deploy --cmd 'npm run build'`
|
||||||
|
|
||||||
|
## Code conventions
|
||||||
|
|
||||||
|
- TypeScript strict mode
|
||||||
|
- Convex validators on all functions (args + returns)
|
||||||
|
- Use indexes, never `.filter()` on queries
|
||||||
|
- Make mutations idempotent with early returns
|
||||||
|
- Patch directly without reading first when possible
|
||||||
|
- Use event records for counters, not increments
|
||||||
|
- No emoji in code or docs
|
||||||
|
- No em dashes between words
|
||||||
|
- Sentence case for headings
|
||||||
|
- CSS variables for theming (no hardcoded colors)
|
||||||
|
|
||||||
|
## Do not
|
||||||
|
|
||||||
|
- Use `.filter()` in Convex queries (use `.withIndex()`)
|
||||||
|
- Increment counters directly (use event records)
|
||||||
|
- Read before patching unless necessary
|
||||||
|
- Leave console.log in production
|
||||||
|
- Break existing functionality
|
||||||
|
- Over-engineer solutions
|
||||||
|
- Add features not requested
|
||||||
|
- Use browser default modals/alerts
|
||||||
|
|
||||||
|
## Key files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `convex/schema.ts` | Database schema with indexes |
|
||||||
|
| `convex/posts.ts` | Post queries and mutations |
|
||||||
|
| `convex/pages.ts` | Page queries and mutations |
|
||||||
|
| `convex/stats.ts` | Analytics (conflict-free patterns) |
|
||||||
|
| `src/config/siteConfig.ts` | Site configuration |
|
||||||
|
| `scripts/sync-posts.ts` | Markdown to Convex sync |
|
||||||
|
| `scripts/sync-discovery-files.ts` | Updates AGENTS.md, llms.txt, CLAUDE.md |
|
||||||
|
|
||||||
|
## Project structure
|
||||||
|
|
||||||
|
```
|
||||||
|
content/
|
||||||
|
blog/ # Markdown blog posts
|
||||||
|
pages/ # Static pages
|
||||||
|
convex/ # Convex functions and schema
|
||||||
|
netlify/
|
||||||
|
edge-functions/ # RSS, sitemap, API proxies
|
||||||
|
public/
|
||||||
|
images/ # Static images
|
||||||
|
raw/ # Generated raw markdown files
|
||||||
|
scripts/ # Sync and utility scripts
|
||||||
|
src/
|
||||||
|
components/ # React components
|
||||||
|
config/ # Site configuration
|
||||||
|
context/ # React context (theme, sidebar)
|
||||||
|
hooks/ # Custom hooks
|
||||||
|
pages/ # Route components
|
||||||
|
styles/ # Global CSS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Skills reference
|
||||||
|
|
||||||
|
Detailed documentation in `.claude/skills/`:
|
||||||
|
|
||||||
|
- `frontmatter.md` - Frontmatter syntax for posts and pages
|
||||||
|
- `convex.md` - Convex patterns specific to this app
|
||||||
|
- `sync.md` - How sync commands work
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Convex Best Practices](https://docs.convex.dev/understanding/best-practices/)
|
||||||
|
- [Convex TypeScript](https://docs.convex.dev/understanding/best-practices/typescript)
|
||||||
|
- [Convex Write Conflicts](https://docs.convex.dev/error#1)
|
||||||
|
- [Project README](./README.md)
|
||||||
|
- [AGENTS.md](./AGENTS.md)
|
||||||
13
README.md
13
README.md
@@ -44,6 +44,19 @@ npm run sync:prod # production
|
|||||||
- **[Configuration Guide](https://www.markdown.fast/fork-configuration-guide)** - Automated or manual fork setup
|
- **[Configuration Guide](https://www.markdown.fast/fork-configuration-guide)** - Automated or manual fork setup
|
||||||
- **[Full Documentation](https://www.markdown.fast/docs)** - Docs for all features and configuration
|
- **[Full Documentation](https://www.markdown.fast/docs)** - Docs for all features and configuration
|
||||||
|
|
||||||
|
### AI Development Tools
|
||||||
|
|
||||||
|
The project includes documentation optimized for AI coding assistants:
|
||||||
|
|
||||||
|
- **CLAUDE.md** - Project instructions for Claude Code CLI with workflows, commands, and conventions
|
||||||
|
- **AGENTS.md** - General AI agent instructions for understanding the codebase structure
|
||||||
|
- **.claude/skills/** - Focused skill documentation:
|
||||||
|
- `frontmatter.md` - Complete frontmatter syntax and all field options
|
||||||
|
- `convex.md` - Convex patterns specific to this app
|
||||||
|
- `sync.md` - How sync commands work and content flow
|
||||||
|
|
||||||
|
These files are automatically updated during `npm run sync:discovery` with current site statistics.
|
||||||
|
|
||||||
## Fork Configuration
|
## Fork Configuration
|
||||||
|
|
||||||
After forking this project, you have two options to configure your site:
|
After forking this project, you have two options to configure your site:
|
||||||
|
|||||||
13
TASK.md
13
TASK.md
@@ -7,10 +7,19 @@
|
|||||||
|
|
||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
v1.47.0 ready. Image lightbox feature complete. Images in blog posts and pages automatically open in full-screen lightbox when clicked (if enabled in siteConfig). Lightbox includes backdrop, close button, keyboard support (Escape), and caption display. Configurable via siteConfig.imageLightbox.enabled (default: true). Dashboard config generator includes image lightbox toggle. Documentation updated in docs.md and setup-guide.md.
|
v2.1.0 ready. CLAUDE.md and Claude skills documentation complete. Created CLAUDE.md in root for Claude Code instructions, .claude/skills/ directory with three focused skill files (frontmatter.md, convex.md, sync.md), and updated sync-discovery-files.ts to automatically update CLAUDE.md during sync. Documentation updated in files.md, changelog.md, changelog-page.md, and TASK.md.
|
||||||
|
|
||||||
## Completed
|
## Completed
|
||||||
|
|
||||||
|
- [x] CLAUDE.md and Claude skills documentation
|
||||||
|
- [x] Created CLAUDE.md in root with project instructions for Claude Code
|
||||||
|
- [x] Created .claude/skills/ directory with three focused skill files
|
||||||
|
- [x] frontmatter.md: Complete frontmatter syntax and all 25+ field options
|
||||||
|
- [x] convex.md: Convex patterns specific to this app (indexes, idempotent mutations, conflict prevention)
|
||||||
|
- [x] sync.md: How sync commands work and content flow from markdown to database
|
||||||
|
- [x] Updated sync-discovery-files.ts to automatically update CLAUDE.md during sync
|
||||||
|
- [x] Updated files.md, changelog.md, changelog-page.md, TASK.md with feature documentation
|
||||||
|
|
||||||
- [x] Image lightbox for blog posts and pages
|
- [x] Image lightbox for blog posts and pages
|
||||||
- [x] Added ImageLightboxConfig interface to siteConfig.ts with enabled option
|
- [x] Added ImageLightboxConfig interface to siteConfig.ts with enabled option
|
||||||
- [x] Created ImageLightbox component in BlogPost.tsx with backdrop, close button, keyboard support
|
- [x] Created ImageLightbox component in BlogPost.tsx with backdrop, close button, keyboard support
|
||||||
@@ -48,7 +57,7 @@ v1.47.0 ready. Image lightbox feature complete. Images in blog posts and pages a
|
|||||||
|
|
||||||
- [x] Blog heading styles for home intro content
|
- [x] Blog heading styles for home intro content
|
||||||
- [x] Added generateSlug, getTextContent, HeadingAnchor helper functions to Home.tsx
|
- [x] Added generateSlug, getTextContent, HeadingAnchor helper functions to Home.tsx
|
||||||
- [x] Updated ReactMarkdown components to include h1-h6 with blog-h* classes
|
- [x] Updated ReactMarkdown components to include h1-h6 with blog-h\* classes
|
||||||
- [x] Added clickable anchor links (#) that appear on hover for each heading
|
- [x] Added clickable anchor links (#) that appear on hover for each heading
|
||||||
- [x] Automatic ID generation from heading text for anchor navigation
|
- [x] Automatic ID generation from heading text for anchor navigation
|
||||||
- [x] Added blog styling for lists (blog-ul, blog-ol, blog-li), blockquotes (blog-blockquote), horizontal rules (blog-hr), and links (blog-link)
|
- [x] Added blog styling for lists (blog-ul, blog-ol, blog-li), blockquotes (blog-blockquote), horizontal rules (blog-hr), and links (blog-link)
|
||||||
|
|||||||
24
changelog.md
24
changelog.md
@@ -4,6 +4,30 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [2.1.0] - 2025-12-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- CLAUDE.md for Claude Code project instructions
|
||||||
|
- Project context and quick start guide
|
||||||
|
- All available npm commands and workflows
|
||||||
|
- Code conventions and "do not" list
|
||||||
|
- Key file references and project structure
|
||||||
|
- Links to detailed skills documentation
|
||||||
|
- Claude skills documentation in `.claude/skills/` directory
|
||||||
|
- `frontmatter.md`: Complete frontmatter syntax with all 25+ field options for posts and pages
|
||||||
|
- `convex.md`: Convex patterns specific to this app (indexes, idempotent mutations, write conflict prevention)
|
||||||
|
- `sync.md`: How sync commands work and content flow from markdown to Convex database
|
||||||
|
- Automated CLAUDE.md updates via sync-discovery-files.ts
|
||||||
|
- CLAUDE.md status comment updated during `npm run sync:discovery`
|
||||||
|
- Includes current site name, post count, page count, and last updated timestamp
|
||||||
|
|
||||||
|
### Technical
|
||||||
|
|
||||||
|
- New file: `CLAUDE.md` in project root
|
||||||
|
- New directory: `.claude/skills/` with three markdown files
|
||||||
|
- Updated: `scripts/sync-discovery-files.ts` to update CLAUDE.md alongside AGENTS.md and llms.txt
|
||||||
|
|
||||||
## [2.0.0] - 2025-12-29
|
## [2.0.0] - 2025-12-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ The configuration script updates these files:
|
|||||||
|
|
||||||
| File | What changes |
|
| File | What changes |
|
||||||
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `src/config/siteConfig.ts` | Site name, bio, GitHub username, features, footer, social footer, newsletter, contact form, AI chat, right sidebar |
|
| `src/config/siteConfig.ts` | Site name, bio, GitHub username, gitHubRepo config, features (logo gallery, GitHub contributions, visitor map, blog page, posts display, homepage, right sidebar, footer, social footer, AI chat, newsletter, contact form, newsletter admin, stats page, MCP server, dashboard, image lightbox) |
|
||||||
| `src/pages/Home.tsx` | Intro paragraph, footer links |
|
| `src/pages/Home.tsx` | Intro paragraph, footer links |
|
||||||
| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
|
| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
|
||||||
| `convex/http.ts` | SITE_URL, SITE_NAME constants |
|
| `convex/http.ts` | SITE_URL, SITE_NAME constants |
|
||||||
@@ -117,6 +117,12 @@ The JSON config file supports additional options:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"gitHubRepoConfig": {
|
||||||
|
"owner": "yourusername",
|
||||||
|
"repo": "your-repo-name",
|
||||||
|
"branch": "main",
|
||||||
|
"contentPath": "public/raw"
|
||||||
|
},
|
||||||
"logoGallery": {
|
"logoGallery": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"title": "Built with",
|
"title": "Built with",
|
||||||
@@ -137,8 +143,8 @@ The JSON config file supports additional options:
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"showInNav": true,
|
"showInNav": true,
|
||||||
"title": "Blog",
|
"title": "Blog",
|
||||||
"description": "Latest posts",
|
"description": "All posts from the blog, sorted by date.",
|
||||||
"order": 0
|
"order": 2
|
||||||
},
|
},
|
||||||
"postsDisplay": {
|
"postsDisplay": {
|
||||||
"showOnHome": true,
|
"showOnHome": true,
|
||||||
@@ -154,6 +160,11 @@ The JSON config file supports additional options:
|
|||||||
"showViewToggle": true,
|
"showViewToggle": true,
|
||||||
"theme": "tan",
|
"theme": "tan",
|
||||||
"fontFamily": "serif",
|
"fontFamily": "serif",
|
||||||
|
"homepage": {
|
||||||
|
"type": "default",
|
||||||
|
"slug": null,
|
||||||
|
"originalHomeRoute": "/home"
|
||||||
|
},
|
||||||
"rightSidebar": {
|
"rightSidebar": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"minWidth": 1135
|
"minWidth": 1135
|
||||||
@@ -163,7 +174,8 @@ The JSON config file supports additional options:
|
|||||||
"showOnHomepage": true,
|
"showOnHomepage": true,
|
||||||
"showOnPosts": true,
|
"showOnPosts": true,
|
||||||
"showOnPages": true,
|
"showOnPages": true,
|
||||||
"showOnBlogPage": true
|
"showOnBlogPage": true,
|
||||||
|
"defaultContent": "Built with [Convex](https://convex.dev) for real-time sync and deployed on [Netlify](https://netlify.com)."
|
||||||
},
|
},
|
||||||
"socialFooter": {
|
"socialFooter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@@ -175,6 +187,14 @@ The JSON config file supports additional options:
|
|||||||
{
|
{
|
||||||
"platform": "github",
|
"platform": "github",
|
||||||
"url": "https://github.com/yourusername/your-repo-name"
|
"url": "https://github.com/yourusername/your-repo-name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "twitter",
|
||||||
|
"url": "https://x.com/yourhandle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "linkedin",
|
||||||
|
"url": "https://www.linkedin.com/in/yourprofile/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"copyright": {
|
"copyright": {
|
||||||
@@ -188,20 +208,98 @@ The JSON config file supports additional options:
|
|||||||
},
|
},
|
||||||
"newsletter": {
|
"newsletter": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"agentmail": {
|
||||||
|
"inbox": "newsletter@mail.agentmail.to"
|
||||||
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"home": { "enabled": false },
|
"home": {
|
||||||
"blogPage": { "enabled": false },
|
"enabled": false,
|
||||||
"posts": { "enabled": false }
|
"position": "above-footer",
|
||||||
|
"title": "Stay Updated",
|
||||||
|
"description": "Get new posts delivered to your inbox."
|
||||||
|
},
|
||||||
|
"blogPage": {
|
||||||
|
"enabled": false,
|
||||||
|
"position": "above-footer",
|
||||||
|
"title": "Subscribe",
|
||||||
|
"description": "Get notified when new posts are published."
|
||||||
|
},
|
||||||
|
"posts": {
|
||||||
|
"enabled": false,
|
||||||
|
"position": "below-content",
|
||||||
|
"title": "Enjoyed this post?",
|
||||||
|
"description": "Subscribe for more updates."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contactForm": {
|
"contactForm": {
|
||||||
"enabled": false
|
"enabled": false,
|
||||||
|
"title": "Get in Touch",
|
||||||
|
"description": "Send us a message and we'll get back to you."
|
||||||
|
},
|
||||||
|
"newsletterAdmin": {
|
||||||
|
"enabled": false,
|
||||||
|
"showInNav": false
|
||||||
|
},
|
||||||
|
"newsletterNotifications": {
|
||||||
|
"enabled": false,
|
||||||
|
"newSubscriberAlert": false,
|
||||||
|
"weeklyStatsSummary": false
|
||||||
|
},
|
||||||
|
"weeklyDigest": {
|
||||||
|
"enabled": false,
|
||||||
|
"dayOfWeek": 0,
|
||||||
|
"subject": "Weekly Digest"
|
||||||
|
},
|
||||||
|
"statsPage": {
|
||||||
|
"enabled": true,
|
||||||
|
"showInNav": true
|
||||||
|
},
|
||||||
|
"mcpServer": {
|
||||||
|
"enabled": true,
|
||||||
|
"endpoint": "/mcp",
|
||||||
|
"publicRateLimit": 50,
|
||||||
|
"authenticatedRateLimit": 1000,
|
||||||
|
"requireAuth": false
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"enabled": true,
|
||||||
|
"requireAuth": false
|
||||||
|
},
|
||||||
|
"imageLightbox": {
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
These are optional. If you omit them, the script uses sensible defaults. See `fork-config.json.example` for the complete schema with all available options.
|
These are optional. If you omit them, the script uses sensible defaults. See `fork-config.json.example` for the complete schema with all available options.
|
||||||
|
|
||||||
|
### Configuration details
|
||||||
|
|
||||||
|
**GitHub Repo Config**: Used for "Open in AI" links (ChatGPT, Claude, Perplexity). Content must be pushed to GitHub for these links to work.
|
||||||
|
|
||||||
|
**Homepage**: Set any page or blog post as your homepage. Options: `"default"` (standard Home component), `"page"` (use a static page), or `"post"` (use a blog post). When using a custom homepage, the original homepage remains accessible at `/home` (or your configured route).
|
||||||
|
|
||||||
|
**Newsletter**: Requires `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` environment variables in Convex dashboard. Signup forms can appear on homepage, blog page, or individual posts.
|
||||||
|
|
||||||
|
**Contact Form**: Requires `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` in Convex dashboard. Optionally set `AGENTMAIL_CONTACT_EMAIL` to override recipient. Enable on specific pages/posts via frontmatter `contactForm: true`.
|
||||||
|
|
||||||
|
**Newsletter Admin**: Admin UI at `/newsletter-admin` for managing subscribers and sending newsletters. Hidden from navigation by default for security.
|
||||||
|
|
||||||
|
**Newsletter Notifications**: Sends developer emails for new subscribers and weekly stats summaries. Uses `AGENTMAIL_CONTACT_EMAIL` or `AGENTMAIL_INBOX` as recipient.
|
||||||
|
|
||||||
|
**Weekly Digest**: Automated weekly email with posts from the past 7 days. Runs via cron job every Sunday at 9:00 AM UTC.
|
||||||
|
|
||||||
|
**Stats Page**: Real-time analytics at `/stats` showing page views, active visitors, and popular content.
|
||||||
|
|
||||||
|
**MCP Server**: HTTP-based Model Context Protocol server at `/mcp` endpoint for AI tool integration. Set `MCP_API_KEY` in Netlify env vars for authenticated access.
|
||||||
|
|
||||||
|
**Dashboard**: Admin dashboard at `/dashboard` for content management and site configuration. Optional WorkOS authentication via `requireAuth: true`. When `requireAuth` is `false`, dashboard is open access.
|
||||||
|
|
||||||
|
**Image Lightbox**: Click-to-magnify functionality for images in blog posts and pages. Images open in full-screen overlay when clicked.
|
||||||
|
|
||||||
|
For detailed configuration instructions, see `FORK_CONFIG.md`.
|
||||||
|
|
||||||
## After configuring
|
## After configuring
|
||||||
|
|
||||||
Once configuration is complete:
|
Once configuration is complete:
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ image: /images/team-sync.png
|
|||||||
featured: false
|
featured: false
|
||||||
layout: "sidebar"
|
layout: "sidebar"
|
||||||
newsletter: true
|
newsletter: true
|
||||||
|
|
||||||
layout: "sidebar"
|
|
||||||
excerpt: "Learn how teams use git for markdown version control, sync to Convex deployments, and automate production workflows."
|
excerpt: "Learn how teams use git for markdown version control, sync to Convex deployments, and automate production workflows."
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -64,25 +64,66 @@ It's a hybrid: developer workflow for publishing + real-time delivery like a dyn
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
**Themes and UI:**
|
||||||
|
|
||||||
- Four theme options (dark, light, tan, cloud)
|
- Four theme options (dark, light, tan, cloud)
|
||||||
|
- Font switcher (serif, sans, monospace) with localStorage persistence
|
||||||
- Mobile menu with hamburger navigation on smaller screens
|
- Mobile menu with hamburger navigation on smaller screens
|
||||||
- Full text search with Command+K shortcut
|
- Image lightbox for full-screen image viewing when clicked
|
||||||
|
- Scroll-to-top button with configurable threshold
|
||||||
|
|
||||||
|
**Content and navigation:**
|
||||||
|
|
||||||
|
- Sidebar layout for docs-style pages with table of contents
|
||||||
|
- Right sidebar with CopyPageDropdown on wide screens
|
||||||
- Featured section with list/card view toggle and excerpts
|
- Featured section with list/card view toggle and excerpts
|
||||||
- Logo gallery with clickable links and marquee scroll
|
- Dedicated blog page with hero cards and featured rows
|
||||||
- GitHub contributions graph with year navigation
|
- Tag pages at `/tags/{tag}` with related posts in footer
|
||||||
- Dedicated blog page with configurable navigation order
|
- Homepage configuration to use any page or post as homepage
|
||||||
- Real-time analytics at `/stats`
|
|
||||||
- RSS feeds and sitemap for SEO
|
**Search and discovery:**
|
||||||
|
|
||||||
|
- Full text search with Command+K shortcut
|
||||||
- Static raw markdown files at `/raw/{slug}.md`
|
- Static raw markdown files at `/raw/{slug}.md`
|
||||||
- API endpoints for AI/LLM access
|
- RSS feeds (`/rss.xml` and `/rss-full.xml`) and sitemap for SEO
|
||||||
- Copy to ChatGPT, Claude, and Perplexity sharing
|
- API endpoints for AI/LLM access (`/api/posts`, `/api/export`)
|
||||||
|
- HTTP-based MCP server at `/mcp` for AI tool integration (Cursor, Claude Desktop)
|
||||||
|
|
||||||
|
**Sharing and AI integration:**
|
||||||
|
|
||||||
|
- Copy to ChatGPT, Claude, and Perplexity sharing buttons
|
||||||
- Generate Skill option for AI agent training
|
- Generate Skill option for AI agent training
|
||||||
- View as Markdown option in share dropdown
|
- View as Markdown option in share dropdown
|
||||||
|
|
||||||
|
**Content creation:**
|
||||||
|
|
||||||
- Markdown writing page at `/write` with frontmatter reference
|
- Markdown writing page at `/write` with frontmatter reference
|
||||||
- HTTP-based MCP server at `/mcp` for AI tool integration (Cursor, Claude Desktop)
|
- AI Agent chat powered by Anthropic Claude (toggle in Write page or right sidebar)
|
||||||
- Firecrawl content importer (`npm run import <url>`) for external articles
|
- Firecrawl content importer (`npm run import <url>`) for external articles
|
||||||
|
|
||||||
|
**Dashboard and admin:**
|
||||||
|
|
||||||
|
- Dashboard at `/dashboard` for content management and site configuration
|
||||||
|
- Posts and pages editor with live preview and frontmatter sidebar
|
||||||
|
- Sync commands UI for executing syncs from browser
|
||||||
- Newsletter management with AgentMail integration and admin UI
|
- Newsletter management with AgentMail integration and admin UI
|
||||||
|
- Real-time analytics at `/stats` with visitor map
|
||||||
|
|
||||||
|
**Newsletter and contact:**
|
||||||
|
|
||||||
|
- Newsletter signup forms on homepage, blog page, and posts
|
||||||
- Contact forms on pages/posts via frontmatter with AgentMail delivery
|
- Contact forms on pages/posts via frontmatter with AgentMail delivery
|
||||||
|
- Email notifications for new subscribers and weekly stats
|
||||||
|
|
||||||
|
**Developer and AI agent support:**
|
||||||
|
|
||||||
|
- CLAUDE.md for Claude Code instructions and workflows
|
||||||
|
- AGENTS.md for AI coding agent context (agents.md spec)
|
||||||
|
- Skills files in `.claude/skills/` (frontmatter, convex, sync)
|
||||||
|
- Sync discovery commands to update AGENTS.md, CLAUDE.md, and llms.txt
|
||||||
|
- Optional WorkOS authentication for dashboard access
|
||||||
|
- GitHub contributions graph with year navigation
|
||||||
|
- Logo gallery with clickable links and static grid or marquee scroll
|
||||||
|
|
||||||
## Who this is for
|
## Who this is for
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,34 @@ layout: "sidebar"
|
|||||||
All notable changes to this project.
|
All notable changes to this project.
|
||||||

|

|
||||||
|
|
||||||
|
## v2.1.0
|
||||||
|
|
||||||
|
Released December 30, 2025
|
||||||
|
|
||||||
|
**CLAUDE.md and Claude skills documentation**
|
||||||
|
|
||||||
|
- CLAUDE.md for Claude Code project instructions
|
||||||
|
- Project context and quick start guide
|
||||||
|
- All available npm commands and workflows
|
||||||
|
- Code conventions and "do not" list
|
||||||
|
- Key file references and project structure
|
||||||
|
- Links to detailed skills documentation
|
||||||
|
- Claude skills documentation in `.claude/skills/` directory
|
||||||
|
- `frontmatter.md`: Complete frontmatter syntax with all 25+ field options for posts and pages
|
||||||
|
- `convex.md`: Convex patterns specific to this app (indexes, idempotent mutations, write conflict prevention)
|
||||||
|
- `sync.md`: How sync commands work and content flow from markdown to Convex database
|
||||||
|
- Automated CLAUDE.md updates via sync-discovery-files.ts
|
||||||
|
- CLAUDE.md status comment updated during `npm run sync:discovery`
|
||||||
|
- Includes current site name, post count, page count, and last updated timestamp
|
||||||
|
|
||||||
|
**Technical details:**
|
||||||
|
|
||||||
|
- New file: `CLAUDE.md` in project root
|
||||||
|
- New directory: `.claude/skills/` with three markdown files
|
||||||
|
- Updated: `scripts/sync-discovery-files.ts` to update CLAUDE.md alongside AGENTS.md and llms.txt
|
||||||
|
|
||||||
|
Updated files: `CLAUDE.md`, `.claude/skills/frontmatter.md`, `.claude/skills/convex.md`, `.claude/skills/sync.md`, `scripts/sync-discovery-files.ts`, `files.md`, `changelog.md`, `TASK.md`
|
||||||
|
|
||||||
## v2.0.0
|
## v2.0.0
|
||||||
|
|
||||||
Released December 29, 2025
|
Released December 29, 2025
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ order: -1
|
|||||||
textAlign: "left"
|
textAlign: "left"
|
||||||
---
|
---
|
||||||
|
|
||||||
An open-source publishing framework built for AI agents and developers to ship **websites**, **docs**, or **blogs**.
|
An open-source publishing framework built for AI agents and developers to ship **[docs](/docs)**, or **[blogs](/blog)** or **[websites](/)**.
|
||||||
|
|
||||||
Write markdown, sync from the terminal. [Fork it](https://github.com/waynesutton/markdown-site), customize it, ship it.
|
Write markdown, sync from the terminal. **[Fork it](https://github.com/waynesutton/markdown-site)**, customize it, ship it.
|
||||||
|
|
||||||
<!-- This is a comments
|
<!-- This is a comments
|
||||||
Your content is instantly available to browsers, LLMs, and AI
|
Your content is instantly available to browsers, LLMs, and AI
|
||||||
@@ -17,7 +17,7 @@ agents. -->
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
**AI agent integration** — API endpoints, raw markdown files, and MCP server included.
|
**AI agent integration** — API endpoints, raw markdown files, skills.md and MCP server included.
|
||||||
|
|
||||||
**File-based publishing** — Write markdown locally, run `npm run sync`, content syncs everywhere.
|
**File-based publishing** — Write markdown locally, run `npm run sync`, content syncs everywhere.
|
||||||
|
|
||||||
@@ -28,3 +28,5 @@ agents. -->
|
|||||||
**Multiple output formats** — JSON via API endpoints, raw .md files, and RSS feeds.
|
**Multiple output formats** — JSON via API endpoints, raw .md files, and RSS feeds.
|
||||||
|
|
||||||
**Real-time team sync** — Multiple developers run npm run sync from different machines.
|
**Real-time team sync** — Multiple developers run npm run sync from different machines.
|
||||||
|
|
||||||
|
**Sync Commands** - Sync discovery commands to update AGENTS.md, CLAUDE.md, and llms.txt
|
||||||
|
|||||||
11
files.md
11
files.md
@@ -13,6 +13,7 @@ A brief description of each file in the codebase.
|
|||||||
| `netlify.toml` | Netlify deployment and Convex HTTP redirects |
|
| `netlify.toml` | Netlify deployment and Convex HTTP redirects |
|
||||||
| `README.md` | Project documentation |
|
| `README.md` | Project documentation |
|
||||||
| `AGENTS.md` | AI coding agent instructions (agents.md spec) |
|
| `AGENTS.md` | AI coding agent instructions (agents.md spec) |
|
||||||
|
| `CLAUDE.md` | Claude Code instructions for project workflows |
|
||||||
| `files.md` | This file - codebase structure |
|
| `files.md` | This file - codebase structure |
|
||||||
| `changelog.md` | Version history and changes |
|
| `changelog.md` | Version history and changes |
|
||||||
| `TASK.md` | Task tracking and project status |
|
| `TASK.md` | Task tracking and project status |
|
||||||
@@ -206,7 +207,7 @@ Markdown files for static pages like About, Projects, Contact, Changelog.
|
|||||||
| File | Description |
|
| File | Description |
|
||||||
| ------------------------- | ----------------------------------------------------- |
|
| ------------------------- | ----------------------------------------------------- |
|
||||||
| `sync-posts.ts` | Syncs markdown files to Convex at build time (markdown sync v2) |
|
| `sync-posts.ts` | Syncs markdown files to Convex at build time (markdown sync v2) |
|
||||||
| `sync-discovery-files.ts` | Updates AGENTS.md and llms.txt with current app data |
|
| `sync-discovery-files.ts` | Updates AGENTS.md, CLAUDE.md, and llms.txt with current app data |
|
||||||
| `import-url.ts` | Imports external URLs as markdown posts (Firecrawl) |
|
| `import-url.ts` | Imports external URLs as markdown posts (Firecrawl) |
|
||||||
| `configure-fork.ts` | Automated fork configuration (reads fork-config.json) |
|
| `configure-fork.ts` | Automated fork configuration (reads fork-config.json) |
|
||||||
| `send-newsletter.ts` | CLI tool for sending newsletter posts (npm run newsletter:send <slug>). Calls scheduleSendPostNewsletter mutation directly. |
|
| `send-newsletter.ts` | CLI tool for sending newsletter posts (npm run newsletter:send <slug>). Calls scheduleSendPostNewsletter mutation directly. |
|
||||||
@@ -302,6 +303,14 @@ Files include a metadata header with type (post/page), date, reading time, and t
|
|||||||
| `sample-logo-4.svg` | Sample logo (replace with your own) |
|
| `sample-logo-4.svg` | Sample logo (replace with your own) |
|
||||||
| `sample-logo-5.svg` | Sample logo (replace with your own) |
|
| `sample-logo-5.svg` | Sample logo (replace with your own) |
|
||||||
|
|
||||||
|
## Claude Skills (`.claude/skills/`)
|
||||||
|
|
||||||
|
| File | Description |
|
||||||
|
| -------------- | ---------------------------------------------------- |
|
||||||
|
| `frontmatter.md` | Frontmatter syntax and all field options for posts and pages |
|
||||||
|
| `convex.md` | Convex patterns specific to this app (indexes, mutations, queries) |
|
||||||
|
| `sync.md` | How sync commands work and content flow from markdown to database |
|
||||||
|
|
||||||
## Cursor Rules (`.cursor/rules/`)
|
## Cursor Rules (`.cursor/rules/`)
|
||||||
|
|
||||||
| File | Description |
|
| File | Description |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# llms.txt - Information for AI assistants and LLMs
|
# llms.txt - Information for AI assistants and LLMs
|
||||||
# Learn more: https://llmstxt.org/
|
# Learn more: https://llmstxt.org/
|
||||||
# Last updated: 2025-12-30T06:25:18.541Z
|
# Last updated: 2025-12-30T08:48:17.736Z
|
||||||
|
|
||||||
> Your content is instantly available to browsers, LLMs, and AI agents.
|
> Your content is instantly available to browsers, LLMs, and AI agents.
|
||||||
|
|
||||||
|
|||||||
@@ -63,25 +63,66 @@ It's a hybrid: developer workflow for publishing + real-time delivery like a dyn
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
**Themes and UI:**
|
||||||
|
|
||||||
- Four theme options (dark, light, tan, cloud)
|
- Four theme options (dark, light, tan, cloud)
|
||||||
|
- Font switcher (serif, sans, monospace) with localStorage persistence
|
||||||
- Mobile menu with hamburger navigation on smaller screens
|
- Mobile menu with hamburger navigation on smaller screens
|
||||||
- Full text search with Command+K shortcut
|
- Image lightbox for full-screen image viewing when clicked
|
||||||
|
- Scroll-to-top button with configurable threshold
|
||||||
|
|
||||||
|
**Content and navigation:**
|
||||||
|
|
||||||
|
- Sidebar layout for docs-style pages with table of contents
|
||||||
|
- Right sidebar with CopyPageDropdown on wide screens
|
||||||
- Featured section with list/card view toggle and excerpts
|
- Featured section with list/card view toggle and excerpts
|
||||||
- Logo gallery with clickable links and marquee scroll
|
- Dedicated blog page with hero cards and featured rows
|
||||||
- GitHub contributions graph with year navigation
|
- Tag pages at `/tags/{tag}` with related posts in footer
|
||||||
- Dedicated blog page with configurable navigation order
|
- Homepage configuration to use any page or post as homepage
|
||||||
- Real-time analytics at `/stats`
|
|
||||||
- RSS feeds and sitemap for SEO
|
**Search and discovery:**
|
||||||
|
|
||||||
|
- Full text search with Command+K shortcut
|
||||||
- Static raw markdown files at `/raw/{slug}.md`
|
- Static raw markdown files at `/raw/{slug}.md`
|
||||||
- API endpoints for AI/LLM access
|
- RSS feeds (`/rss.xml` and `/rss-full.xml`) and sitemap for SEO
|
||||||
- Copy to ChatGPT, Claude, and Perplexity sharing
|
- API endpoints for AI/LLM access (`/api/posts`, `/api/export`)
|
||||||
|
- HTTP-based MCP server at `/mcp` for AI tool integration (Cursor, Claude Desktop)
|
||||||
|
|
||||||
|
**Sharing and AI integration:**
|
||||||
|
|
||||||
|
- Copy to ChatGPT, Claude, and Perplexity sharing buttons
|
||||||
- Generate Skill option for AI agent training
|
- Generate Skill option for AI agent training
|
||||||
- View as Markdown option in share dropdown
|
- View as Markdown option in share dropdown
|
||||||
|
|
||||||
|
**Content creation:**
|
||||||
|
|
||||||
- Markdown writing page at `/write` with frontmatter reference
|
- Markdown writing page at `/write` with frontmatter reference
|
||||||
- HTTP-based MCP server at `/mcp` for AI tool integration (Cursor, Claude Desktop)
|
- AI Agent chat powered by Anthropic Claude (toggle in Write page or right sidebar)
|
||||||
- Firecrawl content importer (`npm run import <url>`) for external articles
|
- Firecrawl content importer (`npm run import <url>`) for external articles
|
||||||
|
|
||||||
|
**Dashboard and admin:**
|
||||||
|
|
||||||
|
- Dashboard at `/dashboard` for content management and site configuration
|
||||||
|
- Posts and pages editor with live preview and frontmatter sidebar
|
||||||
|
- Sync commands UI for executing syncs from browser
|
||||||
- Newsletter management with AgentMail integration and admin UI
|
- Newsletter management with AgentMail integration and admin UI
|
||||||
|
- Real-time analytics at `/stats` with visitor map
|
||||||
|
|
||||||
|
**Newsletter and contact:**
|
||||||
|
|
||||||
|
- Newsletter signup forms on homepage, blog page, and posts
|
||||||
- Contact forms on pages/posts via frontmatter with AgentMail delivery
|
- Contact forms on pages/posts via frontmatter with AgentMail delivery
|
||||||
|
- Email notifications for new subscribers and weekly stats
|
||||||
|
|
||||||
|
**Developer and AI agent support:**
|
||||||
|
|
||||||
|
- CLAUDE.md for Claude Code instructions and workflows
|
||||||
|
- AGENTS.md for AI coding agent context (agents.md spec)
|
||||||
|
- Skills files in `.claude/skills/` (frontmatter, convex, sync)
|
||||||
|
- Sync discovery commands to update AGENTS.md, CLAUDE.md, and llms.txt
|
||||||
|
- Optional WorkOS authentication for dashboard access
|
||||||
|
- GitHub contributions graph with year navigation
|
||||||
|
- Logo gallery with clickable links and static grid or marquee scroll
|
||||||
|
|
||||||
## Who this is for
|
## Who this is for
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,34 @@ Date: 2025-12-30
|
|||||||
All notable changes to this project.
|
All notable changes to this project.
|
||||||

|

|
||||||
|
|
||||||
|
## v2.1.0
|
||||||
|
|
||||||
|
Released December 30, 2025
|
||||||
|
|
||||||
|
**CLAUDE.md and Claude skills documentation**
|
||||||
|
|
||||||
|
- CLAUDE.md for Claude Code project instructions
|
||||||
|
- Project context and quick start guide
|
||||||
|
- All available npm commands and workflows
|
||||||
|
- Code conventions and "do not" list
|
||||||
|
- Key file references and project structure
|
||||||
|
- Links to detailed skills documentation
|
||||||
|
- Claude skills documentation in `.claude/skills/` directory
|
||||||
|
- `frontmatter.md`: Complete frontmatter syntax with all 25+ field options for posts and pages
|
||||||
|
- `convex.md`: Convex patterns specific to this app (indexes, idempotent mutations, write conflict prevention)
|
||||||
|
- `sync.md`: How sync commands work and content flow from markdown to Convex database
|
||||||
|
- Automated CLAUDE.md updates via sync-discovery-files.ts
|
||||||
|
- CLAUDE.md status comment updated during `npm run sync:discovery`
|
||||||
|
- Includes current site name, post count, page count, and last updated timestamp
|
||||||
|
|
||||||
|
**Technical details:**
|
||||||
|
|
||||||
|
- New file: `CLAUDE.md` in project root
|
||||||
|
- New directory: `.claude/skills/` with three markdown files
|
||||||
|
- Updated: `scripts/sync-discovery-files.ts` to update CLAUDE.md alongside AGENTS.md and llms.txt
|
||||||
|
|
||||||
|
Updated files: `CLAUDE.md`, `.claude/skills/frontmatter.md`, `.claude/skills/convex.md`, `.claude/skills/sync.md`, `scripts/sync-discovery-files.ts`, `files.md`, `changelog.md`, `TASK.md`
|
||||||
|
|
||||||
## v2.0.0
|
## v2.0.0
|
||||||
|
|
||||||
Released December 29, 2025
|
Released December 29, 2025
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ The configuration script updates these files:
|
|||||||
|
|
||||||
| File | What changes |
|
| File | What changes |
|
||||||
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `src/config/siteConfig.ts` | Site name, bio, GitHub username, features, footer, social footer, newsletter, contact form, AI chat, right sidebar |
|
| `src/config/siteConfig.ts` | Site name, bio, GitHub username, gitHubRepo config, features (logo gallery, GitHub contributions, visitor map, blog page, posts display, homepage, right sidebar, footer, social footer, AI chat, newsletter, contact form, newsletter admin, stats page, MCP server, dashboard, image lightbox) |
|
||||||
| `src/pages/Home.tsx` | Intro paragraph, footer links |
|
| `src/pages/Home.tsx` | Intro paragraph, footer links |
|
||||||
| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
|
| `src/pages/Post.tsx` | SITE_URL, SITE_NAME constants |
|
||||||
| `convex/http.ts` | SITE_URL, SITE_NAME constants |
|
| `convex/http.ts` | SITE_URL, SITE_NAME constants |
|
||||||
@@ -111,6 +111,12 @@ The JSON config file supports additional options:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"gitHubRepoConfig": {
|
||||||
|
"owner": "yourusername",
|
||||||
|
"repo": "your-repo-name",
|
||||||
|
"branch": "main",
|
||||||
|
"contentPath": "public/raw"
|
||||||
|
},
|
||||||
"logoGallery": {
|
"logoGallery": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"title": "Built with",
|
"title": "Built with",
|
||||||
@@ -131,8 +137,8 @@ The JSON config file supports additional options:
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"showInNav": true,
|
"showInNav": true,
|
||||||
"title": "Blog",
|
"title": "Blog",
|
||||||
"description": "Latest posts",
|
"description": "All posts from the blog, sorted by date.",
|
||||||
"order": 0
|
"order": 2
|
||||||
},
|
},
|
||||||
"postsDisplay": {
|
"postsDisplay": {
|
||||||
"showOnHome": true,
|
"showOnHome": true,
|
||||||
@@ -148,6 +154,11 @@ The JSON config file supports additional options:
|
|||||||
"showViewToggle": true,
|
"showViewToggle": true,
|
||||||
"theme": "tan",
|
"theme": "tan",
|
||||||
"fontFamily": "serif",
|
"fontFamily": "serif",
|
||||||
|
"homepage": {
|
||||||
|
"type": "default",
|
||||||
|
"slug": null,
|
||||||
|
"originalHomeRoute": "/home"
|
||||||
|
},
|
||||||
"rightSidebar": {
|
"rightSidebar": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"minWidth": 1135
|
"minWidth": 1135
|
||||||
@@ -157,7 +168,8 @@ The JSON config file supports additional options:
|
|||||||
"showOnHomepage": true,
|
"showOnHomepage": true,
|
||||||
"showOnPosts": true,
|
"showOnPosts": true,
|
||||||
"showOnPages": true,
|
"showOnPages": true,
|
||||||
"showOnBlogPage": true
|
"showOnBlogPage": true,
|
||||||
|
"defaultContent": "Built with [Convex](https://convex.dev) for real-time sync and deployed on [Netlify](https://netlify.com)."
|
||||||
},
|
},
|
||||||
"socialFooter": {
|
"socialFooter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@@ -169,6 +181,14 @@ The JSON config file supports additional options:
|
|||||||
{
|
{
|
||||||
"platform": "github",
|
"platform": "github",
|
||||||
"url": "https://github.com/yourusername/your-repo-name"
|
"url": "https://github.com/yourusername/your-repo-name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "twitter",
|
||||||
|
"url": "https://x.com/yourhandle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "linkedin",
|
||||||
|
"url": "https://www.linkedin.com/in/yourprofile/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"copyright": {
|
"copyright": {
|
||||||
@@ -182,20 +202,98 @@ The JSON config file supports additional options:
|
|||||||
},
|
},
|
||||||
"newsletter": {
|
"newsletter": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
"agentmail": {
|
||||||
|
"inbox": "newsletter@mail.agentmail.to"
|
||||||
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"home": { "enabled": false },
|
"home": {
|
||||||
"blogPage": { "enabled": false },
|
"enabled": false,
|
||||||
"posts": { "enabled": false }
|
"position": "above-footer",
|
||||||
|
"title": "Stay Updated",
|
||||||
|
"description": "Get new posts delivered to your inbox."
|
||||||
|
},
|
||||||
|
"blogPage": {
|
||||||
|
"enabled": false,
|
||||||
|
"position": "above-footer",
|
||||||
|
"title": "Subscribe",
|
||||||
|
"description": "Get notified when new posts are published."
|
||||||
|
},
|
||||||
|
"posts": {
|
||||||
|
"enabled": false,
|
||||||
|
"position": "below-content",
|
||||||
|
"title": "Enjoyed this post?",
|
||||||
|
"description": "Subscribe for more updates."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contactForm": {
|
"contactForm": {
|
||||||
"enabled": false
|
"enabled": false,
|
||||||
|
"title": "Get in Touch",
|
||||||
|
"description": "Send us a message and we'll get back to you."
|
||||||
|
},
|
||||||
|
"newsletterAdmin": {
|
||||||
|
"enabled": false,
|
||||||
|
"showInNav": false
|
||||||
|
},
|
||||||
|
"newsletterNotifications": {
|
||||||
|
"enabled": false,
|
||||||
|
"newSubscriberAlert": false,
|
||||||
|
"weeklyStatsSummary": false
|
||||||
|
},
|
||||||
|
"weeklyDigest": {
|
||||||
|
"enabled": false,
|
||||||
|
"dayOfWeek": 0,
|
||||||
|
"subject": "Weekly Digest"
|
||||||
|
},
|
||||||
|
"statsPage": {
|
||||||
|
"enabled": true,
|
||||||
|
"showInNav": true
|
||||||
|
},
|
||||||
|
"mcpServer": {
|
||||||
|
"enabled": true,
|
||||||
|
"endpoint": "/mcp",
|
||||||
|
"publicRateLimit": 50,
|
||||||
|
"authenticatedRateLimit": 1000,
|
||||||
|
"requireAuth": false
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"enabled": true,
|
||||||
|
"requireAuth": false
|
||||||
|
},
|
||||||
|
"imageLightbox": {
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
These are optional. If you omit them, the script uses sensible defaults. See `fork-config.json.example` for the complete schema with all available options.
|
These are optional. If you omit them, the script uses sensible defaults. See `fork-config.json.example` for the complete schema with all available options.
|
||||||
|
|
||||||
|
### Configuration details
|
||||||
|
|
||||||
|
**GitHub Repo Config**: Used for "Open in AI" links (ChatGPT, Claude, Perplexity). Content must be pushed to GitHub for these links to work.
|
||||||
|
|
||||||
|
**Homepage**: Set any page or blog post as your homepage. Options: `"default"` (standard Home component), `"page"` (use a static page), or `"post"` (use a blog post). When using a custom homepage, the original homepage remains accessible at `/home` (or your configured route).
|
||||||
|
|
||||||
|
**Newsletter**: Requires `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` environment variables in Convex dashboard. Signup forms can appear on homepage, blog page, or individual posts.
|
||||||
|
|
||||||
|
**Contact Form**: Requires `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` in Convex dashboard. Optionally set `AGENTMAIL_CONTACT_EMAIL` to override recipient. Enable on specific pages/posts via frontmatter `contactForm: true`.
|
||||||
|
|
||||||
|
**Newsletter Admin**: Admin UI at `/newsletter-admin` for managing subscribers and sending newsletters. Hidden from navigation by default for security.
|
||||||
|
|
||||||
|
**Newsletter Notifications**: Sends developer emails for new subscribers and weekly stats summaries. Uses `AGENTMAIL_CONTACT_EMAIL` or `AGENTMAIL_INBOX` as recipient.
|
||||||
|
|
||||||
|
**Weekly Digest**: Automated weekly email with posts from the past 7 days. Runs via cron job every Sunday at 9:00 AM UTC.
|
||||||
|
|
||||||
|
**Stats Page**: Real-time analytics at `/stats` showing page views, active visitors, and popular content.
|
||||||
|
|
||||||
|
**MCP Server**: HTTP-based Model Context Protocol server at `/mcp` endpoint for AI tool integration. Set `MCP_API_KEY` in Netlify env vars for authenticated access.
|
||||||
|
|
||||||
|
**Dashboard**: Admin dashboard at `/dashboard` for content management and site configuration. Optional WorkOS authentication via `requireAuth: true`. When `requireAuth` is `false`, dashboard is open access.
|
||||||
|
|
||||||
|
**Image Lightbox**: Click-to-magnify functionality for images in blog posts and pages. Images open in full-screen overlay when clicked.
|
||||||
|
|
||||||
|
For detailed configuration instructions, see `FORK_CONFIG.md`.
|
||||||
|
|
||||||
## After configuring
|
## After configuring
|
||||||
|
|
||||||
Once configuration is complete:
|
Once configuration is complete:
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ Type: page
|
|||||||
Date: 2025-12-30
|
Date: 2025-12-30
|
||||||
---
|
---
|
||||||
|
|
||||||
An open-source publishing framework built for AI agents and developers to ship **websites**, **docs**, or **blogs**.
|
An open-source publishing framework built for AI agents and developers to ship **[docs](/docs)**, or **[blogs](/blog)** or **[websites](/)**.
|
||||||
|
|
||||||
Write markdown, sync from the terminal. [Fork it](https://github.com/waynesutton/markdown-site), customize it, ship it.
|
Write markdown, sync from the terminal. **[Fork it](https://github.com/waynesutton/markdown-site)**, customize it, ship it.
|
||||||
|
|
||||||
<!-- This is a comments
|
<!-- This is a comments
|
||||||
Your content is instantly available to browsers, LLMs, and AI
|
Your content is instantly available to browsers, LLMs, and AI
|
||||||
@@ -15,7 +15,7 @@ agents. -->
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
**AI agent integration** — API endpoints, raw markdown files, and MCP server included.
|
**AI agent integration** — API endpoints, raw markdown files, skills.md and MCP server included.
|
||||||
|
|
||||||
**File-based publishing** — Write markdown locally, run `npm run sync`, content syncs everywhere.
|
**File-based publishing** — Write markdown locally, run `npm run sync`, content syncs everywhere.
|
||||||
|
|
||||||
@@ -25,4 +25,6 @@ agents. -->
|
|||||||
|
|
||||||
**Multiple output formats** — JSON via API endpoints, raw .md files, and RSS feeds.
|
**Multiple output formats** — JSON via API endpoints, raw .md files, and RSS feeds.
|
||||||
|
|
||||||
**Real-time team sync** — Multiple developers run npm run sync from different machines.
|
**Real-time team sync** — Multiple developers run npm run sync from different machines.
|
||||||
|
|
||||||
|
**Sync Commands** - Sync discovery commands to update AGENTS.md, CLAUDE.md, and llms.txt
|
||||||
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
This is the homepage index of all published content.
|
This is the homepage index of all published content.
|
||||||
|
|
||||||
## Blog Posts (16)
|
## Blog Posts (17)
|
||||||
|
|
||||||
- **[How to setup WorkOS with Markdown Sync](/raw/how-to-setup-workos.md)** - Step-by-step guide to configure WorkOS AuthKit authentication for your markdown blog dashboard. WorkOS is optional and can be enabled in siteConfig.ts.
|
- **[How to setup WorkOS with Markdown Sync](/raw/how-to-setup-workos.md)** - Step-by-step guide to configure WorkOS AuthKit authentication for your markdown blog dashboard. WorkOS is optional and can be enabled in siteConfig.ts.
|
||||||
- Date: 2025-12-29 | Reading time: 10 min read | Tags: workos, authentication, tutorial, dashboard
|
- Date: 2025-12-29 | Reading time: 10 min read | Tags: workos, authentication, tutorial, dashboard
|
||||||
- **[How to use the Markdown sync dashboard](/raw/how-to-use-the-markdown-sync-dashboard.md)** - Learn how to use the dashboard at /dashboard to manage content, configure your site, and sync markdown files without leaving your browser.
|
- **[How to use the Markdown sync dashboard](/raw/how-to-use-the-markdown-sync-dashboard.md)** - Learn how to use the dashboard at /dashboard to manage content, configure your site, and sync markdown files without leaving your browser.
|
||||||
- Date: 2025-12-29 | Reading time: 8 min read | Tags: dashboard, tutorial, content-management
|
- Date: 2025-12-29 | Reading time: 8 min read | Tags: dashboard, tutorial, content-management
|
||||||
|
- **[Team Workflows with Git Version Control](/raw/team-workflows-git-version-control.md)** - How teams collaborate on markdown content using git, sync to shared Convex deployments, and automate production syncs with CI/CD.
|
||||||
|
- Date: 2025-12-29 | Reading time: 6 min read | Tags: git, convex, ci-cd, collaboration, workflow
|
||||||
- **[How to Use the MCP Server with MarkDown Sync](/raw/how-to-use-mcp-server.md)** - Guide to using the HTTP-based Model Context Protocol(MCP) server at www.markdown.fast/mcp with Cursor and other AI tools
|
- **[How to Use the MCP Server with MarkDown Sync](/raw/how-to-use-mcp-server.md)** - Guide to using the HTTP-based Model Context Protocol(MCP) server at www.markdown.fast/mcp with Cursor and other AI tools
|
||||||
- Date: 2025-12-28 | Reading time: 5 min read | Tags: mcp, cursor, ai, tutorial, netlify
|
- Date: 2025-12-28 | Reading time: 5 min read | Tags: mcp, cursor, ai, tutorial, netlify
|
||||||
- **[How to use AgentMail with Markdown Sync](/raw/how-to-use-agentmail.md)** - Complete guide to setting up AgentMail for newsletters and contact forms in your markdown blog
|
- **[How to use AgentMail with Markdown Sync](/raw/how-to-use-agentmail.md)** - Complete guide to setting up AgentMail for newsletters and contact forms in your markdown blog
|
||||||
@@ -49,6 +51,6 @@ This is the homepage index of all published content.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Total Content:** 16 posts, 7 pages
|
**Total Content:** 17 posts, 7 pages
|
||||||
|
|
||||||
All content is available as raw markdown files at `/raw/{slug}.md`
|
All content is available as raw markdown files at `/raw/{slug}.md`
|
||||||
|
|||||||
257
public/raw/team-workflows-git-version-control.md
Normal file
257
public/raw/team-workflows-git-version-control.md
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
# Team Workflows with Git Version Control
|
||||||
|
|
||||||
|
> How teams collaborate on markdown content using git, sync to shared Convex deployments, and automate production syncs with CI/CD.
|
||||||
|
|
||||||
|
---
|
||||||
|
Type: post
|
||||||
|
Date: 2025-12-29
|
||||||
|
Reading time: 6 min read
|
||||||
|
Tags: git, convex, ci-cd, collaboration, workflow
|
||||||
|
---
|
||||||
|
|
||||||
|
# Team Workflows with Git Version Control
|
||||||
|
|
||||||
|
Teams use this markdown framework by treating markdown files as source code. Content lives in git, gets reviewed via pull requests, and syncs to Convex deployments for instant previews and production updates.
|
||||||
|
|
||||||
|
Here's how it works in practice.
|
||||||
|
|
||||||
|
## Initial Setup
|
||||||
|
|
||||||
|
Each team member clones the repo and sets up their own development environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repo
|
||||||
|
git clone https://github.com/your-org/markdown-site.git
|
||||||
|
cd markdown-site
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Initialize Convex (creates .env.local with dev deployment URL)
|
||||||
|
npx convex dev
|
||||||
|
|
||||||
|
# Start dev server
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Each developer gets their own Convex dev deployment. The `.env.local` file contains a unique development URL and stays gitignored. This means everyone can preview changes locally without affecting others.
|
||||||
|
|
||||||
|
## Git Version Control
|
||||||
|
|
||||||
|
Markdown files are regular files in your git repository. Teams commit, push, and review content changes like any other code.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Team member writes a new post
|
||||||
|
# Creates: content/blog/my-new-post.md
|
||||||
|
|
||||||
|
# Commit to git
|
||||||
|
git add content/blog/my-new-post.md
|
||||||
|
git commit -m "Add new blog post"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
The markdown files in `content/blog/` and `content/pages/` are the source of truth. They live in git, get reviewed via pull requests, and can be rolled back like any codebase.
|
||||||
|
|
||||||
|
This approach gives you:
|
||||||
|
|
||||||
|
- Full version history for all content
|
||||||
|
- Pull request reviews before publishing
|
||||||
|
- Easy rollbacks when needed
|
||||||
|
- Branch-based workflows for drafts
|
||||||
|
- Conflict resolution through git merge tools
|
||||||
|
|
||||||
|
## Syncing to Convex
|
||||||
|
|
||||||
|
The sync script reads markdown files from your local filesystem and uploads them to Convex. Development and production use separate deployments.
|
||||||
|
|
||||||
|
**Development (each developer):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# After pulling latest changes from git
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Sync markdown files to YOUR dev Convex
|
||||||
|
npm run sync
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production (shared deployment):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# One person (or CI/CD) syncs to production
|
||||||
|
npm run sync:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
The sync script:
|
||||||
|
|
||||||
|
1. Reads all `.md` files from `content/blog/` and `content/pages/`
|
||||||
|
2. Parses frontmatter using `gray-matter`
|
||||||
|
3. Uploads to Convex via `api.posts.syncPostsPublic` mutation
|
||||||
|
4. Generates static files in `public/raw/` for AI access
|
||||||
|
|
||||||
|
Sync is idempotent. Running it multiple times is safe. The mutation updates posts by slug, so the last sync wins.
|
||||||
|
|
||||||
|
## Environment Files
|
||||||
|
|
||||||
|
Two environment files control which Convex deployment receives your content:
|
||||||
|
|
||||||
|
| File | Purpose | Git Status | Who Has It |
|
||||||
|
| ----------------------- | --------------- | ---------- | ------------------------------- |
|
||||||
|
| `.env.local` | Dev Convex URL | Gitignored | Each developer (different URLs) |
|
||||||
|
| `.env.production.local` | Prod Convex URL | Gitignored | Team shares same URL |
|
||||||
|
|
||||||
|
**Team setup:**
|
||||||
|
|
||||||
|
1. Create production Convex deployment: `npx convex deploy`
|
||||||
|
2. Share the production URL with team
|
||||||
|
3. Each developer creates `.env.production.local`:
|
||||||
|
```
|
||||||
|
VITE_CONVEX_URL=https://your-prod-deployment.convex.cloud
|
||||||
|
```
|
||||||
|
|
||||||
|
Each developer maintains their own dev environment while sharing the production deployment URL.
|
||||||
|
|
||||||
|
## Netlify Deployment
|
||||||
|
|
||||||
|
Netlify connects to your GitHub repo and auto-deploys on every push.
|
||||||
|
|
||||||
|
**Netlify Build Settings:**
|
||||||
|
|
||||||
|
- Build command: `npm ci --include=dev && npx convex deploy --cmd 'npm run build'`
|
||||||
|
- Publish directory: `dist`
|
||||||
|
|
||||||
|
**Netlify Environment Variables:**
|
||||||
|
|
||||||
|
- `CONVEX_DEPLOY_KEY` - Deploys Convex functions at build time
|
||||||
|
- `VITE_CONVEX_URL` - Production Convex URL (same as `.env.production.local`)
|
||||||
|
|
||||||
|
**Workflow:**
|
||||||
|
|
||||||
|
1. Team pushes markdown to GitHub
|
||||||
|
2. Netlify auto-builds and deploys
|
||||||
|
3. Site updates automatically (Convex functions deploy, frontend rebuilds)
|
||||||
|
4. Content sync happens separately via `npm run sync:prod`
|
||||||
|
|
||||||
|
Netlify handles frontend deployment. Content sync is a separate step that updates the Convex database.
|
||||||
|
|
||||||
|
## Complete Team Workflow
|
||||||
|
|
||||||
|
Here's what happens when a team member adds a new blog post:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create markdown file locally
|
||||||
|
# content/blog/team-update.md
|
||||||
|
|
||||||
|
# 2. Commit to git
|
||||||
|
git add content/blog/team-update.md
|
||||||
|
git commit -m "Add team update post"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# 3. Sync to dev Convex (for local preview)
|
||||||
|
npm run sync
|
||||||
|
|
||||||
|
# 4. Netlify auto-deploys from GitHub (frontend rebuilds)
|
||||||
|
|
||||||
|
# 5. Sync to production Convex (one person or CI/CD)
|
||||||
|
npm run sync:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
**Result:**
|
||||||
|
|
||||||
|
- Markdown file is in git (version controlled)
|
||||||
|
- Dev Convex has the post (local preview)
|
||||||
|
- Production Convex has the post (live site)
|
||||||
|
- Netlify site is rebuilt (frontend code)
|
||||||
|
|
||||||
|
## CI/CD Automation
|
||||||
|
|
||||||
|
You can automate production sync with GitHub Actions. This ensures content updates happen automatically when markdown files change.
|
||||||
|
|
||||||
|
Create `.github/workflows/sync-production.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Sync to Production
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "content/**"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "18"
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run sync:prod
|
||||||
|
env:
|
||||||
|
VITE_CONVEX_URL: ${{ secrets.PROD_CONVEX_URL }}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
|
||||||
|
1. Add `PROD_CONVEX_URL` to GitHub Secrets (Settings > Secrets and variables > Actions)
|
||||||
|
2. Push the workflow file to your repo
|
||||||
|
3. Every push to `main` that changes files in `content/` triggers a production sync
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
|
||||||
|
- No manual sync step required
|
||||||
|
- Content updates automatically after git push
|
||||||
|
- Consistent production state
|
||||||
|
- Works for all team members
|
||||||
|
|
||||||
|
**Optional: Sync discovery files too**
|
||||||
|
|
||||||
|
If you want to update discovery files (`AGENTS.md`, `llms.txt`) automatically:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- run: npm run sync:all:prod
|
||||||
|
env:
|
||||||
|
VITE_CONVEX_URL: ${{ secrets.PROD_CONVEX_URL }}
|
||||||
|
```
|
||||||
|
|
||||||
|
This syncs both content and discovery files in one step.
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
The system separates concerns across four layers:
|
||||||
|
|
||||||
|
**Git:** Source of truth for markdown files (version controlled)
|
||||||
|
|
||||||
|
**Convex Dev:** Each developer's local preview database
|
||||||
|
|
||||||
|
**Convex Prod:** Shared production database
|
||||||
|
|
||||||
|
**Netlify:** Frontend hosting (auto-deploys from git)
|
||||||
|
|
||||||
|
**Why this works:**
|
||||||
|
|
||||||
|
- Markdown files are plain text (great for git diffs)
|
||||||
|
- Convex sync is instant (no rebuild needed for content changes)
|
||||||
|
- Netlify handles frontend deployment (code changes trigger rebuilds)
|
||||||
|
- Each developer can preview locally without affecting others
|
||||||
|
|
||||||
|
## Team Collaboration Best Practices
|
||||||
|
|
||||||
|
**Content changes:** Edit markdown → commit → push → sync to prod
|
||||||
|
|
||||||
|
**Code changes:** Edit React/TypeScript → commit → push → Netlify auto-deploys
|
||||||
|
|
||||||
|
**Config changes:** Edit `siteConfig.ts` → commit → push → Netlify rebuilds
|
||||||
|
|
||||||
|
**Convex schema changes:** Edit `convex/schema.ts` → commit → `npx convex deploy`
|
||||||
|
|
||||||
|
**Conflict resolution:**
|
||||||
|
|
||||||
|
- Git handles markdown file conflicts (merge/rebase)
|
||||||
|
- Convex sync is idempotent (safe to run multiple times)
|
||||||
|
- Last sync wins for content (Convex mutations update by slug)
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Teams collaborate on markdown content through git version control. Each developer maintains a local dev environment for previews, while production syncs happen automatically via CI/CD or manual commands. Netlify handles frontend deployment separately from content updates.
|
||||||
|
|
||||||
|
The workflow gives you version control, pull request reviews, and instant previews without sacrificing the real-time sync that makes content updates immediate.
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
*
|
*
|
||||||
* This script updates:
|
* This script updates:
|
||||||
* - AGENTS.md (project overview and current status sections)
|
* - AGENTS.md (project overview and current status sections)
|
||||||
|
* - CLAUDE.md (current status section for Claude Code)
|
||||||
* - public/llms.txt (site info, API endpoints, GitHub links)
|
* - public/llms.txt (site info, API endpoints, GitHub links)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -135,6 +136,43 @@ function getGitHubUrl(siteConfig: SiteConfigData): string {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update CLAUDE.md with current status
|
||||||
|
function updateClaudeMd(
|
||||||
|
content: string,
|
||||||
|
siteConfig: SiteConfigData,
|
||||||
|
siteUrl: string,
|
||||||
|
postCount: number,
|
||||||
|
pageCount: number,
|
||||||
|
latestPostDate?: string,
|
||||||
|
): string {
|
||||||
|
// Build status comment to insert after "## Project context"
|
||||||
|
const statusComment = `<!-- Auto-updated by sync:discovery -->
|
||||||
|
<!-- Site: ${siteConfig.name} | Posts: ${postCount} | Pages: ${pageCount} | Updated: ${new Date().toISOString()} -->`;
|
||||||
|
|
||||||
|
// Check if status comment exists
|
||||||
|
const commentRegex = /<!-- Auto-updated by sync:discovery -->[\s\S]*?<!-- Site:.*?-->/;
|
||||||
|
if (content.match(commentRegex)) {
|
||||||
|
// Replace existing comment
|
||||||
|
content = content.replace(commentRegex, statusComment);
|
||||||
|
} else {
|
||||||
|
// Insert after "## Project context" line
|
||||||
|
const contextIndex = content.indexOf("## Project context");
|
||||||
|
if (contextIndex > -1) {
|
||||||
|
const nextLineIndex = content.indexOf("\n", contextIndex);
|
||||||
|
if (nextLineIndex > -1) {
|
||||||
|
content =
|
||||||
|
content.slice(0, nextLineIndex + 1) +
|
||||||
|
"\n" +
|
||||||
|
statusComment +
|
||||||
|
"\n" +
|
||||||
|
content.slice(nextLineIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
// Update AGENTS.md with app-specific data
|
// Update AGENTS.md with app-specific data
|
||||||
function updateAgentsMd(
|
function updateAgentsMd(
|
||||||
content: string,
|
content: string,
|
||||||
@@ -359,6 +397,23 @@ async function syncDiscoveryFiles() {
|
|||||||
fs.writeFileSync(agentsPath, updatedAgentsContent, "utf-8");
|
fs.writeFileSync(agentsPath, updatedAgentsContent, "utf-8");
|
||||||
console.log(` Updated: ${agentsPath}`);
|
console.log(` Updated: ${agentsPath}`);
|
||||||
|
|
||||||
|
// Read and update CLAUDE.md
|
||||||
|
const claudePath = path.join(ROOT_DIR, "CLAUDE.md");
|
||||||
|
if (fs.existsSync(claudePath)) {
|
||||||
|
console.log("Updating CLAUDE.md with current status...");
|
||||||
|
let claudeContent = fs.readFileSync(claudePath, "utf-8");
|
||||||
|
const updatedClaudeContent = updateClaudeMd(
|
||||||
|
claudeContent,
|
||||||
|
siteConfig,
|
||||||
|
siteUrl,
|
||||||
|
postCount,
|
||||||
|
pageCount,
|
||||||
|
latestPostDate,
|
||||||
|
);
|
||||||
|
fs.writeFileSync(claudePath, updatedClaudeContent, "utf-8");
|
||||||
|
console.log(` Updated: ${claudePath}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate llms.txt
|
// Generate llms.txt
|
||||||
console.log("\nGenerating llms.txt...");
|
console.log("\nGenerating llms.txt...");
|
||||||
const llmsContent = generateLlmsTxt(
|
const llmsContent = generateLlmsTxt(
|
||||||
@@ -373,6 +428,7 @@ async function syncDiscoveryFiles() {
|
|||||||
|
|
||||||
console.log("\nDiscovery files sync complete!");
|
console.log("\nDiscovery files sync complete!");
|
||||||
console.log(` Updated AGENTS.md with app-specific context`);
|
console.log(` Updated AGENTS.md with app-specific context`);
|
||||||
|
console.log(` Updated CLAUDE.md with current status`);
|
||||||
console.log(` Updated llms.txt with ${postCount} posts`);
|
console.log(` Updated llms.txt with ${postCount} posts`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user