# Wayne Sutton full documentation > Developer Community Lead at Convex, tech event organizer, startup ecosystem builder, and adventure motorcycle rider, helping developers and startups build faster with Convex and AI. ## Changelog URL: https://waynesutton.ai/changelog All notable changes to this project. --- ## v2.35.0 Released April 26, 2026 **Agent-ready component: full config, widget URL fix, and production deploy** - Populated `agent-ready.config.json` with 28 pages and 16 API endpoints so llms.txt and agents.md reflect the full site content - All generated URLs now use `https://www.markdown.fast` instead of the raw Convex deployment URL - Enabled `fullTxtEnabled: true` for richer llms-full.txt output - Fixed the widget URL resolver so production builds use `VITE_SITE_URL` or the live browser origin instead of baking in the dev Convex site URL - Deployed updated static bundle to production with the widget URL fix --- ## v2.34.0 Released April 26, 2026 **Agent-ready component integration** - Installed `@waynesutton/agent-ready@0.1.7` with peer deps `@convex-dev/crons` and `@convex-dev/workpool` - Auto-generates, caches, and serves llms.txt, agents.md, and llms-full.txt from the Convex backend - Registered `agentReady`, `crons`, and `workpool` components in `convex/convex.config.ts` - Mounted agent-ready HTTP routes with `skipRoutes: ["/sitemap.xml"]` to avoid conflict with the existing dynamic sitemap - Added `AgentReadyWidget` and `UpdateBanner` to the frontend (floating bottom-right, dark theme) - Scaffolded `convex/agentReady/content.ts` and `convex/agentReady/analytics.ts` wrapper files - Fixed Convex push failure caused by duplicate `/sitemap.xml` route registration between the app and agent-ready --- ## v2.33.0 Released April 26, 2026 **Setup and fork install audit** - Updated `scripts/configure-fork.ts` to support all fork-config.json fields: `statsPage`, `imageLightbox`, `semanticSearch`, `dashboard`, `mcpServer`, `newsletter`, `contactForm`, `newsletterAdmin`, `aiChat`, `askAI` - Changed configure script "Next steps" from Netlify deploy to Convex self-hosted deploy - Updated all site description strings from "Built on Convex and Netlify" to "Built on Convex" across `index.html`, `convex/http.ts`, `convex/rss.ts`, and `sync-discovery-files.ts` - Moved `vite` from runtime to devDependencies in `packages/create-markdown-sync` --- ## v2.32.0 Released April 26, 2026 **Robel auth preview.30 upgrade and admin email lockdown** - Upgraded `@robelest/convex-auth` to `^0.0.4-preview.30` with first-party `github()` provider. Removed direct `arctic` dependency - Rewrote `convex/auth.ts` to use lowercase factory functions: `password()` and `github({ clientId, clientSecret })` - `isDashboardAdmin()` now treats `DASHBOARD_PRIMARY_ADMIN_EMAIL` as the sole admin gate when set. The `dashboardAdmins` table is bypassed entirely in strict mode - Non-admin authenticated users see a demo view with a denied-state banner showing the signed-in email, expected admin email, and a "Sign out and retry" button - Frontend auth uses a singleton `getConvexAuthClient()` from `@robelest/convex-auth/browser` to prevent duplicate OAuth callback verification - OAuth callback cleanup is owned by the auth library during normal login. The app only cleans stale params after a five-second unauthenticated grace period - Fixed blank page on load caused by the auth client throwing during SPA init with a stale refresh token - Fixed repeated `Invalid verification code` logs from multiple auth client instances consuming the same callback - Fixed strict admin mode falling into first-admin bootstrap when no `dashboardAdmins` rows existed --- ## v2.31.0 Released April 14, 2026 **Convex auth upgrade to 0.0.4-preview.25** - Upgraded `@robelest/convex-auth` to the latest preview with `createAuth` factory API - Migrated `convex/auth.ts` off the deprecated `Auth` class and `Portal` helper - GitHub OAuth continues to use `arctic`'s `GitHub` wrapped in `OAuth()` since the preview package does not ship a first-party `github()` provider yet - SPA client now requires `api: api.auth` when calling `createConvexAuthClient`. Added the argument to all four call sites so sign in, sign out, and refresh token flows work - Fixed blank page on load caused by the auth client rejecting during SPA init when localStorage held a stale refresh token - Documented the drift between `auth.estifanos.com` docs and the published preview in the `robel-auth` skill so future updates inspect `node_modules` exports first --- ## v2.30.0 Released April 14, 2026 **Demo mode frontmatter hardening** - Demo users now see a trimmed frontmatter field picker that only shows fields the demo mutation actually accepts - Hidden fields include `showInNav`, `featured`, `featuredOrder`, `blogFeatured`, `order`, and `docsSection` so demo content cannot be forced into the navbar or featured sections - Demo Write tab template now opens with a shorter frontmatter block and a note that demo content resets every 30 minutes --- ## v2.29.0 Released April 14, 2026 **Markdown slide presentations** - Added `slides: true` frontmatter option for posts and pages to enable presentation mode - New `SlidePresentation` component renders fullscreen slide decks from markdown content - Content splits on `---` horizontal rules into individual slides (code blocks are safely skipped) - Keyboard navigation: arrow keys, space, escape, home, end - Progress bar, slide counter, and arrow button navigation - Present button appears in post header when slides are enabled - Full markdown rendering on slides including syntax-highlighted code blocks, tables, images, and blockquotes - New blog post: "Markdown slides" documenting the feature - New blog post: "Slide template example" with a working slide deck you can present - Added `slides` field to posts and pages tables in schema, sync mutations, and sync script --- ## v2.28.0 Released April 14, 2026 **Application-level rate limiting across all endpoints** - Added `@convex-dev/rate-limiter` component with 4-tier protection covering every public endpoint - Tier 1: LLM cost protection on Ask AI, source ingest, wiki compilation, AI image gen, AI chat - Tier 2: Compute protection on VFS exec/tree, API export, full-content RSS - Tier 3: Abuse prevention on heartbeat, page views, newsletter subscribe - Tier 4: Standard protection on API posts/post, sitemap, KB endpoints, RSS, raw markdown - Centralized rate limit definitions in `convex/rateLimits.ts` with HTTP action bridge mutation - All rate-limited endpoints return HTTP 429 with `Retry-After` headers - Rate limiting docs and patterns added to `convex-virtual-fs/` README --- ## v2.27.0 Released April 14, 2026 **Footer AI discovery links and sync wiki integration** - Added `llms.txt` and `AGENTS.md` links to site footer with Robot and FileText icons - Sync discovery script now fetches wiki pages and includes wiki knowledge base section in both `llms.txt` and `AGENTS.md` - `AGENTS.md` copied to `public/` during sync for web access at `/AGENTS.md` --- ## v2.26.0 Released April 13, 2026 **Pre-deploy: docs, model migration, blog post, homepage** - Migrated all OpenAI model references from deprecated `gpt-4o` to `gpt-4.1-mini` across backend, frontend, config, and docs - New blog post: "Wiki, knowledge bases, and virtual filesystem" - "Accessing wiki data" section added to docs, dashboard docs, and AGENTS.md documenting auth vs. unauthenticated access - README features section rewritten to match homepage, "Recent updates" refreshed - AGENTS.md key features list expanded with all current capabilities - Homepage tagline rewritten to include wikis and knowledge bases - Fixed stale "Hourly" references in demo mode docs --- ## v2.25.0 Released April 13, 2026 **Demo mode, wiki UI, and sidebar polish** - Demo content cleanup cron changed from hourly to every 30 minutes - Demo banner now says "your content resets every 30 minutes" with fork repo link - Added `demo` boolean field to schema for explicit frontmatter labeling of demo content - Wiki long names now wrap properly instead of overflowing cards and nav items - Dashboard config gets a "Show wiki in nav" toggle - Wiki left sidebar restyled to match docs sidebar pattern (uppercase header, left border active state, group dividers) - Wiki right sidebar TOC restyled to match docs TOC pattern (label border, left border accent items) --- ## v2.24.0 Released April 5, 2026 **Knowledge bases and LLM knowledge base projects** Added a full knowledge base management system. Admins can create multiple KB projects, upload markdown files or Obsidian vaults, control visibility and API access per KB, and share them on the public wiki page. Each KB gets its own knowledge graph and searchable index. convex-doctor score stays at 100/100. **New features:** - Knowledge base CRUD: create, update, delete KBs with visibility and API settings - Markdown file upload: drag and drop `.md` files into any KB from the dashboard - Per-KB API endpoints: `/api/kb`, `/api/kb/pages?slug=`, `/api/kb/page?kb=&slug=` - KB switcher on the public Wiki page for browsing between site wiki and uploaded KBs - Full-text search scoped by knowledge base - Knowledge graph visualization per KB - `--kb=` flag for `npm run sync:wiki` CLI command - New tables: `knowledgeBases`, `kbUploadJobs` - `kbId` foreign key on `wikiPages`, `wikiIndex`, `wikiCompilationJobs` **Files added:** - `convex/knowledgeBases.ts` - `convex/kbUpload.ts` - `prds/knowledge-bases.md` **Files changed:** - `convex/schema.ts` (new tables, kbId fields, indexes) - `convex/wiki.ts` (kbId scoping on all queries, search, sync) - `convex/http.ts` (KB API endpoints) - `src/pages/Dashboard.tsx` (KB management section) - `src/pages/Wiki.tsx` (KB switcher) - `src/styles/global.css` (KB switcher styles) - `scripts/sync-wiki.ts` (--kb flag) --- ## v2.23.0 Released April 4, 2026 **Virtual filesystem, source ingest pipeline, and LLM wiki** Added a shell-like virtual filesystem HTTP interface, a Firecrawl powered source ingestion pipeline with OpenAI embeddings, and an LLM driven wiki compilation system. All new code passes convex-doctor at 100/100 with 0 errors and 0 warnings. **New features:** - `/vfs/tree` and `/vfs/exec` HTTP endpoints for shell command emulation (ls, cat, grep, find, tree, head, wc, pwd, cd) - Source ingest with queued job pattern: submit a URL, Firecrawl scrapes it, OpenAI generates embeddings - LLM wiki compilation: GPT-4.1 mini synthesizes interlinked wiki pages from all site content - Wiki linting: automated checks for backlinks, content length, and title presence - Daily wiki compilation cron job at 4:00 AM UTC - Five new database tables: `sources`, `sourceIngestJobs`, `wikiPages`, `wikiIndex`, `wikiCompilationJobs` - Wiki resources page with reference links **Performance:** - Virtual filesystem uses shared helper functions to avoid `ctx.runQuery` within the same module - Wiki compilation batches all page upserts, index regeneration, and job finalization into single mutations - Source processing batches mark-processed and job finalization into one mutation **Dashboard:** - New "Knowledge" sidebar section with Sources and Wiki tabs - Sources tab: ingest form (URL + title + type selector), source list with processing status, content preview panel - Wiki tab: compile/lint buttons with real-time job polling, latest job status bar, lint report viewer, wiki pages list with rendered markdown detail, backlink navigation, wiki index display **Files added:** - `convex/virtualFs.ts`, `convex/sources.ts`, `convex/sourceActions.ts` - `convex/wiki.ts`, `convex/wikiCompiler.ts`, `convex/wikiJobs.ts` - `content/pages/wiki-resources.md`, `prds/virtual-filesystem.md` **Files changed:** - `convex/schema.ts` (5 new tables with indexes) - `convex/http.ts` (2 new routes + OPTIONS handlers) - `convex/crons.ts` (daily wiki compilation cron) - `src/pages/Dashboard.tsx` (SourcesSection + WikiSection components, Knowledge nav section) --- ## v2.22.0 Released March 20, 2026 **convex-doctor 100/100 and blog post** Reached a perfect convex-doctor score across 17 remediation passes. Added a featured blog post documenting the full journey from 42/100 to 100/100. **Changes:** - 17 passes of convex-doctor remediation: security hardening, performance fixes, schema cleanup, architecture refactors - New blog post: "How convex-doctor took markdown.fast from 42 to 100" - Generated before/after comparison image and added benchmark screenshots - Added convex-doctor skill and always-on Cursor rule - Reverted `.unique()` to `.first()` in `authAdmin.ts` and `dashboardAuth.ts` (fix for duplicate row runtime errors) - Added `convex-doctor.toml` with documented suppressions for by-design patterns **Files changed:** - `content/blog/convex-doctor-score-42-to-100.md` (new featured blog post) - `public/images/convex-doctor-*.png` (3 new images) - `convex-doctor.toml` (new config) - `.cursor/skills/convex-doctor/SKILL.md` (new skill) - `.cursor/rules/convex-doctor.mdc` (new rule) - `convex/authAdmin.ts`, `convex/dashboardAuth.ts` (reverted .unique() to .first()) - 30+ Convex function files modified for security, performance, and architecture improvements --- ## v2.21.6 Released March 1, 2026 **Rybbit analytics integration** Adds Rybbit analytics for site tracking. **Changes:** - Added Rybbit analytics script to `index.html` with site ID `24731ca420a4` - Script loads with `defer` attribute to avoid blocking page rendering **Files changed:** - `index.html` (added Rybbit analytics script) --- ## v2.21.5 Released February 27, 2026 **TypeScript error fixes** Fixes TypeScript compilation errors for cleaner builds with zero errors. **Changes:** - Removed unused variables `pathsWithCounts` and `allPathsFromAggregate` in `convex/stats.ts` - Fixed `fetchpriority` to `fetchPriority` (React camelCase) in logo and header images **Files changed:** - `convex/stats.ts` (removed unused variables) - `src/components/Layout.tsx` (fetchPriority fix) - `src/pages/Home.tsx` (fetchPriority fix) - `src/pages/Post.tsx` (4 fetchPriority fixes) --- ## v2.21.4 Released February 22, 2026 **Button border radius consistency fix** Fixes inconsistent button border radius across Write page and Dashboard. **CSS changes:** - Added missing CSS variables to `:root`: `--border-radius-sm: 4px`, `--border-radius-md: 6px`, `--border-radius-lg: 8px` - Dashboard mode toggles (Markdown/Rich Text/Preview) now have consistent 6px border radius - All action buttons (Copy All, Clear, Image, Download .md, Save to DB) match **Files changed:** - `src/styles/global.css` (added border-radius CSS variables) --- ## v2.21.3 Released February 22, 2026 **Media Library and router fixes** Fixes Media Library upload and preview for all media providers, image clipping, React Router warnings, and dynamic usage text. **Media Library:** - Upload with `convex` or `r2` providers now shows image preview with MD/HTML/URL copy buttons - Recent uploads persist to `sessionStorage` so they survive page refreshes - Image previews use real Convex storage URLs instead of ephemeral blob URLs - Usage text dynamically reflects the active media provider (Bunny CDN, ConvexFS, R2, or Convex storage) - Fixed image clipping in grid: changed from square crop to 4:3 aspect ratio with full image visible **ImageUploadModal:** - Media Library tab no longer requires Bunny CDN configuration (only needs `convexfs` provider) **Other fixes:** - Added React Router v7 future flags (`v7_startTransition`, `v7_relativeSplatPath`) to eliminate deprecation warnings - Removed unused logo preload from `index.html` that caused console warnings **Files changed:** - `src/components/MediaLibrary.tsx` (recent uploads tracking, dynamic usage text, sessionStorage persistence) - `src/components/ImageUploadModal.tsx` (removed Bunny CDN gate from Media Library tab) - `src/styles/global.css` (image preview aspect ratio fix, recent uploads CSS) - `src/main.tsx` (React Router v7 future flags) - `index.html` (removed logo preload) --- ## v2.21.2 Released February 22, 2026 **Heartbeat write conflict elimination** This release eliminates write conflicts in the `activeSessions` table from rapid heartbeat mutations. **Backend changes:** - Increased `HEARTBEAT_DEDUP_MS` from 20s to 45s in `convex/stats.ts` - Backend now rejects duplicate heartbeats within 45 seconds regardless of path changes **Frontend changes:** - Increased `HEARTBEAT_INTERVAL_MS` from 30s to 45s - Increased `HEARTBEAT_DEBOUNCE_MS` from 20s to 45s - Added BroadcastChannel cross-tab coordination so only leader tab sends heartbeats - Tab leadership election with automatic handoff when tabs close - Heartbeat completely disabled when `statsPage.enabled: false` in siteConfig **Files changed:** - `convex/stats.ts` (increased dedup window) - `src/hooks/usePageTracking.ts` (BroadcastChannel coordination, timing increases) - `.cursor/rules/convex-write-conflicts.mdc` (updated app-specific patterns) - `prds/fix-heartbeat-write-conflicts.md` (new PRD) --- ## v2.21.1 Released February 21, 2026 **Stats performance optimizations** This release significantly improves stats page loading performance and reduces Convex database usage. **Performance improvements:** - Stats tracking now respects `statsPage.enabled` config. When disabled, no page views or heartbeats are recorded, eliminating all stats-related DB writes. - Removed the expensive full table scan fallback in `getStats` query. The query now trusts aggregate counts directly, improving from O(n) to O(log n) complexity. - Added `uniquePaths` aggregate component for efficient tracking of distinct pages viewed. - Paginated `pageStats` to return only the top 50 pages by views instead of all paths. **UI updates:** - Stats page now shows "Top Pages by Views" section title - Displays "(showing X of Y)" count indicator when more paths exist than displayed **Files changed:** - `src/hooks/usePageTracking.ts` (stats enabled check) - `convex/stats.ts` (removed table scan, added pagination, added uniquePaths) - `convex/convex.config.ts` (uniquePaths aggregate registration) - `src/pages/Stats.tsx` (updated section title and count display) - `src/styles/global.css` (stats-section-subtitle class) **After deploying**, run the backfill to populate the new aggregate: ```bash npx convex run stats:backfillAggregates ``` --- ## v2.21.0 Released February 21, 2026 **Convex self hosting and @robelest/convex-auth integration** Major architecture update establishing Convex self hosting and `@robelest/convex-auth` as the default deployment and authentication stack while preserving full backwards compatibility with WorkOS and Netlify. **Default architecture:** - `auth.mode: "convex-auth"` with GitHub OAuth via `@robelest/convex-auth` - `hosting.mode: "convex-self-hosted"` with `@convex-dev/self-hosting` - `media.provider: "convex"` for direct Convex storage **Legacy compatibility:** - `auth.mode: "workos"` for WorkOS AuthKit - `hosting.mode: "netlify"` for Netlify deployment - `media.provider: "convexfs"` or `"r2"` for alternate storage **New backend wiring:** - `convex/auth.ts` exports Convex Auth helpers - `convex/staticHosting.ts` provides static asset deployment APIs - `convex/http.ts` registers auth routes and static file routes - `convex/convex.config.ts` registers Auth, Self Hosting, and R2 components - `convex/r2.ts` for optional Cloudflare R2 uploads - `convex/media.ts` for provider resolution **Frontend auth refactor:** - `src/main.tsx` uses centralized auth wrapper - `src/AppWithWorkOS.tsx` handles all auth modes with proper `ConvexAuthWrapper` - Custom domain support via `VITE_CONVEX_SITE_URL` and `VITE_SITE_URL` **Dashboard admin system:** - Server-side admin authorization with `dashboardAdmins` table - Admin APIs in `convex/authAdmin.ts` for grant/revoke/list - Bootstrap command: `npx convex run authAdmin:bootstrapDashboardAdmin` - Optional strict email gate via `DASHBOARD_PRIMARY_ADMIN_EMAIL` - Auth setup status query for first-admin guidance UI **One click deploy improvements:** - GitHub template flow: Use this template, clone, run `npm install && npx convex dev --once && npm run sync && npm run deploy` - CLI flow: `npx create-markdown-sync my-site` - Updated `FORK_CONFIG.md` with admin setup instructions - Updated `fork-config.json.example` with default mode config - Validation scripts: `scripts/validate-env.ts`, `scripts/verify-deploy.ts` **Rich text editor replacement:** - Replaced Quill with lightweight `contentEditable` editor - Simple formatting toolbar (bold, italic, strike, headings, lists, quote) - Preserved Markdown, Rich Text, Preview modes - Image insertion support - Zero vulnerabilities: `npm audit --omit=dev` passes **Files changed:** - `convex/auth.ts`, `convex/authAdmin.ts`, `convex/dashboardAuth.ts` - `convex/staticHosting.ts`, `convex/media.ts`, `convex/r2.ts` - `convex/http.ts`, `convex/convex.config.ts`, `convex/schema.ts` - `src/main.tsx`, `src/AppWithWorkOS.tsx`, `src/utils/workos.ts` - `src/pages/Dashboard.tsx`, `src/config/siteConfig.ts` - `README.md`, `FORK_CONFIG.md`, `fork-config.json.example` - `scripts/validate-env.ts`, `scripts/verify-deploy.ts` - `.cursor/skills/robel-auth/SKILL.md` - `.cursor/skills/convex-self-hosting/SKILL.md` --- ## v2.20.1 Released January 11, 2026 **True delete for AI generated images** Added proper delete functionality for AI generated images in the Dashboard AI Agent section. The clear button has been replaced with a delete button that shows a confirmation dialog before permanently removing the image from both the database and Convex Storage. **Changes:** - Delete button with confirmation dialog in AI Agent image generation - Removes image from `aiGeneratedImages` table and Convex Storage - Added `by_storageId` index for efficient image lookup - Added `deleteGeneratedImage` mutation to aiChats.ts - Removed Save to Media Library feature (users can download and re-upload instead) **Files changed:** - `convex/schema.ts` - Added by_storageId index to aiGeneratedImages table - `convex/aiChats.ts` - Added deleteGeneratedImage mutation - `src/pages/Dashboard.tsx` - Updated AIAgentSection with delete button and confirmation modal - `src/styles/global.css` - Added delete button and confirmation dialog styles --- ## v2.20.0 Released January 11, 2026 **Dashboard frontmatter synchronization** All 30+ frontmatter fields now sync between the Dashboard UI and the database schema. Posts and pages editors support every available frontmatter option including docs section fields, layout options, and feature toggles. **Sync warning modal for synced content** Added a warning modal when editing content that was created via `npm run sync`. The modal explains that local file changes will overwrite dashboard edits on the next sync. Users can download or copy the markdown before editing, or choose "Save Anyway" for intentional edits. Dashboard-created content bypasses this warning. **Changes:** - Updated ContentItem interface with 19 new frontmatter fields - Updated postFrontmatterFields and pageFrontmatterFields arrays to match schema - Added SyncWarningModal component with download/copy options - Fixed missing `unlisted` field in sync-posts.ts PostFrontmatter interface - Created RC1 release blog post documenting major features **Files changed:** - `src/pages/Dashboard.tsx` - ContentItem interface, frontmatter arrays, SyncWarningModal, save handlers - `src/styles/global.css` - Sync warning modal styles - `scripts/sync-posts.ts` - Added unlisted field to PostFrontmatter interface - `content/blog/version-rc1.md` - RC1 release announcement --- ## v2.19.0 Released January 10, 2026 **npx create-markdown-sync CLI** Added a CLI tool to scaffold new markdown-sync projects with a single command. Run `npx create-markdown-sync my-site` to clone the template, configure your site through an interactive wizard, install dependencies, and set up Convex. **Changes:** - Interactive wizard with 13 sections covering all configuration options - Clones template from GitHub via giget - Configures site settings automatically (siteConfig.ts, fork-config.json) - Installs dependencies with your preferred package manager - Sets up Convex project with optional WorkOS auth (disabled by default) - Starts dev server and opens browser - Clear next steps with links to docs, deployment guide, and WorkOS setup **Files changed:** - `packages/create-markdown-sync/` - New monorepo package - `packages/create-markdown-sync/src/index.ts` - CLI entry point - `packages/create-markdown-sync/src/wizard.ts` - Interactive prompts - `packages/create-markdown-sync/src/clone.ts` - Template cloning - `packages/create-markdown-sync/src/configure.ts` - Site configuration - `packages/create-markdown-sync/src/install.ts` - Dependency installation - `packages/create-markdown-sync/src/convex-setup.ts` - Convex initialization - `packages/create-markdown-sync/src/utils.ts` - Helper utilities - `package.json` - Added workspaces configuration - `.gitignore` - Added packages/*/dist/ and packages/*/node_modules/ --- ## v2.18.2 Released January 10, 2026 **Related posts thumbnail view with toggle** Added a new thumbnail view for related posts at the bottom of blog posts. Shows post image, title, description, author avatar, author name, and date. Users can toggle between the new thumbnail view and the existing list view, with their preference saved to localStorage. **Changes:** - New thumbnail view with image on left, content on right (like attached screenshot) - Toggle button using same icons as homepage featured section - View preference saved to localStorage - Configuration via siteConfig.relatedPosts (defaultViewMode, showViewToggle) - Dashboard Config section for related posts settings **Files changed:** - `convex/posts.ts` - Updated getRelatedPosts query with image, excerpt, authorName, authorImage - `src/config/siteConfig.ts` - Added RelatedPostsConfig interface and relatedPosts config - `src/pages/Post.tsx` - Added thumbnail view, toggle state, and view mode rendering - `src/pages/Dashboard.tsx` - Added Related Posts config card in ConfigSection - `src/styles/global.css` - Added thumbnail view CSS styles --- ## v2.18.1 Released January 10, 2026 **README.md streamlined with docs links** Reduced README from 609 lines to 155 lines. Detailed documentation now lives on the live site at markdown.fast/docs. **Changes:** - Added Documentation section with link to markdown.fast/docs - Added Guides subsection with links to Setup, Fork Configuration, Dashboard, WorkOS, MCP Server, and AgentMail guides - Simplified Features section to brief summary with link to About page - Simplified Fork Configuration to quick commands with doc link - Kept sync commands, setup, and Netlify deployment sections - Removed sections now covered by live docs **Files changed:** - `README.md` - Streamlined from 609 to 155 lines --- ## v2.18.0 Released January 10, 2026 **OpenCode AI development tool integration** Added full OpenCode support to make the framework compatible with the OpenCode AI-first development tool. This works alongside existing Claude Code and Cursor integrations without conflicts. **Changes:** - Created `.opencode/` directory structure with config, agents, commands, skills, and plugins - 3 specialized agents: orchestrator (main router), content-writer, sync-manager - 6 commands: /sync, /sync-prod, /create-post, /create-page, /import, /deploy - 4 skills adapted from .claude/skills/: frontmatter, sync, convex, content - sync-helper plugin logs reminders when content files change - Documentation page at /docs-opencode **Files changed:** - `opencode.json` - Root OpenCode project configuration - `.opencode/config.json` - OpenCode app configuration - `.opencode/agent/*.md` - Agent definitions (3 files) - `.opencode/command/*.md` - Command definitions (6 files) - `.opencode/skill/*.md` - Skill documentation (4 files) - `.opencode/plugin/sync-helper.ts` - Reminder plugin - `content/pages/docs-opencode.md` - Documentation page - `files.md` - Added OpenCode Configuration section --- ## v2.17.0 Released January 10, 2026 **ConvexFS Media Library with Bunny CDN integration** Added a full-featured media library for uploading and managing images in the dashboard. Images are stored on Bunny.net Edge Storage and served via their global CDN. The Image Insert modal now supports selecting from existing media and choosing image sizes. **Changes:** - Upload images via drag-and-drop or click to upload - Copy images as Markdown, HTML, or direct URL - Bulk select and delete multiple images at once - Media Library tab in Image Insert modal for selecting existing images - Size presets: Original, Large (1200px), Medium (800px), Small (400px), Thumbnail (200px), Custom - Image dimensions displayed before insert with aspect ratio preserved - File expiration support for automatic cleanup - Configuration warning when Bunny CDN not set up **Files changed:** - `convex/convex.config.ts` - Added ConvexFS component - `convex/fs.ts` - ConvexFS instance with Bunny CDN config - `convex/files.ts` - File mutations and queries - `convex/http.ts` - ConvexFS routes for upload/download - `src/components/MediaLibrary.tsx` - Media library gallery - `src/components/ImageUploadModal.tsx` - Enhanced modal with library and sizes - `src/styles/global.css` - Media library and modal styles - `content/pages/docs-media-setup.md` - Setup documentation --- ## v2.16.4 Released January 10, 2026 **AI image generation download and copy options** Added download and copy functionality to the Dashboard AI Agent image generation section. After generating an image with Nano Banana, users can now download the image or copy Markdown/HTML code for embedding. **Changes:** - Download button saves generated image to computer with filename from prompt - MD button copies Markdown code (`![prompt](url)`) to clipboard - HTML button copies HTML code (`prompt`) to clipboard - Code preview section displays both Markdown and HTML snippets - Visual feedback when code is copied (button changes to "Copied") **Files changed:** - `src/pages/Dashboard.tsx` - Added download/copy handlers and updated UI - `src/styles/global.css` - Added CSS for action buttons and code preview --- ## v2.16.3 Released January 10, 2026 **Social icons in hamburger menu and Dashboard Config alignment** Moved social icons from mobile header to hamburger menu for cleaner mobile UI. Added Dashboard Config options for `socialFooter.showInHeader` and `askAI.enabled`. Added configuration alignment documentation for AI/LLMs. **Changes:** - Social icons now appear in hamburger menu below navigation links (mobile only) - Removed social icons from mobile header (cleaner mobile UI) - Added `socialFooter.showInHeader` toggle to Dashboard Config Social Footer card - Added new Ask AI config card with `askAI.enabled` toggle in Dashboard Config - Added "Configuration alignment" section to CLAUDE.md for AI/LLM guidance - Added sync comments to siteConfig.ts and Dashboard.tsx ConfigSection **Files changed:** - `src/components/MobileMenu.tsx` - Added social icons section - `src/components/Layout.tsx` - Removed social icons from mobile-nav-controls - `src/pages/Dashboard.tsx` - Added socialFooterShowInHeader and askAIEnabled config - `src/styles/global.css` - Added mobile-menu-social CSS styles - `src/config/siteConfig.ts` - Added alignment comment - `CLAUDE.md` - Added Configuration alignment section --- ## v2.16.2 Released January 10, 2026 **Ask AI documentation alignment** Aligned Ask AI configuration across all config and documentation files. The Ask AI feature (header chat with RAG) is now properly documented alongside AI Agent and AI Dashboard features. **Changes:** - Added `askAI` config to `fork-config.json.example` - Added Ask AI Configuration section to `FORK_CONFIG.md` - Added Ask AI (header chat) section to `docs-dashboard.md` - Added Ask AI (header chat) section to `how-to-use-the-markdown-sync-dashboard.md` **Files changed:** - `fork-config.json.example` - Added askAI config block - `FORK_CONFIG.md` - Added Ask AI Configuration section - `content/pages/docs-dashboard.md` - Added Ask AI documentation - `content/blog/how-to-use-the-markdown-sync-dashboard.md` - Added Ask AI setup guide --- ## v2.16.1 Released January 10, 2026 **Docs layout scrollbar hiding** Hidden scrollbars on the docs section layout while preserving scroll functionality. Cleaner UI that matches the design without visible scrollbars. **Fixes:** - Left sidebar scrolls but no scrollbar visible - Right sidebar scrolls but no scrollbar visible - Main docs content scrolls but no scrollbar visible - No browser page scrollbar on docs pages - Scrolling works via trackpad, mouse wheel, and touch **Technical:** - Added `body:has(.docs-layout) { overflow: hidden; }` to prevent page-level scroll - Added scrollbar hiding rules for `.docs-sidebar-left`, `.docs-sidebar-right`, `.docs-content` - Cross-browser support: `-ms-overflow-style: none` (IE/Edge), `scrollbar-width: none` (Firefox), `::-webkit-scrollbar { width: 0 }` (Chrome/Safari) **Files changed:** - `src/styles/global.css` - Added scrollbar hiding rules and body overflow rule --- ## v2.16.0 Released January 9, 2026 **Version control system** Added a Sync version control system for tracking changes to posts, pages, home content, and footer. **Features:** - 3-day version history for all content - Dashboard toggle to enable/disable version control - Version history modal with unified diff visualization - Preview mode to view previous version content - One-click restore with automatic backup of current state - Automatic cleanup of versions older than 3 days (daily cron at 3 AM UTC) - Version stats display in Config section **How to use:** 1. Navigate to Dashboard > Config 2. Find the "Version Control" card 3. Toggle "Enable version control" on 4. Edit posts/pages or run sync commands to capture versions 5. Click the History button in the editor to view version history 6. Select a version to view diff or preview, then click "Restore This Version" **Technical:** - New `convex/versions.ts` with 7 functions (isEnabled, setEnabled, createVersion, getVersionHistory, getVersion, restoreVersion, cleanupOldVersions, getStats) - New `contentVersions` table with indexes for efficient queries - New `versionControlSettings` table for toggle state - New `VersionHistoryModal.tsx` component using existing DiffCodeBlock - Version capture integrated into cms.ts, posts.ts, and pages.ts - Cleanup cron job in crons.ts **Files changed:** - `convex/schema.ts` - Added contentVersions and versionControlSettings tables - `convex/versions.ts` - New file with all version control logic - `convex/cms.ts` - Added version capture before dashboard edits - `convex/posts.ts` - Added version capture before sync updates - `convex/pages.ts` - Added version capture before sync updates - `convex/crons.ts` - Added daily cleanup job - `src/components/VersionHistoryModal.tsx` - New version history modal - `src/pages/Dashboard.tsx` - Added Version Control config card and History button - `src/styles/global.css` - Added ~370 lines of version modal CSS --- ## v2.15.3 Released January 9, 2026 **Footer not displaying on /docs landing page fix** Fixed an issue where the footer was not displaying on the `/docs` landing page even when `showFooter: true` was set in the frontmatter. The `DocsPage.tsx` component (which handles the `/docs` route with `docsLanding: true`) was missing the Footer component entirely. **Fixes:** - Added Footer component to DocsPage.tsx - Footer now respects `showFooter` frontmatter field on docs landing pages - Added AI chat support to docs landing page via `aiChatEnabled` and `pageContent` props **Technical:** - Added `Footer` import and `footerPage` query to fetch footer content - Added footer rendering logic after BlogPost component (same pattern as Post.tsx) - Updated `getDocsLandingPage` query in `convex/pages.ts` to return `showFooter`, `footer`, `excerpt`, and `aiChat` fields - Updated `getDocsLandingPost` query in `convex/posts.ts` to return `showFooter`, `footer`, and `aiChat` fields **Files changed:** - `src/pages/DocsPage.tsx` - Added Footer component and rendering logic - `convex/pages.ts` - Updated getDocsLandingPage query return fields - `convex/posts.ts` - Updated getDocsLandingPost query return fields --- ## v2.15.2 Released January 8, 2026 **Docs layout CSS conflict fix** Fixed a CSS conflict where the `.main-content` container was constraining the docs section layout to 800px max-width, preventing the three-column layout (left sidebar, content, right sidebar) from displaying correctly. **Fixes:** - Left sidebar now properly flush left at `left: 0` - Right sidebar now properly flush right at `right: 0` - Docs content area properly positioned between sidebars - Responsive margins adjusted for all breakpoints **Technical:** - Added `.main-content:has(.docs-layout)` CSS rule to expand to 100% width - Updated Layout.tsx to use `main-content-wide` class for docs pages - Fixed `.docs-content` margins: 280px (desktop), 240px (small tablet), 0 (mobile) - Added responsive margin adjustments at 1200px, 900px, 768px breakpoints **Files changed:** - `src/styles/global.css` - Added docs layout override, fixed margin values - `src/components/Layout.tsx` - Added isDocsPage check for main-content-wide --- ## v2.15.1 Released January 8, 2026 **Additional Core Web Vitals CLS and INP improvements** Continued performance improvements targeting Cumulative Layout Shift (CLS), Largest Contentful Paint (LCP), and Interaction to Next Paint (INP). **CLS Fixes:** - Added `aspect-ratio: 16/10` to `.blog-image` to reserve space before images load - Added `aspect-ratio: 16/9` to `.post-header-image-img` to prevent header image layout shift - Added `contain: layout style` to `.main-content` and `.main-content-wide` to isolate layout recalculations **LCP Improvements:** - Added `fetchPriority="high"` to logo image in Layout.tsx for faster loading - Added `fetchPriority="high"` to header images (showImageAtTop) in Post.tsx **INP/Animation Improvements:** - Added `will-change: transform` to continuous spin animations: - `.spinner-icon` - `.animate-spin` - `.ai-chat-spinner` - `.ai-image-spinner` - `.spinning` - `.dashboard-import-btn .spin` - Added `will-change: transform` to `.logo-marquee-track` for smoother marquee - Added `will-change: opacity` to `.visitor-map-badge-dot` for pulse animation **Files changed:** - `src/styles/global.css` - CLS prevention, CSS containment, animation will-change hints - `src/components/Layout.tsx` - fetchPriority on logo - `src/pages/Post.tsx` - fetchPriority on header images --- ## v2.15.0 Released January 7, 2026 **Export as PDF** Added PDF export option to CopyPageDropdown. Users can now export any blog post or page as a clean, formatted PDF document using the browser's native print dialog. **Features:** - Export as PDF button in Copy page dropdown (positioned at end of menu) - Clean formatted output without markdown syntax - Title displayed as proper heading - Metadata shown on single line (date, read time, tags) - Content with markdown stripped for readable document - Uses Phosphor FilePdf icon **Technical:** - Added `formatForPrint` function to strip markdown syntax (headings, bold, italic, code, links, blockquotes) - Added `handleExportPDF` handler that opens styled print window - Imports `FilePdf` from `@phosphor-icons/react` (already installed in project) **Files changed:** - `src/components/CopyPageDropdown.tsx` - New PDF export functionality --- ## v2.14.1 Released January 7, 2026 **Additional Core Web Vitals animation fixes** Continued performance improvements targeting non-composited animations identified by PageSpeed Insights. **Fixes:** - Fixed `docs-skeleton-pulse` animation: Converted from `background-position` (non-composited) to pseudo-element with `transform: translateX()` (GPU-composited) - Added `will-change` hints to 6 more animated elements for GPU compositing **Elements with new will-change hints:** - `.image-lightbox-backdrop` - will-change: opacity - `.search-modal` - will-change: transform, opacity - `.ai-chat-message` - will-change: transform, opacity - `.dashboard-toast` - will-change: transform, opacity - `.ask-ai-modal` - will-change: transform, opacity - `.docs-article` - will-change: opacity **Files changed:** - `src/styles/global.css` - Skeleton animation fix, additional will-change hints --- ## v2.14.0 Released January 7, 2026 **Core Web Vitals performance optimizations** Fixes for PageSpeed Insights failures on mobile and desktop. These changes improve Largest Contentful Paint (LCP) and eliminate non-composited animation warnings. **Fixes:** - Non-composited animations: Visitor map pulse animations now use GPU-composited `transform: scale()` instead of animating SVG `r` attribute - Duplicate keyframes: Removed 5 redundant `@keyframes spin` definitions from CSS - GPU compositing hints: Added `will-change` to animated elements (theme toggle, dropdown menus, modals, scroll-to-top button) **Performance additions:** - Critical CSS inlined in index.html (~2KB) for instant first paint - Theme variables, reset styles, layout skeleton, and navigation pre-loaded - Additional preconnect hints for Convex site endpoints **Files changed:** - `src/styles/global.css` - Animation fixes, will-change hints, removed duplicates - `src/components/VisitorMap.tsx` - Updated SVG circle radius for transform-based animation - `index.html` - Inline critical CSS, resource hints --- ## v2.13.0 Released January 7, 2026 **Enhanced diff code block rendering** Diff and patch code blocks now render with enhanced visualization powered by @pierre/diffs. This brings Shiki-based syntax highlighting specifically designed for showing code changes. **Features:** - Unified view (default): Single column with +/- indicators - Split view: Side-by-side comparison of old and new code - View toggle button to switch between modes - Theme-aware colors matching dark/light/tan/cloud themes - Copy button for copying raw diff content - Automatic routing: Use `diff or `patch in markdown **New documentation:** - Blog post: "How to Use Code Blocks" with examples of regular code blocks and diff rendering **Technical:** - Added `@pierre/diffs` package - Created `DiffCodeBlock` component (`src/components/DiffCodeBlock.tsx`) - Updated `BlogPost.tsx` to route diff/patch blocks to new renderer - Added diff block CSS styles to `global.css` - Added `vendor-diffs` chunk to Vite config --- ## v2.12.0 Released January 7, 2026 **Canonical URL fix for search engines (GitHub Issue #6)** Fixed a mismatch where raw HTML was showing the homepage canonical URL instead of the page-specific canonical URL. Search engines that check raw HTML before rendering JavaScript now receive the correct canonical tags. **Changes:** - Added search engine bot detection (Google, Bing, DuckDuckGo, etc.) to serve pre-rendered HTML - Search engines now receive correct canonical URLs in the initial HTML response - Added SEO Bot Configuration documentation in FORK_CONFIG.md and setup-guide.md - Bot detection arrays are easily customizable in `netlify/edge-functions/botMeta.ts` **For forkers:** The bot detection configuration is documented with clear comments at the top of `botMeta.ts`. You can customize which bots receive pre-rendered HTML by editing the `SOCIAL_PREVIEW_BOTS`, `SEARCH_ENGINE_BOTS`, and `AI_CRAWLERS` arrays. --- ## v2.11.0 Released January 6, 2026 **Ask AI header button with RAG-based Q&A** New header button that opens a chat modal for asking questions about site content. Uses semantic search to find relevant posts and pages, then generates AI responses with source citations. **Features:** - Header button with sparkle icon (before search button) - Keyboard shortcuts: Cmd+J or Cmd+/ (Mac), Ctrl+J or Ctrl+/ (Windows/Linux) - Real-time streaming responses via Convex Persistent Text Streaming - Model selector: Claude Sonnet 4 (default) or GPT-4.1 mini - Markdown rendering with syntax highlighting - Internal links use React Router for seamless navigation - Source citations with links to referenced content - Copy response button (hover to reveal) for copying AI answers - Chat history within session (clears on page refresh) - Clear chat button to reset conversation **How it works:** 1. User question is stored in database with session ID 2. Query is converted to embedding using OpenAI text-embedding-ada-002 3. Vector search finds top 5 relevant posts/pages 4. Content is sent to selected AI model with RAG system prompt 5. Response streams in real-time with source citations appended **Configuration:** Enable in `src/config/siteConfig.ts`: ```typescript askAI: { enabled: true, defaultModel: "claude-sonnet-4-20250514", models: [ { id: "claude-sonnet-4-20250514", name: "Claude Sonnet 4", provider: "anthropic" }, { id: "gpt-4.1-mini", name: "GPT-4.1 mini", provider: "openai" }, ], }, ``` **Requirements:** - `semanticSearch.enabled: true` (for embeddings) - `OPENAI_API_KEY` in Convex (for embeddings) - `ANTHROPIC_API_KEY` in Convex (for Claude models) - Run `npm run sync` to generate embeddings **Technical details:** - New component: `src/components/AskAIModal.tsx` - New Convex files: `convex/askAI.ts` (mutations/queries), `convex/askAI.node.ts` (HTTP action) - New table: `askAISessions` with `by_stream` index - HTTP endpoint: `/ask-ai-stream` for streaming responses - Uses `@convex-dev/persistent-text-streaming` component - Separated Node.js runtime (askAI.node.ts) from regular runtime (askAI.ts) Updated files: `convex/schema.ts`, `convex/askAI.ts`, `convex/askAI.node.ts`, `convex/http.ts`, `convex/convex.config.ts`, `src/components/AskAIModal.tsx`, `src/components/Layout.tsx`, `src/config/siteConfig.ts`, `src/styles/global.css` ## v2.10.2 Released January 6, 2026 **SEO fixes for GitHub Issue #4** Seven SEO issues resolved to improve search engine optimization: 1. **Canonical URL** - Dynamic canonical link tags added client-side for posts and pages 2. **Single H1 per page** - Markdown H1s demoted to H2 elements with `.blog-h1-demoted` class (maintains H1 visual styling) 3. **DOM order fix** - Article now loads before sidebar in DOM for better SEO (CSS `order` property maintains visual layout) 4. **X-Robots-Tag** - HTTP header added via netlify.toml (public routes indexed, dashboard/API routes noindexed) 5. **Hreflang tags** - Self-referencing hreflang (en, x-default) for language targeting 6. **og:url consistency** - Uses same canonicalUrl variable as canonical link tag 7. **twitter:site** - New `TwitterConfig` in siteConfig.ts for Twitter Cards **Configuration:** Add your Twitter handle in `src/config/siteConfig.ts`: ```typescript twitter: { site: "@yourhandle", creator: "@yourhandle", }, ``` **Updated files:** `src/config/siteConfig.ts`, `src/pages/Post.tsx`, `src/components/BlogPost.tsx`, `src/styles/global.css`, `convex/http.ts`, `netlify.toml`, `index.html`, `fork-config.json.example` ## v2.10.1 Released January 5, 2026 **Optional semantic search configuration** Semantic search can now be disabled via `siteConfig.semanticSearch.enabled`: ```typescript semanticSearch: { enabled: false, // Disable semantic search, use keyword only }, ``` When disabled: - Search modal shows only keyword search (no mode toggle) - Embedding generation skipped during sync (saves API costs) - Existing embeddings preserved in database (no data loss) Default is `enabled: false` (keyword search only, no API key required). Set to `true` and configure OPENAI_API_KEY to enable semantic search. Updated files: `src/config/siteConfig.ts`, `src/components/SearchModal.tsx`, `scripts/sync-posts.ts`, `src/pages/Dashboard.tsx`, `FORK_CONFIG.md`, `fork-config.json.example`, `content/pages/docs-semantic-search.md`, `content/pages/docs.md` ## v2.10.0 Released January 5, 2026 **Semantic search with vector embeddings** Search now supports two modes accessible via Cmd+K: - **Keyword search** (existing) - Matches exact words using Convex full-text search. Instant, free, supports highlighting. - **Semantic search** (new) - Finds content by meaning using OpenAI embeddings. Toggle to "Semantic" mode in search modal. **How semantic search works:** 1. Your query is converted to a 1536-dimension vector using OpenAI text-embedding-ada-002 2. Convex compares this vector to stored embeddings for all posts and pages 3. Results ranked by similarity score (displayed as percentage) 4. Top 15 results returned **When to use each mode:** | Use Case | Mode | | ----------------------------------------- | -------- | | Specific code, commands, exact phrases | Keyword | | Conceptual questions ("how do I deploy?") | Semantic | | Need to highlight matches on page | Keyword | | Not sure of exact terminology | Semantic | **Configuration:** Semantic search requires an OpenAI API key: ```bash npx convex env set OPENAI_API_KEY sk-your-key-here npm run sync # Generates embeddings for all content ``` If OPENAI_API_KEY is not configured, semantic search returns empty results and keyword search continues to work normally. **Technical details:** - New files: `convex/embeddings.ts`, `convex/embeddingsQueries.ts`, `convex/semanticSearch.ts`, `convex/semanticSearchQueries.ts` - Added `embedding` field and `by_embedding` vector index to posts and pages tables - SearchModal.tsx updated with Keyword/Semantic toggle (TextAa and Brain icons) - Embeddings generated automatically during `npm run sync` - Cost: ~$0.0001 per search query (embedding generation) Updated files: `convex/schema.ts`, `convex/embeddings.ts`, `convex/embeddingsQueries.ts`, `convex/semanticSearch.ts`, `convex/semanticSearchQueries.ts`, `src/compone [Read the complete markdown](/raw/changelog.md) ## Frontmatter Options URL: https://waynesutton.ai/docs-frontmatter ## Frontmatter Options Frontmatter is the YAML metadata at the top of each markdown file between `---` markers. It controls how content is displayed, organized, and discovered. ## Blog post fields | Field | Required | Description | | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `title` | Yes | Post title | | `description` | Yes | SEO description | | `date` | Yes | YYYY-MM-DD format | | `slug` | Yes | URL path (unique) | | `published` | Yes | `true` to show | | `tags` | Yes | Array of strings | | `readTime` | No | Display time estimate | | `image` | No | OG image and featured card thumbnail. See [Using Images in Blog Posts](/using-images-in-posts) for markdown and HTML syntax | | `ogImage` | No | Social share image override. Only changes the Open Graph and Twitter preview image; cards and headers keep using `image`. Set `ogImage: false` to disable the share image entirely. | | `noOgImage` | No | Set `true` for a text-only share preview (no image). Social previews show just the title and description. Same effect as `ogImage: false`. | | `showImageAtTop` | No | Set `true` to display the image at the top of the post above the header (default: `false`) | | `excerpt` | No | Short text for card view | | `featured` | No | `true` to show in the homepage featured section (its heading comes from `siteConfig.featuredTitle`). Requires `published: true` and no `unlisted: true`. | | `featuredOrder` | No | Order in the homepage featured section (lower = first) | | `authorName` | No | Author display name shown next to date | | `authorImage` | No | Round author avatar image URL | | `layout` | No | Set to `"sidebar"` for docs-style layout with TOC | | `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) | | `showFooter` | No | Show footer on this post (overrides siteConfig default) | | `footer` | No | Per-post closing note markdown (wins over Site Config copy and `footer.md`) | | `showSocialFooter` | No | Show social footer on this post (overrides siteConfig default) | | `aiChat` | No | Enable AI chat in right sidebar. Set `true` to enable (requires `rightSidebar: true` and `siteConfig.aiChat.enabledOnContent: true`). Set `false` to explicitly hide even if global config is enabled. | | `blogFeatured` | No | Show as featured on blog page (first becomes hero, rest in 2-column row) | | `newsletter` | No | Override newsletter signup display (`true` to show, `false` to hide) | | `contactForm` | No | Enable contact form on this post | | `unlisted` | No | Hide from listings but allow direct access via slug. Set `true` to hide from blog listings, featured sections, tag pages, search results, related posts, sitemap, RSS, and API listings. The post remains accessible via direct link and serves a `noindex, nofollow` robots meta tag so search engines skip it. | | `aiWritten` | No | Posts only. Set `true` to show a small note under the title: "This post was written with AI and proofed by a human." Set `false` to hide it. This field overrules the Drafts Inbox Written with AI default. Omitted means no note. | | `audio` | No | Posts only. `true` shows the listen player under the title and, on save or sync of a published post, generates the reading. `false` hides it. Omitted uses the Site Config default, which is on. Works on existing posts the same way: set it and save, or add it to the markdown file and run sync. | | `audioVoice` | No | Posts only. `male` or `female`. Omitted uses the Site Config default voice (female). Changing the voice on a published post regenerates the file on the next save or sync. | | `minimap` | No | Posts only. Set `true` to render a right-side heading outline (h1 to h6) that highlights the current section as the reader scrolls. Needs at least one heading. The rail sits in the right margin so the article stays centered. Hidden below 1135px, where the headings move into the mobile menu. Shown instead of `rightSidebar` when both are on. Default: `false`. | | `hideNav` | No | Posts only. Set `true` to let the site navigation bar scroll away with the page instead of staying pinned to the top. The nav still shows when the reader is at the top of the post. Default: `false`. | | `docsSection` | No | Include in docs sidebar. Set `true` to show in the docs section navigation. | | `docsSectionGroup` | No | Group name for docs sidebar. Posts with the same group name appear together. | | `docsSectionOrder` | No | Order within docs group. Lower numbers appear first within the group. | | `docsSectionGroupOrder` | No | Order of the group in docs sidebar. Lower numbers make the group appear first. Groups without this field sort alphabetically. | | `docsSectionGroupIcon` | No | Phosphor icon name for docs sidebar group (e.g., "Rocket", "Book", "PuzzlePiece"). Icon appears left of the group title. See [Phosphor Icons](https://phosphoricons.com) for available icons. | | `docsLanding` | No | Set `true` to use this post as the docs landing page (shown when navigating to `/docs`). | | `slides` | No | Enable slide presentation mode. Set `true` to add a Present button that launches fullscreen slides. Content splits on `---` horizontal rules. | ## Page fields | Field | Required | Description | | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `title` | Yes | Nav link text | | `slug` | Yes | URL path | | `published` | Yes | `true` to show | | `order` | No | Nav order (lower = first) | | `showInNav` | No | Show in navigation menu (default: `true`) | | `excerpt` | No | Short text for card view | | `image` | No | Thumbnail for featured card view | | `ogImage` | No | Social share image override. Only changes the Open Graph and Twitter preview image; cards keep using `image`. Set `ogImage: false` to disable the share image entirely. | | `noOgImage` | No | Set `true` for a text-only share preview (no image). Social previews show just the title and description. Same effect as `ogImage: false`. | | `showImageAtTop` | No | Set `true` to display the image at the top of the page above the header (default: `false`) | | `featured` | No | `true` to show in the homepage featured section (its heading comes from `siteConfig.featuredTitle`). Requires `published: true` and no `unlisted: true`. | | `featuredOrder` | No | Order in the homepage featured section (lower = first) | | `authorName` | No | Author display name shown next to date | | `authorImage` | No | Round author avatar image URL | | `layout` | No | Set to `"sidebar"` for docs-style layout with TOC | | `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) | | `showFooter` | No | Show footer on this page (overrides siteConfig default) | | `footer` | No | Per-page closing note markdown (wins over Site Config copy and `footer.md`) | | `showSocialFooter` | No | Show social footer on this page (overrides siteConfig default) | | `aiChat` | No | Enable AI chat in right sidebar. Set `true` to enable (requires `rightSidebar: true` and `siteConfig.aiChat.enabledOnContent: true`). Set `false` to explicitly hide even if global config is enabled. | | `newsletter` | No | Override newsletter signup display (`true` to show, `false` to hide) | | `contactForm` | No | Enable contact form on this page | | `unlisted` | No | Hide from listings but allow direct access via slug. Set `true` to hide from navigation, featured sections, search results, sitemap, and API listings. The page remains accessible via direct link and serves a `noindex, nofollow` robots meta tag so search engines skip it. | | `textAlign` | No | Text alignment: "left" (default), "center", or "right". Used by `home.md` for home intro alignment | | `docsSection` | No | Include in docs sidebar. Set `true` to show in the docs section navigation. | | `docsSectionGroup` | No | Group name for docs sidebar. Pages with the same group name appear together. | | `docsSectionOrder` | No | Order within docs group. Lower numbers appear first within the group. | | `docsSectionGroupOrder` | No | Order of the group in docs sidebar. Lower numbers make the group appear first. Groups without this field sort alphabetically. | | `docsSectionGroupIcon` | No | Phosphor icon name for docs sidebar group (e.g., "Rocket", "Book", "PuzzlePiece"). Icon appears left of the group title. See [Phosphor Icons](https://phosphoricons.com) for available icons. | | `docsLanding` | No | Set `true` to use this page as the docs landing page (shown when navigating to `/docs`). | | `slides` | No | Enable slide presentation mode. Set `true` to add a Present button that launches fullscreen slides. Content splits on `---` horizontal rules. | ## Common patterns ### Hide pages from navigation Set `showInNav: false` to keep a page published and accessible via direct URL, but hidden from the navigation menu. Pages with `showInNav: false` remain searchable and available via API endpoints. Useful for pages you want to link directly but not show in the main nav. ### Unlisted posts and pages Set `unlisted: true` to hide a post or page from all listings while keeping it live at its direct URL. Unlisted content is excluded from: blog listings (`/blog` page), navigation, featured sections, tag pages (`/tags/[tag]`), search results (Command+K), related posts, the sitemap, RSS feeds, and API listings. It also serves a `noindex, nofollow` robots meta tag and an `X-Robots-Tag: noindex` header on API and raw markdown responses so Google will not index it. Anyone with the link can still view and share it. Your unlisted URLs are listed in the dashboard under Posts and Pages using the Unlisted filter tab, with a copy link button on each row. Unpublished (`published: false`) remains the only truly private state. ### Control the social share image Three ways to control what social previews show, without touching cards or headers: ```yaml # Use a different image for social previews only image: "/images/card-thumbnail.png" ogImage: "/images/share-wide.png" # Text-only preview (title and description, no image) noOgImage: true # Shorthand for the same text-only behavior ogImage: false ``` When the share image is disabled, the Twitter card switches from `summary_large_image` to `summary` so the preview renders cleanly as text. If neither `ogImage` nor `image` is set, the site default OG image is used. You can also set these from the dashboard editor under More options, which includes upload buttons for both the featured image and the share image. ### Show image at top Add `showImageAtTop: true` to display the `image` field at the top of the post/page above the header. Default behavior: if `showImageAtTop` is not set or `false`, image only used for Open Graph previews and featured card thumbnails. ### Image lightbox Images in blog posts and pages automatically open in a full-screen lightbox when clicked (if enabled in `siteConfig.imageLightbox.enabled`). This allows readers to view images at full size. The lightbox can be closed by clicking outside the image, pressing Escape, or clicking the close button. ### Text alignment Use `textAlign` field to control text alignment for page content. Options: `"left"` (default), `"center"`, or `"right"`. Used by `home.md` to control home intro alignment. ### Docs section To add content to the docs sidebar: 1. Add `docsSection: true` to frontmatter 2. Optionally set `docsSectionGroup` to group related content 3. Use `docsSectionOrder` to control order within groups 4. Use `docsSectionGroupOrder` to control group order 5. Add `docsSectionGroupIcon` for visual icons (Phosphor icons) ### Docs landing page Set `docsLanding: true` on one post or page to make it the docs landing page. This content displays when navigating to `/docs`. ### Slide presentations Set `slides: true` on any post or page to enable presentation mode. A Present button appears in the post header. Clicking it opens a fullscreen overlay where each `---` horizontal rule in your markdown becomes a slide boundary. Navigate with arrow keys, space bar, or the on-screen buttons. Press Escape to exit. The post still renders normally as a readable article by default. See the [slide template example](/slide-template-example) for a working demo. ## Footer URL: https://waynesutton.ai/footer Connect with me on [Twitter/X](https://x.com/waynesutton), [LinkedIn](https://www.linkedin.com/in/waynesutton/), and [GitHub](https://github.com/waynesutton). ## Home Intro URL: https://waynesutton.ai/home-intro ### Builder Operator | Developer Communities | Startup Programs | Adv Motorcycle Rider I build developer communities. At [Convex](https://convex.dev), I run programs like Convex Champions and Convex For Startups, organize events, and manage our Discord. I've spent 15 years doing this across 100+ events in 50+ cities, working with startups and Fortune 500s. The goal is always the same: help developers connect, share feedback, and build things together. I write about tech, life, and AI here. When I'm not working, I'm on my adventure motorcycle or finding excuses to meet more builders and developers. ## Projects URL: https://waynesutton.ai/projects # Projects ## [OpenSync](https://www.opensync.dev/) Cloud dashboards that sync session activity, tool usage, and token spend. Build and export eval datasets across projects. [Repo](https://github.com/waynesutton/opensync) ## [Markdown Sync](https://www.markdown.fast/) Open-source publishing framework for developers and AI agents. Write content, run sync, every browser updates instantly. [Repo](https://github.com/waynesutton/markdown-site) ## [Convex Components Directory](https://www.convex.dev/components) Approval and submissions convex components directory [Repo](https://github.com/get-convex/components-submissions-directory) ## [AI Agent Ready Convex component](https://quixotic-viper-800.convex.site/) A Convex component that makes your app readable by AI agents [Repo](https://github.com/waynesutton/agent-ready-component) ## Grok Bot to AgentMail: How a walk and yapping becomes a post. URL: https://waynesutton.ai/grokbot-agentmail-blog-covnex-setup # The walk already had the idea Ideas come when you’re walking, not when you’re sitting at your editor. The problem isn’t forgetting the idea. It’s the toolchain waiting for you to become a full-fledged writer after inspiration hits. Traditional CMS and chat apps ask you to stop what you’re doing. To engage in a different mindset. That’s friction. A chat app might keep a note, but a blog CMS usually waits for the later version of you — the one who sits down. What if the proof could come back first? ## You already have an app for this Sure, OpenAI, Claude, ChatGPT, and Grok all have apps. They help you talk to AI. You’ve tried frameworks and repos. Scripts to run, tools to set up, and hacks to stitch together. That’s the old way. Complex and developer-only. Grok Bot feels different. It’s immediate. It just works. Download it. Type. It gets the work done. No config hoops. No setup mess. It vibes with everyday people. Not superheroes, not pros, just you. It fits into your walk. That’s the future: agents that work for humans, not frameworks humans have to build. ## An agent with a computer Grok Bot is not just chat that drafts. It’s an agent with a cloud computer on standby. Named bots have skills. Persistent state. Filesystem. Terminal access. They sign into your tools. They ping you only when they need approval. This is real stuff, fresh out of beta. Desktop, iOS. You address bots with @. Plugins live in Settings. It’s early days and I’m already using it daily. ## I yap. Notes still count. Writing to a blog starts with talking. I walk, I yap, I talk random ideas. Voice transcription captures it all. Inside Grok Bot, I have a Blog bot wired to Gmail. I speak. Wespen, a custom writing skill, turns those yaps into posts in my voice. The flow is fixed: Grok Bot → Blog bot → Wespen skill → Gmail connector → AgentMail → Convex blog site. Each step is seamless. The app listens. The AI drafts. I approve. ## The site has to know who sent it waynesutton.ai runs on Convex. AgentMail powers email infrastructure for AI agents. Each bot can send, receive, and thread emails like a real inbox. The site only accepts publishing emails from Grok Bot through AgentMail API with Convex environment variables. This allowlist makes sure only trusted agent mail publishes posts. ## Then a proof comes back When AgentMail sends a post to the site, it lands as a draft unless auto-publish is enabled. An AI proof reply asks: publish, reject, or edit. No need to open CMS or editor. Just answer the proof. This tight loop keeps momentum flowing. ## Why this is not slop The key is skilled agents, not generic AI sludge. Wespen’s writing skill keeps posts aligned with my tone and style. I review every draft. The proof ensures quality before sitting down to write. This saves huge time. The idea moves forward immediately. No blank page anxiety. ## Give publishing an inbox If you’re already talking to an agent, run publishing through an inbox and a review step. Speak the post aloud. AI drafts it. Email carries it to your site. The proof arrives. Publish or reject. The walk already had the idea. The proof finds you later. That is where blogging with AI begins. ## About URL: https://waynesutton.ai/about --- I build developer communities. At Convex, I run programs like Convex Champions and Convex For Startups, organize meetups, and manage our Discord. I've spent 15 years doing this—100+ events across 50+ cities, working with startups and Fortune 500s. The goal is always the same: help developers connect, share feedback, and build things together. When I'm not working, I'm on my adventure motorcycle or finding excuses to meet more founders and developers in person.
Long Bio I'm Wayne Sutton. I help startups build developer communities through strategy, events, and operations. As Head of Community and Events at Convex, I lead Convex Champions and Convex For Startups, organize developer meetups with partners, and manage our Discord community. The goal: create a space where developers collaborate, get technical support, and showcase what they build. I've spent over 15 years in this space. I've launched programs to support startups and developers, hosted virtual meetups and talks, and partnered with YouTube creators and influencers to help developers learn Convex and ship projects with it. Events are core to what I do. I've organized and managed over 100 virtual and in-person events across 50+ cities, bringing together more than 50,000 attendees. I've run conferences with million-dollar budgets and partnered with organizations from early-stage startups to Fortune 500 companies. Every event I touch is designed to run smoothly and deliver real value to attendees. Before Convex, I mentored startups, built programs to support emerging tech founders, and consulted with Fortune 500s on growth and marketing strategy. Outside of work, I live in the Bay Area with my wife and cat. I ride my adventure motorcycle across California, stay active, and look for excuses to connect with founders and developers in person. --- **Specialties:** Developer communities, champion and ambassador programs, startup programs, AI for community engagement, partnerships, international community management, community strategy and operations, social media strategy, campaign execution, product and project management, SaaS, partner management, BaaS, databases
Photos Wayne Sutton Wayne Sutton
## Why I joined Convex URL: https://waynesutton.ai/why-i-joined-convex # Why I joined Convex Photo note: Here's a shot of Convex co-founder and CTO James Cowling, Liz Cardoza from marketing, and my motorcycles in the office garage. When you pull up and see another bike from your coworkers, you know you're in the right place. --- Last night(October 2025) at the Pre Next.js Conf / Ship AI Meetup in SF, a developer asked why I'm working at Convex instead of another startup or database company. I smiled because the answer is simple. **The team.** In the Bay Area, people say Convex has some of the best engineers in tech. We're 20 people, led by founders who built the sync engine at Dropbox. They understand scale and infrastructure better than anyone. And they're good people. When you find humans you can learn from, enjoy being around, and who do right by their customers, it's a privilege. **The product.** Convex is a database, but it's more than that. It's a database platform with a short learning curve that helps experienced developers, new developers, and vibe coders ship faster. That benefits both teams and users. Can your database be your moat? Yes, with Convex. I've built more than eight apps this year using Convex, and I can immediately tell when other apps are running on outdated libraries and databases. They feel slow and clunky. Many new startups are switching to Convex because they want better dx and what's best for their teams and customers. **The mission.** Convex's mission is to fundamentally change how software is built on the Internet and who gets to build it. If you're on some change-the-world energy, this is it. Read that twice. If you've ever built an app with Convex, you already understand. **The adventure.** Reaching experienced developers and founders while introducing Convex to new ones is like teaching someone to ride a bike. It takes patience, but once they get it, the joy is shared. They remember the experience, tell their friends, and keep building together. Building communities, startup programs, and supporting founders and developers is rewarding when done with empathy, patience, and education. Jamie Turner, Convex's co-founder and CEO, recently told a group of startup founders that Crossing the Chasm by Geoffrey A. Moore is one of his favorite books. It reminded me of this line: "The early majority is willing and able to become technologically competent where necessary; the late majority is not." That quote captures both the challenge and the opportunity we have at Convex with today's developers, engineers, and founders. And yes, Convex is hiring serious engineers who want to join the adventure: https://www.convex.dev/jobs ## Open source developer communities are eating the world and always have been URL: https://waynesutton.ai/open-source-communities-are-eating-the-world ## Open source developer communities have been the growth engine for every major platform cycle. I have watched this pattern repeat from web communities to mobile to AI. The platforms that win are the ones developers can build on. Forums and early internet communities gave builders a place to learn in public. Facebook scaled once developers could build on top of its API and plug social features into other products. Twitter became part of developer workflow once the API made automation and client apps possible. Instagram grew faster when distribution across other networks became simple. The iPhone became mainstream when developers filled the App Store with useful apps. Same pattern now. Different stack. ## Open source communities execute faster than closed roadmaps. A company can launch a model. A community can turn that model into hundreds of real use cases in weeks. Developers ship wrappers, agents, integrations, templates, and revenue generating products on top of it. The difference is distribution through builders. When APIs are clear, docs are usable, and builders feel respected, momentum compounds. People do not just test a tool. They build business workflows, side projects, plugins, components, clients, and integrations that pull in the next wave of users. ## That is why developer trust matters so much right now. If you run a platform, your developer experience is your distribution strategy. [Angie Jones](https://x.com/techgirl1908/status/2023159121348825214?s=20) recently called out Anthropic for frustrating developers. That point landed hard across the ecosystem. You can have great tech and still lose mindshare if builders feel ignored. On the other side, teams that welcome builders create a flywheel. Open tools invite experiments. Experiments become products. Products create distribution. Distribution brings more builders. ## Peter and OpenAI This is why [OpenClaw](https://openclaw.ai/) sparked so much excitement. The energy was not only about code. It was about permission to build. Congrats Peter on building and empowering the OpenClaw community. Thanks for using [Convex](https://convex.dev) for [ClawHub](https://clawhub.ai/) Good luck at OpenAI, I'm looking foward to see what's next and how you continue to change the world. Peter also shared more context here: [OpenClaw post by Peter](https://steipete.me/posts/2026/openclaw) ## Open-source is for builders If you are building a platform in 2026, invest in the people shipping on top of you. Treat docs and API quality as product work. Celebrate community projects. Reward developers who extend your platform into new use cases. Open source communities are eating the world. They always have been. ## Who are you blogging for anyway? URL: https://waynesutton.ai/the-blogging-trap > Beez in the Trap It's day 2 of 2026 and I still haven't come up with a new year's resolution. And that's okay. I've been watching the resolutions roll in on Twitter. Jamie Turner, Convex CEO, wants to become a [better storyteller for Convex](https://x.com/jamwt/status/2007148956149805121?s=20). Sherry Jiang announced her [code every day 2026 challenge](https://x.com/SherryYanJiang/status/2007286795952680974?s=20). Both goals are inspirational. Part of me wants to announce my own: blog every day now that I finally have my site live. Or code every day like Sherry. But I know me. I know the weight of "I need to blog every day for the sake of blogging." That pressure takes the fun out of it. The obligation kills the creativity. The streak becomes the point instead of the writing. ## Who am I even blogging for? I'm blogging for me. I used to blog every day before my unc days and stopped somewhere along the way. Now I have professional development goals around sharing and communicating. That's the why. What am I going to write about? Everything. AI, life, coding, learning new skills, motorcycle adventure recaps, startup stories. I don't want to put myself in a box. Everything is on the table. The audience? Myself, first. AI, sure. Coworkers, social media friends, whoever finds this. Truth is, I'm writing for me. But if you're reading this, thanks. Feel free to slide in the DMs. ## The decision Do I want to blog every day? Yes. Is it going to be my new year's resolution? No. Depending on how the sunsets beam in the spring as the seasons change, maybe I'll pick a goal then. But for now, one day at a time. --- Writing by a human, proofed by AI. ## The definition of sauce aka taste URL: https://waynesutton.ai/definition-of-sauce It's the first day of 2026. We made it. Another year, but this one feels different if you work in tech or are an experienced entrepreneur. AI is everywhere. Agents, models, image generation. Doesn't matter if you're a full-stack dev or a vibe coder—you're always one text message away from building. It's an exciting time in tech. You can feel the energy in SF. Meetups, hackathons, long-form articles, and heated debates about AI replacing engineers, developers hating the term "vibe coding," who's actually doing 100+ million ARR. All while facing a new uphill problem if you're competing in the world of AI, launching a SaaS, or creating influencer content: distribution. Everyone knows distribution starts with an audience that turns into a community, that turns into customers or champions, with outcomes of everyone telling everyone how great you or your product is. That's the dream for anyone building today. Before the product is built, before you tweet about your new landing page, before you type your first prompt, it starts with foundations that help you stand out among the clouds. Your humanity, creativity, and passion. That's your sauce. We've always heard the quotes: "OpenAI just killed xyz startup" or "someone else already built it." In both cases, they wouldn't have built it like you would have. With your sauce. Paul Graham calls this [taste](https://paulgraham.com/taste.html), but we like sauce better. ## Sauce principles ### Humanity Humanity is your experience; how you see the world, your favorite music or color. It's also part of your why. What solutions do you want to build and why? I wanted to build [markdown.fast](https://markdown.fast) because after years of using or building WordPress sites for others back in the day and using other CMS tools that weren't AI-native or were just slow, I wanted a faster experience to publish content using [Convex](https://convex.dev). I believed others would benefit from a more modern solution. If I never had those experiences with WordPress or other CMS solutions, I would have never built something different. Plus I gotta stay up-to-date on my prompt engineering skills. ### Creativity Think of creativity as an unlimited supply of colors and empty coloring books. Or an empty moleskine. All blank canvases. If you passed these out to every single person in the world, each one would be different. This is how I feel with AI. I have access to unlimited coloring books, pens, and markers to create art or build an app. ### Passion Yes, passion. Passion is the driver that keeps you going, or prompting, trying new ways to build. Passion is staying up at 11pm watching a livestream of [Ray Fernando](https://x.com/RayFernando1337) showing how he's building apps and trying different AI models. Passion will have you questioning every SaaS subscription thinking you can build the same app, but better with your favorite stack. Passion will have you posting on Twitter (X), LinkedIn, and braving Reddit about your new app. Passion will move you to SF, have you apply to YC, attend the meetup, or join a hackathon. Passion will drive you to join a startup. Humanity, creativity, and passion. Cook with these three and you'll have a great 2026. Happy New Year! --- Writing by a human, proofed by AI.