105 KiB
Changelog
Type: page Date: 2026-01-11
All notable changes to this project.
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 packagepackages/create-markdown-sync/src/index.ts- CLI entry pointpackages/create-markdown-sync/src/wizard.ts- Interactive promptspackages/create-markdown-sync/src/clone.ts- Template cloningpackages/create-markdown-sync/src/configure.ts- Site configurationpackages/create-markdown-sync/src/install.ts- Dependency installationpackages/create-markdown-sync/src/convex-setup.ts- Convex initializationpackages/create-markdown-sync/src/utils.ts- Helper utilitiespackage.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, authorImagesrc/config/siteConfig.ts- Added RelatedPostsConfig interface and relatedPosts configsrc/pages/Post.tsx- Added thumbnail view, toggle state, and view mode renderingsrc/pages/Dashboard.tsx- Added Related Posts config card in ConfigSectionsrc/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 plugincontent/pages/docs-opencode.md- Documentation pagefiles.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 componentconvex/fs.ts- ConvexFS instance with Bunny CDN configconvex/files.ts- File mutations and queriesconvex/http.ts- ConvexFS routes for upload/downloadsrc/components/MediaLibrary.tsx- Media library gallerysrc/components/ImageUploadModal.tsx- Enhanced modal with library and sizessrc/styles/global.css- Media library and modal stylescontent/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 (
) to clipboard - HTML button copies HTML code (
<img src="url" alt="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 UIsrc/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.showInHeadertoggle to Dashboard Config Social Footer card - Added new Ask AI config card with
askAI.enabledtoggle 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 sectionsrc/components/Layout.tsx- Removed social icons from mobile-nav-controlssrc/pages/Dashboard.tsx- Added socialFooterShowInHeader and askAIEnabled configsrc/styles/global.css- Added mobile-menu-social CSS stylessrc/config/siteConfig.ts- Added alignment commentCLAUDE.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
askAIconfig tofork-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 blockFORK_CONFIG.md- Added Ask AI Configuration sectioncontent/pages/docs-dashboard.md- Added Ask AI documentationcontent/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:
- Navigate to Dashboard > Config
- Find the "Version Control" card
- Toggle "Enable version control" on
- Edit posts/pages or run sync commands to capture versions
- Click the History button in the editor to view version history
- Select a version to view diff or preview, then click "Restore This Version"
Technical:
- New
convex/versions.tswith 7 functions (isEnabled, setEnabled, createVersion, getVersionHistory, getVersion, restoreVersion, cleanupOldVersions, getStats) - New
contentVersionstable with indexes for efficient queries - New
versionControlSettingstable for toggle state - New
VersionHistoryModal.tsxcomponent 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 tablesconvex/versions.ts- New file with all version control logicconvex/cms.ts- Added version capture before dashboard editsconvex/posts.ts- Added version capture before sync updatesconvex/pages.ts- Added version capture before sync updatesconvex/crons.ts- Added daily cleanup jobsrc/components/VersionHistoryModal.tsx- New version history modalsrc/pages/Dashboard.tsx- Added Version Control config card and History buttonsrc/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
showFooterfrontmatter field on docs landing pages - Added AI chat support to docs landing page via
aiChatEnabledandpageContentprops
Technical:
- Added
Footerimport andfooterPagequery to fetch footer content - Added footer rendering logic after BlogPost component (same pattern as Post.tsx)
- Updated
getDocsLandingPagequery inconvex/pages.tsto returnshowFooter,footer,excerpt, andaiChatfields - Updated
getDocsLandingPostquery inconvex/posts.tsto returnshowFooter,footer, andaiChatfields
Files changed:
src/pages/DocsPage.tsx- Added Footer component and rendering logicconvex/pages.ts- Updated getDocsLandingPage query return fieldsconvex/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-wideclass for docs pages - Fixed
.docs-contentmargins: 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 valuessrc/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/10to.blog-imageto reserve space before images load - Added
aspect-ratio: 16/9to.post-header-image-imgto prevent header image layout shift - Added
contain: layout styleto.main-contentand.main-content-wideto 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: transformto continuous spin animations:.spinner-icon.animate-spin.ai-chat-spinner.ai-image-spinner.spinning.dashboard-import-btn .spin
- Added
will-change: transformto.logo-marquee-trackfor smoother marquee - Added
will-change: opacityto.visitor-map-badge-dotfor pulse animation
Files changed:
src/styles/global.css- CLS prevention, CSS containment, animation will-change hintssrc/components/Layout.tsx- fetchPriority on logosrc/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
formatForPrintfunction to strip markdown syntax (headings, bold, italic, code, links, blockquotes) - Added
handleExportPDFhandler that opens styled print window - Imports
FilePdffrom@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-pulseanimation: Converted frombackground-position(non-composited) to pseudo-element withtransform: translateX()(GPU-composited) - Added
will-changehints 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 SVGrattribute - Duplicate keyframes: Removed 5 redundant
@keyframes spindefinitions from CSS - GPU compositing hints: Added
will-changeto 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 duplicatessrc/components/VisitorMap.tsx- Updated SVG circle radius for transform-based animationindex.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 orpatch in markdown
New documentation:
- Blog post: "How to Use Code Blocks" with examples of regular code blocks and diff rendering
Technical:
- Added
@pierre/diffspackage - Created
DiffCodeBlockcomponent (src/components/DiffCodeBlock.tsx) - Updated
BlogPost.tsxto route diff/patch blocks to new renderer - Added diff block CSS styles to
global.css - Added
vendor-diffschunk 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-4o
- 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:
- User question is stored in database with session ID
- Query is converted to embedding using OpenAI text-embedding-ada-002
- Vector search finds top 5 relevant posts/pages
- Content is sent to selected AI model with RAG system prompt
- Response streams in real-time with source citations appended
Configuration:
Enable in src/config/siteConfig.ts:
askAI: {
enabled: true,
defaultModel: "claude-sonnet-4-20250514",
models: [
{ id: "claude-sonnet-4-20250514", name: "Claude Sonnet 4", provider: "anthropic" },
{ id: "gpt-4o", name: "GPT-4o", provider: "openai" },
],
},
Requirements:
semanticSearch.enabled: true(for embeddings)OPENAI_API_KEYin Convex (for embeddings)ANTHROPIC_API_KEYin Convex (for Claude models)- Run
npm run syncto 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:
askAISessionswithby_streamindex - HTTP endpoint:
/ask-ai-streamfor streaming responses - Uses
@convex-dev/persistent-text-streamingcomponent - 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:
- Canonical URL - Dynamic canonical link tags added client-side for posts and pages
- Single H1 per page - Markdown H1s demoted to H2 elements with
.blog-h1-demotedclass (maintains H1 visual styling) - DOM order fix - Article now loads before sidebar in DOM for better SEO (CSS
orderproperty maintains visual layout) - X-Robots-Tag - HTTP header added via netlify.toml (public routes indexed, dashboard/API routes noindexed)
- Hreflang tags - Self-referencing hreflang (en, x-default) for language targeting
- og:url consistency - Uses same canonicalUrl variable as canonical link tag
- twitter:site - New
TwitterConfigin siteConfig.ts for Twitter Cards
Configuration:
Add your Twitter handle in src/config/siteConfig.ts:
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:
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:
- Your query is converted to a 1536-dimension vector using OpenAI text-embedding-ada-002
- Convex compares this vector to stored embeddings for all posts and pages
- Results ranked by similarity score (displayed as percentage)
- 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:
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
embeddingfield andby_embeddingvector 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/components/SearchModal.tsx, scripts/sync-posts.ts, src/styles/global.css, content/pages/docs-search.md, content/pages/docs-semantic-search.md
v2.9.0
Released January 4, 2026
Dashboard Cloud CMS Features
The Dashboard now functions as a WordPress-style cloud CMS, allowing content creation and editing directly in the database without requiring the markdown file sync workflow.
Dual Source Architecture:
- Dashboard-created content marked with
source: "dashboard" - Markdown-synced content marked with
source: "sync" - Both coexist independently in the database
- Sync operations only affect synced content (dashboard content protected)
- Source badges in Posts and Pages list views (blue "Dashboard", gray "Synced")
Direct Database Operations:
- "Save to DB" button in Write Post/Page sections saves directly to database
- "Save Changes" button in Post/Page editor updates content immediately
- Delete button for dashboard-created content (synced content protected)
- Changes appear instantly without requiring sync
Delete Confirmation Modal:
- Warning modal displayed before deleting posts or pages
- Shows item name and type being deleted
- Themed to match dashboard UI with danger button styling
- Backdrop click and Escape key to cancel
Rich Text Editor:
- Three editing modes: Markdown (default), Rich Text (Quill WYSIWYG), Preview
- Quill-based editor with formatting toolbar
- Toolbar: headers (H1-H3), bold, italic, strikethrough, blockquote, code, lists, links
- Automatic HTML-to-Markdown conversion when switching modes
- Theme-aware styling using CSS variables
Server-Side URL Import:
- Direct database import via Firecrawl (no file sync needed)
- Enter URL in Import section, content is scraped and saved to database
- Optional "Publish immediately" checkbox
- Imported posts tagged with
importedby default - Requires
FIRECRAWL_API_KEYin Convex environment variables
Export to Markdown:
- Export any post/page to
.mdfile with complete frontmatter - Bulk export script:
npm run export:db(dev) ornpm run export:db:prod(prod) - Use for backup or converting dashboard content to file-based workflow
Technical details:
- New file:
convex/cms.tswith CRUD mutations - New file:
convex/importAction.tswith Firecrawl server-side action - New file:
scripts/export-db-posts.tsfor bulk markdown export - Added
sourcefield andby_sourceindex to posts and pages tables - Added ConfirmDeleteModal component to Dashboard.tsx
- Fixed list row grid layout for proper source badge display
Updated files: convex/schema.ts, convex/posts.ts, convex/pages.ts, convex/cms.ts, convex/importAction.ts, scripts/export-db-posts.ts, src/pages/Dashboard.tsx, src/styles/global.css, package.json, content/pages/docs-dashboard.md
v2.8.7
Released January 4, 2026
Write page frontmatter sidebar toggle fix
- Frontmatter sidebar toggle now works outside focus mode
- Grid layout adjusts properly when frontmatter sidebar is collapsed
- Previously only worked in focus mode due to missing CSS rules
- Both sidebars can now be collapsed independently or together
Technical details:
- Added
.write-layout.frontmatter-collapsedCSS rule (grid-template-columns: 220px 1fr 56px) - Added
.write-layout.sidebar-collapsed.frontmatter-collapsedCSS rule for both sidebars collapsed - Added responsive tablet styles for frontmatter collapsed state
Updated files: src/styles/global.css
v2.8.6
Released January 4, 2026
Fork configuration improvements
- Fork configuration script now updates 14 files (was 11)
- Added
src/pages/DocsPage.tsx(SITE_URL constant) - Added
netlify/edge-functions/mcp.ts(SITE_URL, SITE_NAME, MCP_SERVER_NAME) - Added
scripts/send-newsletter.ts(default SITE_URL) - Improved
public/openapi.yamlhandling for all example URLs
- Added
- Logo gallery hrefs now use relative URLs instead of hardcoded markdown.fast URLs
- Updated
fork-config.json.examplewith missing options (statsPage, mcpServer, imageLightbox)
Updated files: scripts/configure-fork.ts, src/config/siteConfig.ts, FORK_CONFIG.md, content/blog/fork-configuration-guide.md, fork-config.json.example
v2.8.5
Released January 3, 2026
Search result highlighting and scroll-to-match
- Clicking a search result now navigates to the exact match location (not just the nearest heading)
- All matching text is highlighted with theme-appropriate colors
- Highlights pulse on arrival, then fade to subtle background after 4 seconds
- Press Escape to clear highlights
- Works across all four themes (dark, light, tan, cloud)
Technical details:
- New
useSearchHighlighting.tshook with polling mechanism to wait for content load - Search query passed via
?q=URL parameter instead of hash anchor - Theme-specific highlight colors matching existing design system
Updated files: src/hooks/useSearchHighlighting.ts (new), src/components/SearchModal.tsx, src/components/BlogPost.tsx, src/pages/Post.tsx, src/styles/global.css
v2.8.4
Released January 3, 2026
AI service links now use local /raw URLs
- ChatGPT, Claude, and Perplexity links now use local
/raw/{slug}.mdURLs instead of GitHub raw URLs - Simplified AI prompt from multi-line instructions to "Read this URL and summarize it:"
- No longer requires git push for AI links to work (synced content available immediately)
Technical details:
- Updated URL construction to use
window.location.originfor consistency - Removed unused
siteConfigimport andgetGitHubRawUrlfunction
Updated files: src/components/CopyPageDropdown.tsx
v2.8.3
Released January 3, 2026
Raw index.md now includes home.md and footer.md content
raw/index.mdnow mirrors the actual homepage structure- Home intro content from
content/pages/home.mddisplays at top - Footer content from
content/pages/footer.mddisplays at bottom - Horizontal rule separators between sections
- Falls back to generic message if home-intro page not found
- Home intro content from
- AI agents reading
/raw/index.mdnow get the full homepage experience
Technical details:
- Updated
generateHomepageIndexfunction inscripts/sync-posts.ts - Finds home-intro and footer pages from published pages array by slug
Updated files: scripts/sync-posts.ts
v2.8.2
Released January 3, 2026
Footer fix for docs section pages
- Fixed footer not displaying on docs section posts/pages even with
showFooter: truein frontmatter- Post.tsx now fetches footer.md content from Convex (matching Home.tsx and Blog.tsx pattern)
- Footer falls back to footer.md content when no per-post
footer:frontmatter is specified - Priority order: per-post frontmatter
footer:> synced footer.md content > siteConfig.footer.defaultContent
Technical details:
- Added
useQuery(api.pages.getPageBySlug, { slug: "footer" })to Post.tsx - Updated all 4 Footer component calls to use
post.footer || footerPage?.contentpattern
Updated files: src/pages/Post.tsx
v2.8.1
Released January 3, 2026
Centralized defaultTheme in siteConfig.ts
- Theme configuration moved from ThemeContext.tsx to siteConfig.ts
- New
defaultThemefield in siteConfig for centralized theme management - ThemeContext.tsx now imports theme setting from siteConfig
- Fork configuration script updated to modify siteConfig.ts
- Backward compatible: falls back to "tan" if defaultTheme not set
Configuration example:
export const siteConfig: SiteConfig = {
// ... other config
defaultTheme: "tan", // Options: "dark", "light", "tan", "cloud"
};
Technical details:
- Added
Themetype export tosrc/config/siteConfig.ts - Added
defaultTheme?: Themefield to SiteConfig interface - Updated
src/context/ThemeContext.tsxto import from siteConfig - Renamed
updateThemeContexttoupdateThemeConfiginscripts/configure-fork.ts
Updated files: src/config/siteConfig.ts, src/context/ThemeContext.tsx, scripts/configure-fork.ts, content/pages/docs.md, content/blog/setup-guide.md, FORK_CONFIG.md, content/blog/fork-configuration-guide.md
v2.8.0
Released January 3, 2026
Docs sidebar group icons via frontmatter
- New
docsSectionGroupIconfrontmatter field for docs sidebar group icons- Display Phosphor icons next to docs sidebar group titles
- Icon appears left of the expand/collapse chevron
- 55 supported icon names (Rocket, Book, PuzzlePiece, Gear, Code, etc.)
- Icon weight: regular, size: 16px
- Only one item per group needs to specify the icon
- Graceful fallback if icon name not recognized
Example usage:
---
docsSection: true
docsSectionGroup: "Getting Started"
docsSectionGroupOrder: 1
docsSectionGroupIcon: "Rocket"
docsSectionOrder: 1
---
Technical details:
- Updated
convex/schema.tswithdocsSectionGroupIconfield in posts and pages tables - Updated
convex/posts.tsandconvex/pages.tsqueries and mutations - Updated
scripts/sync-posts.tsto parsedocsSectionGroupIconfrom frontmatter - Updated
src/components/DocsSidebar.tsxwith Phosphor icon imports and rendering - Added CSS styles for
.docs-sidebar-group-icon - Updated
.claude/skills/frontmatter.mdwith icon documentation
Updated files: convex/schema.ts, convex/posts.ts, convex/pages.ts, scripts/sync-posts.ts, src/components/DocsSidebar.tsx, src/styles/global.css, .claude/skills/frontmatter.md, files.md, TASK.md, changelog.md, content/pages/docs.md, public/raw/setup-guide.md
v2.7.0
Released January 2, 2026
Docs sidebar group ordering
- New
docsSectionGroupOrderfrontmatter field for controlling docs sidebar group order - Groups are sorted by the minimum
docsSectionGroupOrdervalue among items in each group - Lower numbers appear first, groups without this field sort alphabetically
- Works alongside
docsSection,docsSectionGroup, anddocsSectionOrderfields
Example usage:
---
docsSection: true
docsSectionGroup: "Getting Started"
docsSectionGroupOrder: 1
docsSectionOrder: 1
---
Technical details:
- Updated
convex/schema.tswithdocsSectionGroupOrderfield in posts and pages tables - Updated
convex/posts.tsandconvex/pages.tsqueries and mutations - Updated
scripts/sync-posts.tsto parsedocsSectionGroupOrderfrom frontmatter - Updated
src/components/DocsSidebar.tsxto sort groups bydocsSectionGroupOrder
v2.6.0
Released January 1, 2026
Multi-model AI chat and image generation in Dashboard
- AI Agent section with tab-based UI (Chat and Image Generation tabs)
- Multi-model selector for text chat
- Claude Sonnet 4 (Anthropic)
- GPT-4o (OpenAI)
- Gemini 2.0 Flash (Google)
- Lazy API key validation: errors only shown when user tries to use a specific model
- Each provider has friendly setup instructions with links to get API keys
- AI Image Generation tab
- Generate images using Gemini models (Nano Banana and Nano Banana Pro)
- Aspect ratio selector (1:1, 16:9, 9:16, 4:3, 3:4)
- Generated images stored in Convex storage with session tracking
- Markdown-rendered error messages with setup instructions
- New
aiDashboardconfiguration in siteConfigenableImageGeneration: Toggle image generation tabdefaultTextModel: Set default AI model for chattextModels: Configure available text chat modelsimageModels: Configure available image generation models
Technical details:
- New file:
convex/aiImageGeneration.tsfor Gemini image generation action - New table:
aiGeneratedImagesin schema for tracking generated images - Updated
convex/aiChatActions.tswith multi-provider support- Added
callAnthropicApi,callOpenAIApi,callGeminiApihelper functions - Added
getProviderFromModelto determine provider from model ID - Added
getApiKeyForProviderfor lazy API key retrieval - Added
getNotConfiguredMessagefor provider-specific setup instructions
- Added
- Updated
src/components/AIChatView.tsxwithselectedModelprop - Updated
src/pages/Dashboard.tsxwith new AI Agent section- Tab-based UI for Chat and Image Generation
- Model dropdowns with provider labels
- Aspect ratio selector for image generation
- CSS styles for AI Agent section in
src/styles/global.css.ai-agent-tabs,.ai-agent-tabfor tab navigation.ai-model-selector,.ai-model-dropdownfor model selection.ai-aspect-ratio-selectorfor aspect ratio options.ai-generated-image,.ai-image-error,.ai-image-loadingfor image display
Environment Variables:
ANTHROPIC_API_KEY: Required for Claude modelsOPENAI_API_KEY: Required for GPT-4oGOOGLE_AI_API_KEY: Required for Gemini text chat and image generation
Updated files: convex/aiImageGeneration.ts, convex/aiChatActions.ts, convex/aiChats.ts, convex/schema.ts, src/components/AIChatView.tsx, src/pages/Dashboard.tsx, src/config/siteConfig.ts, src/styles/global.css, files.md, TASK.md, changelog.md, content/pages/changelog-page.md
v2.5.0
Released January 1, 2026
Social footer icons in header navigation
- New
showInHeaderoption insiteConfig.socialFooterto display social icons in the header- Social icons appear left of the search icon on desktop viewports
- Uses same icons and links as the social footer component
- Configurable via siteConfig, FORK_CONFIG.md, and fork-config.json
- Set
showInHeader: truein socialFooter config to enable
Technical details:
- Exported
platformIconsfromsrc/components/SocialFooter.tsxfor reuse - Added social icon rendering in
src/components/Layout.tsxheader controls - Added
.header-social-linksand.header-social-linkCSS styles - Updated
SocialFooterConfiginterface withshowInHeader: boolean - Added socialFooter support to
scripts/configure-fork.ts
Updated files: src/config/siteConfig.ts, src/components/SocialFooter.tsx, src/components/Layout.tsx, src/styles/global.css, scripts/configure-fork.ts, FORK_CONFIG.md, fork-config.json.example, public/raw/docs.md, public/raw/setup-guide.md, files.md, TASK.md, changelog.md, content/pages/changelog-page.md
v2.4.0
Released January 1, 2026
YouTube and Twitter/X embed support
- Embed YouTube videos and Twitter/X posts directly in markdown
- Domain whitelisting for security (only trusted domains allowed)
- Whitelisted domains:
youtube.com,www.youtube.com,youtube-nocookie.com,www.youtube-nocookie.com,platform.twitter.com,platform.x.com - Auto-adds
sandboxandloading="lazy"attributes for security - Non-whitelisted iframes silently blocked
- Works on both blog posts and pages
- Embeds section added to markdown-with-code-examples.md with usage examples
Technical details:
- Added
ALLOWED_IFRAME_DOMAINSconstant insrc/components/BlogPost.tsx - Added
iframeto sanitize schema with allowed attributes - Added custom iframe component handler with URL validation
- Added
.embed-containerCSS styles for responsive embeds
Updated files: src/components/BlogPost.tsx, src/styles/global.css, content/blog/markdown-with-code-examples.md, files.md, TASK.md, changelog.md, content/pages/changelog-page.md
v2.3.0
Released December 31, 2025
Author pages feature
- Author archive pages at
/author/:authorSlugdisplaying all posts by that author- Click on any author name in a post to view all their posts
- View mode toggle (list/cards) with localStorage persistence
- Mobile responsive layout matching tag pages design
- Sitemap updated to include all author pages dynamically
- New Convex queries for author data
getAllAuthors: Returns all unique authors with post countsgetPostsByAuthor: Returns posts by a specific author slug
- Author name links in post headers
- Author names now clickable with hover underline effect
- Works on both blog posts and pages with authorName field
- Follows existing tag pages pattern for consistent UX
Technical details:
- Added
by_authorNameindex to posts table inconvex/schema.ts - New queries in
convex/posts.ts:getAllAuthors,getPostsByAuthor - New component:
src/pages/AuthorPage.tsx(based on TagPage.tsx pattern) - Added route
/author/:authorSluginsrc/App.tsx - Updated
src/pages/Post.tsxto make authorName a clickable Link - Added author link and page styles to
src/styles/global.css - Added author pages to sitemap in
convex/http.ts
Updated files: convex/schema.ts, convex/posts.ts, convex/http.ts, src/pages/AuthorPage.tsx, src/App.tsx, src/pages/Post.tsx, src/styles/global.css, files.md, prds/authorname-blogs.md
v2.2.2
Released December 31, 2025
Homepage intro loading flash fix
- Removed visible loading states from homepage intro content
- No more "Loading..." text flash when app loads (fixed Suspense fallback in main.tsx)
- No more bio text flash while home intro content loads (fixed conditional in Home.tsx)
- Home intro content now appears without any visible loading state or fallback
- Matches the loading pattern used by Post.tsx for docs pages (render nothing while loading)
Updated files: src/main.tsx, src/pages/Home.tsx, changelog.md, content/pages/changelog-page.md, TASK.md, files.md
v2.2.1
Released December 31, 2025
ES module compatibility fix for configure-fork.ts
- Fixed
__dirname is not definederror when runningnpm run configure - Added
fileURLToPathimport fromurlmodule to create ES module equivalent of__dirname - Script now works correctly with
"type": "module"in package.json
Updated files: scripts/configure-fork.ts, files.md, changelog.md, content/pages/changelog-page.md, TASK.md
v2.2.0
Released December 30, 2025
Footer content via markdown page
- New
content/pages/footer.mdfor managing footer content via markdown sync- Footer content syncs with
npm run syncwithout redeploy needed - Edit footer text, links, and formatting through markdown instead of code
- Falls back to
siteConfig.footer.defaultContentwhen page not found - Set
showInNav: falseto hide from navigation (page remains accessible via direct URL) - Supports full markdown including links, paragraphs, and line breaks
- Footer content syncs with
Technical details:
- New file:
content/pages/footer.mdwith frontmatter (slug: "footer", showInNav: false) - Updated:
src/pages/Home.tsxto fetch footer page by slug "footer" - Updated:
src/pages/Blog.tsxto fetch footer page by slug "footer" - Footer component now prioritizes page content over siteConfig.defaultContent
- Pattern matches
home-intropage for consistent content management
Updated files: content/pages/footer.md, src/pages/Home.tsx, src/pages/Blog.tsx, files.md, changelog.md, content/pages/changelog-page.md, FORK_CONFIG.md, TASK.md
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/directoryfrontmatter.md: Complete frontmatter syntax with all 25+ field options for posts and pagesconvex.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
- CLAUDE.md status comment updated during
- Unlisted posts feature
- New
unlistedfrontmatter field for blog posts - Set
unlisted: trueto hide posts from listings while keeping them accessible via direct link - Unlisted posts are excluded from: blog listings, featured sections, tag pages, search results, and related posts
- Posts remain accessible via direct URL (e.g.,
/blog/post-slug) - Useful for draft posts, private content, or posts you want to share via direct link only
- New
Technical details:
- New file:
CLAUDE.mdin project root - New directory:
.claude/skills/with three markdown files - Updated:
scripts/sync-discovery-files.tsto update CLAUDE.md alongside AGENTS.md and llms.txt - Updated:
convex/schema.ts- Addedunlistedoptional boolean field to posts table - Updated:
convex/posts.ts- All listing queries filter out unlisted posts - Updated:
convex/search.ts- Search excludes unlisted posts from results - Updated:
scripts/sync-posts.ts- Addedunlistedto interfaces and parsing logic - Updated:
src/pages/Write.tsx- Addedunlistedto POST_FIELDS frontmatter reference - Updated documentation:
.claude/skills/frontmatter.md,content/pages/docs.md,content/blog/setup-guide.md,files.md
Updated files: CLAUDE.md, .claude/skills/frontmatter.md, .claude/skills/convex.md, .claude/skills/sync.md, scripts/sync-discovery-files.ts, convex/schema.ts, convex/posts.ts, convex/search.ts, scripts/sync-posts.ts, src/pages/Write.tsx, files.md, changelog.md, content/pages/changelog-page.md
v2.0.0
Released December 29, 2025
Markdown sync v2 complete
- Full markdown content synchronization system
- Real-time sync from markdown files to Convex database
- Dashboard UI for content management
- Sync server for executing sync commands from UI
- Complete type safety across all Convex functions
- Security improvements and optimizations
Technical details:
- Optimized
recordPageViewmutation to reduce unnecessary reads - All mutations follow Convex best practices for write conflict prevention
- Type-safe Convex functions with proper validators
- Security review completed with all endpoints properly secured
v1.47.0
Released December 29, 2025
Image lightbox for blog posts and pages
- Images automatically open in full-screen lightbox when clicked (if enabled)
- Lightbox includes dark backdrop, close button (X icon), and caption display
- Keyboard support: Press Escape to close lightbox
- Click outside image (backdrop) to close
- Alt text displayed as caption below image in lightbox
- Images show pointer cursor (
zoom-in) and subtle hover effect when lightbox is enabled - Configurable via
siteConfig.imageLightbox.enabled(default:true) - Dashboard config generator includes image lightbox toggle
- Responsive design: lightbox adapts to mobile screens
Configuration:
// src/config/siteConfig.ts
imageLightbox: {
enabled: true, // Set to false to disable image lightbox
},
Technical details:
- New
ImageLightboxcomponent inBlogPost.tsxwith backdrop, close button, and keyboard handlers - Lightbox state management using React hooks (
useState,useEffect) - CSS styles for lightbox backdrop, image container, close button, and caption
- Prevents body scrolling when lightbox is open
- Smooth fade-in animation for lightbox appearance
Updated files: src/components/BlogPost.tsx, src/config/siteConfig.ts, src/styles/global.css, src/pages/Dashboard.tsx, content/pages/docs.md, content/blog/setup-guide.md
v1.46.0
Released December 29, 2025
Dashboard sync server for executing sync commands from UI
- Local HTTP server for executing sync commands directly from dashboard
- Run
npm run sync-serverto start the local server on localhost:3001 - Execute sync commands without opening a terminal
- Real-time output streaming in dashboard terminal view
- Server status indicator shows online/offline status
- Copy and Execute buttons for each sync command
- Optional token authentication via
SYNC_TOKENenvironment variable - Whitelisted commands only for security
- Health check endpoint for server availability detection
- Header sync buttons automatically use sync server when available
- Copy icons for
npm run sync-servercommand throughout dashboard
- Run
Technical details:
- New
scripts/sync-server.tsfile implements local HTTP server - Uses Node.js
child_process.spawnto execute npm commands - Streams output in real-time to dashboard UI
- CORS enabled for localhost:5173 development server
- Server binds to localhost only (not accessible from network)
Updated files: scripts/sync-server.ts, src/pages/Dashboard.tsx, src/styles/global.css, package.json
v1.45.0
Released December 29, 2025
Dashboard and WorkOS authentication integration
- Dashboard supports optional WorkOS authentication via
siteConfig.dashboard.requireAuth - WorkOS is optional - dashboard works with or without WorkOS configured
- When
requireAuthisfalse, dashboard is open access - When
requireAuthistrueand WorkOS is configured, dashboard requires login - Shows setup instructions if
requireAuthistruebut WorkOS is not configured - Warning banner displayed when authentication is not enabled
- Blog posts added: "How to use the Markdown sync dashboard" and "How to setup WorkOS"
Updated files: src/pages/Dashboard.tsx, src/main.tsx, src/App.tsx, src/pages/Callback.tsx, src/utils/workos.ts, convex/auth.config.ts, src/config/siteConfig.ts, README.md, content/pages/docs.md, content/blog/setup-guide.md, FORK_CONFIG.md, fork-config.json.example, files.md, TASK.md, changelog.md, content/pages/changelog-page.md
v1.44.0
Released December 29, 2025
Dashboard for centralized content management and site configuration
- Dashboard at
/dashboardprovides a centralized UI for managing content, configuring the site, and performing sync operations - Content management: Posts and Pages list views with filtering, search, pagination, and items per page selector (15, 25, 50, 100)
- Post and Page editor: Markdown editor with live preview, draggable/resizable frontmatter sidebar (200px-600px), independent scrolling, download markdown, copy to clipboard
- Write Post and Write Page: Full-screen writing interface with markdown editor, frontmatter reference, download markdown, localStorage persistence
- AI Agent section: Dedicated AI chat separate from Write page, uses Anthropic Claude API, per-session chat history, markdown rendering
- Newsletter management: All Newsletter Admin features integrated (subscribers, send newsletter, write email, recent sends, email stats)
- Content import: Firecrawl import UI for importing external URLs as markdown drafts
- Site configuration: Config Generator UI for all
siteConfig.tssettings, generates downloadable config file - Index HTML editor: View and edit
index.htmlcontent with meta tags, Open Graph, Twitter Cards, JSON-LD - Analytics: Real-time stats dashboard (clone of
/statspage, always accessible in dashboard) - Sync commands: UI with buttons for all sync operations (sync, sync:discovery, sync:all for dev and prod)
- Header sync buttons: Quick sync buttons in dashboard header for
npm run sync:all(dev and prod) - Dashboard search: Search bar in header to search dashboard features, page titles, and post content
- Toast notifications: Success, error, info, and warning notifications with auto-dismiss
- Command modal: Shows sync command output with copy to clipboard functionality
- Mobile responsive: Fully responsive design with mobile-optimized layout
- Theme and font: Theme toggle and font switcher with persistent preferences
Updated files: src/pages/Dashboard.tsx, src/styles/global.css, src/App.tsx
v1.43.0
Released December 29, 2025
Stats page configuration option for public/private access
- New
StatsPageConfiginterface insiteConfig.tswithenabledandshowInNavoptions - Stats page can be made private by setting
enabled: false(similar to NewsletterAdmin pattern) - When disabled, route shows "Stats page is disabled" message instead of analytics
- Navigation item automatically hidden when stats page is disabled
- Default configuration:
enabled: true(public),showInNav: true(visible in nav)
Updated files: src/config/siteConfig.ts, src/App.tsx, src/pages/Stats.tsx, src/components/Layout.tsx
v1.42.0
Released December 29, 2025
Honeypot bot protection for contact and newsletter forms
- Hidden honeypot fields invisible to humans but visible to bots
- Contact form uses hidden "Website" field for bot detection
- Newsletter signup uses hidden "Fax" field for bot detection
- Bots that fill hidden fields receive fake success message (no data submitted)
- No external dependencies required (client-side only protection)
- Works with all four themes (dark, light, tan, cloud)
Updated files: src/components/ContactForm.tsx, src/components/NewsletterSignup.tsx
- Honeypot fields use CSS positioning (position: absolute, left: -9999px) to hide from users
- Fields include aria-hidden="true" and tabIndex={-1} for accessibility
- Different field names per form (website/fax) to avoid pattern detection
v1.41.0
Released December 28, 2025
Blog heading styles for home intro content
- Headings (h1-h6) in
content/pages/home.mdnow use same styling as blog posts - Classes:
blog-h1,blog-h2,blog-h3,blog-h4,blog-h5,blog-h6 - Clickable anchor links (#) appear on hover for each heading
- Automatic ID generation from heading text for anchor navigation
- Additional blog styling for lists, blockquotes, horizontal rules, and links
- Home intro headings now match blog post typography and spacing
Updated files: src/pages/Home.tsx
v1.39.0
Released December 28, 2025
HTTP-based MCP Server
- Model Context Protocol (MCP) server deployed on Netlify Edge Functions
- Accessible 24/7 at
https://www.markdown.fast/mcp - No local machine required (unlike stdio-based MCP servers)
- Works with Cursor, Claude Desktop, and other MCP-compatible clients
- Accessible 24/7 at
- Public access with Netlify built-in rate limiting (50 req/min per IP)
- Optional API key authentication for higher limits (1000 req/min)
- Set
MCP_API_KEYin Netlify environment variables - Add
Authorization: Bearer <key>header to requests
- Set
- Read-only access to blog content:
list_posts: Get all published posts with metadataget_post: Get single post by slug with full contentlist_pages: Get all published pagesget_page: Get single page by slug with full contentget_homepage: Get homepage data with featured and recent postssearch_content: Full text search across posts and pagesexport_all: Batch export all content
Documentation
- Blog post: "How to Use the MCP Server" with client configuration examples
- MCP Server section added to docs.md
- MCP configuration added to siteConfig.ts
- Setup guide updated with MCP server section
Configuration
Add to Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"markdown-fast": {
"url": "https://www.markdown.fast/mcp"
}
}
}
Updated files: netlify/edge-functions/mcp.ts, netlify.toml, package.json, src/config/siteConfig.ts, content/blog/how-to-use-mcp-server.md, content/pages/docs.md, content/blog/setup-guide.md, files.md, changelog.md, content/pages/changelog-page.md
v1.38.0
Released December 27, 2025
Newsletter CLI improvements
newsletter:sendnow callsscheduleSendPostNewslettermutation directly- Sends emails in the background instead of printing instructions
- Provides clear success/error feedback
- Shows helpful messages about checking Newsletter Admin for results
- New
newsletter:send:statscommand- Sends weekly stats summary to your inbox on demand
- Uses
scheduleSendStatsSummarymutation - Email sent to AGENTMAIL_INBOX or AGENTMAIL_CONTACT_EMAIL
- New mutation
scheduleSendStatsSummaryinconvex/newsletter.ts- Allows CLI to trigger stats summary sending
- Schedules
sendWeeklyStatsSummaryinternal action
Documentation
- Blog post: "How to use AgentMail with Markdown Sync"
- Complete setup guide for AgentMail integration
- Environment variables configuration
- Newsletter and contact form features
- CLI commands documentation
- Troubleshooting section
- Updated docs.md with new CLI commands
- Updated files.md with new script reference
- Verified all AgentMail features use environment variables (no hardcoded emails)
Updated files: scripts/send-newsletter.ts, scripts/send-newsletter-stats.ts, convex/newsletter.ts, package.json, content/blog/how-to-use-agentmail.md, content/pages/docs.md, files.md, changelog.md, content/pages/changelog-page.md, TASK.md
v1.37.0
Released December 27, 2025
Newsletter Admin UI
- Newsletter Admin UI at
/newsletter-admin- Three-column layout similar to Write page
- View all subscribers with search and filter (all/active/unsubscribed)
- Stats showing active, total, and sent newsletter counts
- Delete subscribers directly from admin
- Send newsletter panel with two modes:
- Send Post: Select a blog post to send as newsletter
- Write Email: Compose custom email with markdown support
- Markdown-to-HTML conversion for custom emails (headers, bold, italic, links, lists)
- Copy icon on success messages to copy CLI commands
- Theme-aware success/error styling (no hardcoded green)
- Recent newsletters list showing sent history
- Configurable via
siteConfig.newsletterAdmin
Weekly Digest automation
- Cron job runs every Sunday at 9:00 AM UTC
- Automatically sends all posts published in the last 7 days
- Uses AgentMail SDK for email delivery
- Configurable via
siteConfig.weeklyDigest
Developer Notifications
- New subscriber alerts sent via email when someone subscribes
- Weekly stats summary sent every Monday at 9:00 AM UTC
- Uses
AGENTMAIL_CONTACT_EMAILorAGENTMAIL_INBOXas recipient - Configurable via
siteConfig.newsletterNotifications
Admin queries and mutations
getAllSubscribers: Paginated subscriber list with search/filterdeleteSubscriber: Remove subscriber from databasegetNewsletterStats: Stats for admin dashboardgetPostsForNewsletter: List of posts with sent status
Updated files: convex/newsletter.ts, convex/newsletterActions.ts, convex/posts.ts, convex/crons.ts, src/config/siteConfig.ts, src/App.tsx, src/styles/global.css, src/pages/NewsletterAdmin.tsx
v1.36.0
Released December 27, 2025
Social footer component
- Social footer component with customizable social links and copyright
- Displays social icons on the left (GitHub, Twitter/X, LinkedIn, and more)
- Shows copyright symbol, site name, and auto-updating year on the right
- Configurable via
siteConfig.socialFooterinsrc/config/siteConfig.ts - Supports 8 platform types: github, twitter, linkedin, instagram, youtube, tiktok, discord, website
- Uses Phosphor icons for consistent styling
- Appears below the main footer on homepage, blog posts, and pages
- Can work independently of the main footer when set via frontmatter
Frontmatter control for social footer
showSocialFooterfield for posts and pages to override siteConfig defaults- Set
showSocialFooter: falseto hide on specific posts/pages - Works like existing
showFooterfield pattern
Social footer configuration options
enabled: Global toggle for social footershowOnHomepage,showOnPosts,showOnPages,showOnBlogPage: Per-location visibilitysocialLinks: Array of social link objects with platform and URLcopyright.siteName: Site/company name for copyright displaycopyright.showYear: Toggle for auto-updating year
Updated files: src/config/siteConfig.ts, convex/schema.ts, convex/posts.ts, convex/pages.ts, scripts/sync-posts.ts, src/pages/Home.tsx, src/pages/Post.tsx, src/pages/Blog.tsx, src/styles/global.css, src/components/SocialFooter.tsx
v1.35.0
Released December 26, 2025
Image support at top of posts and pages
showImageAtTopfrontmatter field for posts and pages- Set
showImageAtTop: trueto display theimagefield at the top of the post/page above the header - Image displays full-width with rounded corners above the post header
- Default behavior: if
showImageAtTopis not set orfalse, image only used for Open Graph previews and featured card thumbnails - Works for both blog posts and static pages
- Image appears above the post header when enabled
- Set
Updated files: convex/schema.ts, scripts/sync-posts.ts, convex/posts.ts, convex/pages.ts, src/pages/Post.tsx, src/pages/Write.tsx, src/styles/global.css
Documentation updated: content/pages/docs.md, content/blog/how-to-publish.md, content/blog/using-images-in-posts.md, files.md
v1.34.0
Released December 26, 2025
Blog page featured layout with hero post
blogFeaturedfrontmatter field for posts to mark as featured on blog page- First
blogFeaturedpost displays as hero card with landscape image, tags, date, title, excerpt, author info, and read more link - Remaining
blogFeaturedposts display in 2-column featured row with excerpts - Regular (non-featured) posts display in 3-column grid without excerpts
- New
BlogHeroCardcomponent (src/components/BlogHeroCard.tsx) for hero display - New
getBlogFeaturedPostsquery returns all published posts withblogFeatured: truesorted by date PostListcomponent updated withcolumnsprop (2 or 3) andshowExcerptsprop- Card images use 16:10 landscape aspect ratio
- Footer support on blog page via
siteConfig.footer.showOnBlogPage
- First
Updated files: convex/schema.ts, convex/posts.ts, scripts/sync-posts.ts, src/pages/Blog.tsx, src/components/PostList.tsx, src/styles/global.css
v1.33.1
Released December 26, 2025
Article centering in sidebar layouts
- Article content now centers in the middle column when sidebars are present
- Left sidebar stays flush left, right sidebar stays flush right
- Article uses
margin-left: auto; margin-right: autowithin its1frgrid column - Works with both two-column (left sidebar only) and three-column (both sidebars) layouts
- Consistent
max-width: 800pxfor article content across all sidebar configurations
Updated files: src/styles/global.css
v1.33.0
Released December 26, 2025
AI Chat Write Agent (Agent) integration
- AI Agent chat interface powered by Anthropic Claude API
- New
AIChatViewcomponent for AI-powered chat interface - Available on Write page (replaces textarea when enabled) and optionally in RightSidebar on posts/pages
- Per-session, per-context chat history stored in Convex (aiChats table)
- Supports page content as context for AI responses
- Markdown rendering for AI responses with copy functionality
- Theme-aware styling matching the site's design system
- Uses Phosphor Icons for all UI elements
- New
- Convex backend for AI chat
- New
convex/aiChats.tswith queries and mutations for chat history - New
convex/aiChatActions.tswith Claude API integration (requires ANTHROPIC_API_KEY environment variable) - System prompt configurable via Convex environment variables:
CLAUDE_PROMPT_STYLE,CLAUDE_PROMPT_COMMUNITY,CLAUDE_PROMPT_RULES(split prompts, joined with separators)CLAUDE_SYSTEM_PROMPT(single prompt, fallback if split prompts not set)
- Chat history limited to last 20 messages for context efficiency
- Error handling: displays "API key is not set" message when ANTHROPIC_API_KEY is missing in Convex environment variables
- New
- Configuration options
siteConfig.aiChatinterface withenabledOnWritePageandenabledOnContentboolean flags- Both flags default to false (opt-in feature)
- New
aiChatfrontmatter field for posts and pages (requires rightSidebar: true)
- Write page AI Agent mode
- Title changes from "Blog Post" or "Page" to "Agent" when in AI chat mode
- Toggle button text changes between "Agent" and "Text Editor"
- Page scroll prevention when switching modes (no page jump)
- RightSidebar AI chat support
- Conditionally renders AIChatView when enabled via frontmatter
aiChat: truefield - Requires both
siteConfig.aiChat.enabledOnContentand frontmatteraiChat: true - Passes page content as context for AI responses
- Conditionally renders AIChatView when enabled via frontmatter
Updated files: src/components/AIChatView.tsx, src/components/RightSidebar.tsx, src/pages/Write.tsx, src/pages/Post.tsx, src/config/siteConfig.ts, convex/schema.ts, convex/aiChats.ts, convex/aiChatActions.ts, convex/posts.ts, convex/pages.ts, scripts/sync-posts.ts, src/styles/global.css, package.json
Documentation updated: files.md, changelog.md, README.md, content/blog/setup-guide.md, public/raw/docs.md
v1.32.0
Released December 25, 2025
Custom homepage configuration
- Set any page or blog post to serve as the homepage instead of the default Home component
- Configure via
siteConfig.homepagewithtype("default", "page", or "post"),slug(required for page/post), andoriginalHomeRoute(default: "/home") - Custom homepage retains all Post component features (sidebar, copy dropdown, author info, footer) but without the featured section
- Original homepage remains accessible at
/homeroute (or configuredoriginalHomeRoute) when custom homepage is set - SEO metadata uses the page/post's frontmatter when used as homepage
- Back button hidden when Post component is used as homepage
- Fork configuration support for homepage
- Added
homepagefield tofork-config.json.example - Updated
configure-fork.tsto handle homepage configuration - Documentation added to
FORK_CONFIG.mdwith usage examples
- Added
Updated files: src/App.tsx, src/pages/Post.tsx, src/config/siteConfig.ts, scripts/configure-fork.ts, fork-config.json.example, FORK_CONFIG.md
v1.31.1
Released December 25, 2025
Image support in footer component
- Footer markdown now supports images using standard markdown syntax or HTML
- Images can be sized using
width,height,style, orclassHTML attributes - Image attributes are sanitized by rehypeSanitize for security (removes dangerous CSS)
- Footer images support lazy loading and optional captions from alt text
- CSS styles added for footer images
Updated files: src/components/Footer.tsx, src/styles/global.css
v1.31.0
Released December 25, 2025
Customizable footer component with markdown support
- New
Footercomponent that renders markdown content - Footer content can be set in frontmatter
footerfield (markdown) or usesiteConfig.footer.defaultContent - Footer can be enabled/disabled globally via
siteConfig.footer.enabled - Footer visibility controlled per-page type via
siteConfig.footer.showOnHomepage,showOnPosts,showOnPages - New
showFooterfrontmatter field for posts and pages to override siteConfig defaults - New
footerfrontmatter field for posts and pages to provide custom markdown content - Footer renders inside article at bottom for posts/pages, maintains current position on homepage
- Footer supports markdown formatting (links, paragraphs, line breaks)
- Sidebars flush to bottom when footer is enabled
Updated files: src/components/Footer.tsx, src/pages/Home.tsx, src/pages/Post.tsx, src/config/siteConfig.ts, src/styles/global.css, convex/schema.ts, convex/posts.ts, convex/pages.ts, scripts/sync-posts.ts, src/pages/Write.tsx
Documentation updated: files.md, changelog.md
v1.30.2
Released December 25, 2025
Right sidebar default behavior fix
- Right sidebar no longer appears on pages/posts without explicit
rightSidebar: truein frontmatter- Changed default behavior: right sidebar is now opt-in only
- Pages like About and Contact now render without the right sidebar as expected
CopyPageDropdowncorrectly appears in nav bar when right sidebar is disabled
- Logic in
Post.tsxchanged from(page.rightSidebar ?? true)topage.rightSidebar === true
Updated files: src/pages/Post.tsx
v1.30.1
Released December 25, 2025
TypeScript error fix
- TypeScript error in
convex/posts.tswhererightSidebarwas used in mutation handlers but missing from args validators- Added
rightSidebar: v.optional(v.boolean())tosyncPostsargs validator - Added
rightSidebar: v.optional(v.boolean())tosyncPostsPublicargs validator
- Added
Updated files: convex/posts.ts
v1.30.0
Released December 25, 2025
Right sidebar feature for posts and pages
- New
RightSidebarcomponent that displaysCopyPageDropdownin a right sidebar- Appears at 1135px+ viewport width when enabled
- Controlled by
siteConfig.rightSidebar.enabled(global toggle) - Per-post/page control via
rightSidebar: truefrontmatter field (opt-in only) - Three-column layout support: left sidebar (TOC), main content, right sidebar (CopyPageDropdown)
- CopyPageDropdown automatically moves from nav to right sidebar when enabled
- Responsive: right sidebar hidden below 1135px, CopyPageDropdown returns to nav
- Right sidebar configuration in siteConfig
rightSidebar.enabled: Global toggle for right sidebar featurerightSidebar.minWidth: Minimum viewport width to show sidebar (default: 1135px)
rightSidebarfrontmatter field- Available for both blog posts and pages
- Optional boolean field to enable/disable right sidebar per post/page
- Added to Write page frontmatter reference with copy button
Updated files: src/components/RightSidebar.tsx, src/pages/Post.tsx, src/config/siteConfig.ts, src/styles/global.css, convex/schema.ts, convex/posts.ts, convex/pages.ts, scripts/sync-posts.ts, src/pages/Write.tsx
Documentation updated: content/blog/setup-guide.md, content/pages/docs.md, files.md, changelog.md
v1.29.0
Released December 25, 2025
Font family configuration system
- Font family configuration via siteConfig.ts
- Three font options: "serif" (New York), "sans" (system fonts), "monospace" (IBM Plex Mono)
- Configure default font in
src/config/siteConfig.tswithfontFamilyoption - Font preference persists in localStorage across page reloads
- SiteConfig default font overrides localStorage when siteConfig changes
- Monospace font option added
- Added monospace to FONT SWITCHER options in global.css
- Uses "IBM Plex Mono", "Liberation Mono", ui-monospace, monospace
- Write page font switcher now cycles through all three options
- Fork configuration support
- Added fontFamily field to fork-config.json.example
- Automated fork configuration script supports fontFamily option
Updated files: src/config/siteConfig.ts, src/context/FontContext.tsx, src/main.tsx, src/pages/Write.tsx, src/styles/global.css, scripts/configure-fork.ts, fork-config.json.example
Documentation updated: content/blog/setup-guide.md, content/pages/docs.md, files.md
v1.28.2
Released December 25, 2025
Plain text code block wrapping
- Code blocks without a language specifier now wrap text properly
- Fixed horizontal overflow for long error messages and prose in code blocks
- Updated inline vs block code detection logic
- Inline code: short content (< 80 chars), no newlines, no language class
- Block code: longer content or has language specifier
- Text wrapping uses
pre-wrapstyling applied via SyntaxHighlighter props
Updated files: src/components/BlogPost.tsx, src/styles/global.css
v1.28.1
Released December 25, 2025
RSS feed validation fixes
- Standardized all URLs to
www.markdown.fastacross the application - Fixed
atom:link rel="self"attribute mismatch that caused RSS validation failures - Updated
index.htmlmeta tags (og:url, og:image, twitter:domain, twitter:url, twitter:image, JSON-LD) - Updated
convex/rss.tsandconvex/http.tsSITE_URL constants to use www.markdown.fast - Updated
public/robots.txt,public/openapi.yaml, andpublic/llms.txtwith www URLs - RSS exclusions already present in
netlify.tomlfor botMeta edge function
All URL references now consistently use https://www.markdown.fast. RSS feed rel="self" attribute now matches actual feed URL. Build passes successfully.
v1.28.0
Released December 25, 2025
Discovery files sync automation
- New discovery files sync script
- Automatically updates AGENTS.md and llms.txt with current app data
- Reads from siteConfig.ts and queries Convex for post/page counts
- Preserves existing AGENTS.md instructional content
- Regenerates llms.txt with current site information
- New npm sync commands
npm run sync:discovery- Update discovery files (development)npm run sync:discovery:prod- Update discovery files (production)npm run sync:all- Sync content + discovery files together (development)npm run sync:all:prod- Sync content + discovery files together (production)
- Fork configuration support for gitHubRepo
- Added gitHubRepoConfig to fork-config.json.example
- Updated configure-fork.ts with backward compatibility for legacy fields
Updated files: scripts/sync-discovery-files.ts, package.json, fork-config.json.example, scripts/configure-fork.ts, FORK_CONFIG.md, files.md
Documentation updated: README.md, docs.md, setup-guide.md, about.md, about-this-blog.md
v1.27.0
Released December 24, 2025
Homepage post limit and optional read more link
- Configurable post limit for homepage via
siteConfig.postsDisplay.homePostsLimit- Default limit set to 10 most recent posts
- Set to
undefinedto show all posts (no limit)
- Optional "read more" link below limited post list
- Configurable via
siteConfig.postsDisplay.homePostsReadMore - Customizable link text and destination URL
- Only appears when posts are limited and there are more posts than the limit
- Default links to
/blogpage - Can be disabled by setting
enabled: false
- Configurable via
Updated files: src/config/siteConfig.ts, src/pages/Home.tsx, src/styles/global.css
v1.26.0
Released December 24, 2025
Tag pages, related posts, and AI service links re-enabled
- Tag pages at
/tags/[tag]route- Dynamic tag archive pages showing all posts with a specific tag
- View mode toggle (list/cards) with localStorage persistence
- Mobile responsive layout matching existing blog page design
- Sitemap updated to include all tag pages dynamically
- Related posts component for blog post footers
- Shows up to 3 related posts based on shared tags
- Sorted by relevance (number of shared tags) then by date
- Only displays on blog posts (not static pages)
- Improved tag links in post footers
- Tags now link to
/tags/[tag]archive pages - Visual styling consistent with existing theme
- Tags now link to
- Open in AI service links re-enabled in CopyPageDropdown
- Uses GitHub raw URLs instead of Netlify paths (bypasses edge function issues)
- ChatGPT, Claude, and Perplexity links with universal prompt
- "Requires git push" hint for users (npm sync alone doesn't update GitHub)
- Visual divider separating AI options from other menu items
Updated files: src/config/siteConfig.ts, convex/schema.ts, convex/posts.ts, convex/http.ts, src/pages/TagPage.tsx, src/pages/Post.tsx, src/components/CopyPageDropdown.tsx, src/styles/global.css, src/App.tsx
Documentation updated: content/pages/docs.md, content/blog/setup-guide.md
v1.25.2
Released December 24, 2025
AI service links disabled due to Netlify edge function issues
-
Direct links to ChatGPT, Claude, and Perplexity removed from CopyPageDropdown
- AI crawlers cannot reliably fetch
/raw/*.mdfiles despite multiple configuration attempts - Netlify edge functions intercept requests before static files are served
- Multiple solutions attempted: excludedPath, code-level bypasses, AI crawler whitelisting, Netlify Functions, header adjustments
- None resolved the issue for ChatGPT or Perplexity (Claude works)
- AI crawlers cannot reliably fetch
-
Workaround for users
- Copy page: copies markdown to clipboard, paste directly into any AI tool
- View as Markdown: opens raw
.mdfile in browser for manual copying - Download as SKILL.md: downloads in Anthropic Agent Skills format
-
Removed Netlify Function at
/api/raw/:slug- Caused build failures and dependency conflicts
- Static
/raw/*.mdfiles still work in browsers
Updated files: src/components/CopyPageDropdown.tsx, netlify.toml
Documentation: content/blog/netlify-edge-excludedpath-ai-crawlers.md updated with detailed log of all attempted solutions
v1.25.1
Released December 24, 2025
Logo moved to top navigation header
- Logo now appears in header bar (top-left) on all pages
- Separate from back button and navigation links
- Reads from
siteConfig.innerPageLogoandsiteConfig.logo - Mobile responsive: logo positioned on left in header
Updated files: src/components/Layout.tsx, src/pages/Post.tsx, src/pages/Blog.tsx, src/styles/global.css
v1.25.0
Released December 24, 2025
Sidebar styling updated to match Cursor docs style
- Sidebar has alternate background color for visual separation
- Vertical border line on right side of sidebar
- Theme-aware colors for all four themes
- Sidebar width increased to 240px
- Mobile responsive: sidebar hidden below 1024px
Updated files: src/styles/global.css
v1.24.4
Released December 23, 2025
Navigation visibility control and hardcoded nav items
-
showInNavfield for pages to control navigation visibility- Pages can be published and accessible but hidden from navigation menu
- Set
showInNav: falsein page frontmatter to hide from nav - Defaults to
truefor backwards compatibility (all existing pages show in nav) - Pages with
showInNav: falseremain:- Published and accessible via direct URL
- Searchable via search indexes
- Available via API endpoints
- Just hidden from the navigation menu
- Matches the pattern used for
blogPage.showInNavin siteConfig.ts
-
Hardcoded navigation items configuration for React routes
- Add React route pages (like
/stats,/write) to navigation viasiteConfig.hardcodedNavItems - Configure navigation order, title, and visibility per route
- Set
showInNav: falseto hide from nav while keeping route accessible - Navigation combines Blog link, hardcoded nav items, and markdown pages
- All nav items sorted by
orderfield (lower = first)
- Add React route pages (like
Example configuration:
// src/config/siteConfig.ts
hardcodedNavItems: [
{
slug: "stats",
title: "Stats",
order: 10,
showInNav: true,
},
{
slug: "write",
title: "Write",
order: 20,
showInNav: true,
},
],
Updated files: convex/schema.ts, convex/pages.ts, scripts/sync-posts.ts, src/pages/Write.tsx, src/config/siteConfig.ts, src/components/Layout.tsx
Documentation updated: content/pages/docs.md, content/blog/setup-guide.md
v1.24.3
Released December 23, 2025
Inner page logo configuration
- Logo displays in header on blog page, individual posts, and static pages
- Desktop: logo positioned on the left (before back button)
- Mobile: logo positioned on the right (smaller size for compact header)
- Configurable via
siteConfig.innerPageLogo.enabledandsiteConfig.innerPageLogo.size - Does not affect homepage logo (controlled separately)
- Logo links to homepage when clicked
Configuration:
// src/config/siteConfig.ts
innerPageLogo: {
enabled: true, // Set to false to hide logo on inner pages
size: 28, // Logo height in pixels (keeps aspect ratio)
},
Updated files: src/config/siteConfig.ts, src/pages/Blog.tsx, src/pages/Post.tsx, src/styles/global.css
v1.24.2
Released December 23, 2025
Mobile menu redesign with sidebar integration
-
Mobile navigation controls moved to left side
- Hamburger menu, search, and theme toggle now positioned on the left
- Order: hamburger first, then search, then theme toggle
- Consistent left-aligned navigation on mobile devices
-
Sidebar table of contents in mobile menu
- When a page or blog post has sidebar layout, the TOC appears in the mobile menu
- Desktop sidebar hidden on mobile (max-width: 768px) since accessible via hamburger
- Back button and CopyPageDropdown remain visible above main content on mobile
- Sidebar headings displayed with same collapsible tree structure as desktop
-
Typography standardization
- All mobile menu elements use CSS variables for font sizes
- Font-family standardized using
inheritto match body font - Mobile menu TOC links use consistent sizing with desktop sidebar
- Added CSS variables:
--font-size-mobile-toc-titleand--font-size-mobile-toc-link
New files: src/context/SidebarContext.tsx
Updated files: src/components/Layout.tsx, src/components/MobileMenu.tsx, src/pages/Post.tsx, src/styles/global.css
v1.24.1
Released December 23, 2025
Sidebar navigation fixes
-
Fixed anchor link navigation when sidebar sections are collapsed or expanded
- Navigation now correctly scrolls to target headings with proper header offset
- Sections expand automatically when navigating to nested headings
- Collapse button works reliably without triggering navigation
- Manual collapse/expand state persists during scrolling
-
Fixed heading extraction to ignore code blocks
- Sidebar no longer shows example headings from markdown code examples
- Only actual page headings appear in the table of contents
- Filters out fenced code blocks (```) and indented code blocks
Updated files: src/components/PageSidebar.tsx, src/utils/extractHeadings.ts
v1.24.0
Released December 23, 2025
Sidebar layout for blog posts
- Blog posts now support
layout: "sidebar"frontmatter field - Previously only available for static pages, now works for posts too
- Enables docs-style layout with table of contents sidebar for long-form content
- Same features as page sidebar: automatic TOC extraction, active heading highlighting, smooth scroll navigation
- Mobile responsive: stacks to single column below 1024px
Add layout: "sidebar" to any blog post frontmatter to enable the sidebar layout. The sidebar extracts headings (H1, H2, H3) automatically and only appears if headings exist in the content.
Example:
---
title: "My Tutorial"
description: "A detailed guide"
date: "2025-01-20"
slug: "my-tutorial"
published: true
tags: ["tutorial"]
layout: "sidebar"
---
Updated files: convex/schema.ts, scripts/sync-posts.ts, convex/posts.ts, src/pages/Post.tsx, src/pages/Write.tsx
Documentation updated: docs.md, setup-guide.md, how-to-publish.md
v1.23.0
Released December 23, 2025
Collapsible sections in markdown
- Create expandable/collapsible content using HTML
<details>and<summary>tags - Use
<details open>attribute for sections that start expanded by default - Supports nested collapsible sections for multi-level content
- Theme-aware styling for all four themes (dark, light, tan, cloud)
- Works with all markdown content inside: lists, code blocks, bold, italic, links, etc.
Example usage:
<details>
<summary>Click to expand</summary>
Hidden content here with **markdown** support.
</details>
New packages: rehype-raw, rehype-sanitize
Updated files: src/components/BlogPost.tsx, src/styles/global.css
Documentation updated: markdown-with-code-examples.md, docs.md
v1.22.0
Released December 21, 2025
Sidebar layout for pages
- Pages can now use a docs-style layout with table of contents sidebar
- Add
layout: "sidebar"to page frontmatter to enable - Left sidebar displays TOC extracted from H1, H2, H3 headings automatically
- Two-column grid layout: 220px sidebar + flexible content area
- Active heading highlighting on scroll
- Smooth scroll navigation to sections
- Sidebar only appears if headings exist in content
- Mobile responsive: stacks to single column below 1024px
- CopyPageDropdown remains in top navigation for sidebar pages
New files: src/utils/extractHeadings.ts, src/components/PageSidebar.tsx
Updated files: convex/schema.ts, scripts/sync-posts.ts, convex/pages.ts, src/pages/Post.tsx, src/styles/global.css
v1.21.0
Released December 21, 2025
Blog page view mode toggle
- Blog page now supports two view modes: list view and card view
- Toggle button in blog header switches between views
- List view: year-grouped posts with titles, read time, and dates
- Card view: 3-column grid with thumbnails, titles, excerpts, and metadata
- Default view configurable via
siteConfig.blogPage.viewMode - Toggle visibility controlled by
siteConfig.blogPage.showViewToggle - View preference saved to localStorage and persists across visits
- Responsive grid: 3 columns (desktop), 2 columns (tablet), 1 column (mobile)
- Theme-aware styling for all four themes (dark, light, tan, cloud)
- Cards display post thumbnails from
imagefrontmatter field - Posts without images show cards without thumbnail areas
Updated files: src/pages/Blog.tsx, src/components/PostList.tsx, src/config/siteConfig.ts, src/styles/global.css
v1.20.3
Released December 21, 2025
SEO, AEO, and GEO improvements
- Raw markdown files now accessible to AI crawlers (ChatGPT, Perplexity)
- Added
/raw/path bypass in botMeta edge function so AI services receive markdown, not HTML - Sitemap now includes static pages (about, docs, contact, etc.)
- Security headers: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy
- Link header pointing to llms.txt for AI discovery
- Raw markdown files served with proper Content-Type and CORS headers
- Preconnect hints for Convex backend (faster API calls)
- Fixed URL consistency: openapi.yaml and robots.txt now use www.markdown.fast
v1.20.2
Released December 21, 2025
Write conflict prevention for heartbeat mutation
- Increased backend dedup window from 10s to 20s
- Increased frontend debounce from 10s to 20s to match backend
- Added random jitter (±5s) to heartbeat intervals to prevent synchronized calls across tabs
- Simplified early return to skip ANY update within dedup window
- Prevents "Documents read from or written to the activeSessions table changed" errors
v1.20.1
Released December 21, 2025
Visitor map styling improvements
- Removed box-shadow from map wrapper for cleaner flat design
- Increased land dot contrast for better globe visibility on all themes
- Increased land dot opacity from 0.6 to 0.85
- Darker/more visible land colors for light, tan, and cloud themes
- Lighter land color for dark theme to stand out on dark background
v1.20.0
Released December 21, 2025
Real-time visitor map on stats page
- Displays live visitor locations on a dotted world map
- Uses Netlify's built-in geo detection via edge function (no third-party API needed)
- Privacy friendly: stores city, country, and coordinates only (no IP addresses)
- Theme-aware colors for all four themes (dark, light, tan, cloud)
- Animated pulsing dots for active visitors
- Configurable via
siteConfig.visitorMap
New files:
netlify/edge-functions/geo.ts: Edge function returning geo data from Netlify headerssrc/components/VisitorMap.tsx: SVG world map component with visitor dots
Configuration:
// src/config/siteConfig.ts
visitorMap: {
enabled: true, // Set to false to hide
title: "Live Visitors", // Optional title above the map
},
Updated files: convex/schema.ts, convex/stats.ts, src/hooks/usePageTracking.ts, src/pages/Stats.tsx, src/config/siteConfig.ts, src/styles/global.css
Documentation updated: setup-guide.md, docs.md, FORK_CONFIG.md, fork-config.json.example, fork-configuration-guide.md
v1.19.2
Released December 21, 2025
Improved AI service prompts in CopyPageDropdown
- Updated ChatGPT, Claude, and Perplexity prompts with clearer instructions
- AI now attempts to load raw markdown URL and provides fallback behavior
- If content loads: provides concise summary and asks how to help
- If content fails: states page could not be loaded without guessing content
Updated file: src/components/CopyPageDropdown.tsx
v1.19.1
Released December 21, 2025
GitHub Stars on Stats page
- New GitHub Stars card displays live star count from repository
- Fetches from GitHub public API (no token required)
- Uses Phosphor GithubLogo icon
- Stats page now shows 6 cards in a single row
- Responsive layout: 3x2 on tablet, 2x3 on mobile, stacked on small screens
Updated files: src/pages/Stats.tsx, src/styles/global.css
v1.19.0
Released December 21, 2025
Author display for posts and pages
- New optional
authorNameandauthorImagefrontmatter fields - Round avatar image displayed next to date and read time
- Works on individual post and page views (not on blog list)
- Write page updated with new frontmatter field reference
Example frontmatter:
authorName: "Your Name"
authorImage: "/images/authors/photo.png"
Place author avatar images in public/images/authors/. Recommended: square images (they display as circles).
Updated files: convex/schema.ts, scripts/sync-posts.ts, convex/posts.ts, convex/pages.ts, src/pages/Post.tsx, src/pages/Write.tsx, src/styles/global.css
Documentation updated: setup-guide.md, docs.md, files.md, README.md, AGENTS.md
New PRD: prds/howto-Frontmatter.md with reusable prompt for future frontmatter updates.
v1.18.1
Released December 21, 2025
CopyPageDropdown raw markdown URLs
- AI services (ChatGPT, Claude, Perplexity) now receive raw markdown file URLs instead of page URLs
- URL format:
/raw/{slug}.md(e.g.,/raw/setup-guide.md) - AI services can fetch and parse clean markdown content directly
- Includes metadata headers for structured parsing
- No HTML parsing required by AI services
v1.18.0
Released December 20, 2025
Automated fork configuration
- New
npm run configurecommand for one-step fork setup - Copy
fork-config.json.exampletofork-config.json - Edit the JSON file with your site information
- Run
npm run configureto apply all changes automatically
Two options for fork setup:
- Automated (recommended): JSON config file +
npm run configure - Manual: Follow step-by-step instructions in
FORK_CONFIG.md
The configure script updates all 11 configuration files:
| File | What it updates |
|---|---|
src/config/siteConfig.ts |
Site name, bio, GitHub, features |
src/pages/Home.tsx |
Intro paragraph, footer links |
src/pages/Post.tsx |
SITE_URL, SITE_NAME constants |
convex/http.ts |
SITE_URL, SITE_NAME constants |
convex/rss.ts |
SITE_URL, SITE_TITLE, SITE_DESCRIPTION |
index.html |
Meta tags, JSON-LD, page title |
public/llms.txt |
Site info, GitHub link |
public/robots.txt |
Sitemap URL |
public/openapi.yaml |
Server URL, site name |
public/.well-known/ai-plugin.json |
Plugin metadata |
src/context/ThemeContext.tsx |
Default theme |
New files: FORK_CONFIG.md, fork-config.json.example, scripts/configure-fork.ts
v1.17.0
Released December 20, 2025
GitHub contributions graph
- GitHub activity graph on homepage with theme-aware colors
- Year navigation with Phosphor CaretLeft/CaretRight icons
- Click graph to visit GitHub profile
- Configurable via
siteConfig.gitHubContributions - Uses public API (no GitHub token required)
Theme-specific contribution colors:
- Dark theme: GitHub green on dark background
- Light theme: Standard GitHub green
- Tan theme: Warm brown tones
- Cloud theme: Gray-blue tones
New component: src/components/GitHubContributions.tsx
Set enabled: false in siteConfig to disable.
v1.15.2
Released December 20, 2025
Write page font switcher
- Font switcher in
/writepage Actions section - Toggle between Serif and Sans-serif fonts in the writing area
- Font preference saved to localStorage and persists across sessions
- Uses same font families defined in global.css
v1.15.1
Released December 20, 2025
Write page theme and content fixes
- Fixed theme toggle icons on
/writepage to matchThemeToggle.tsx(Moon, Sun, Half2Icon, Cloud) - Content type switching now always updates the template in the writing area
v1.15.0
Released December 20, 2025
Write page three-column layout
- Redesigned
/writepage with Cursor docs-style three-column layout - Left sidebar: content type selector (Blog Post/Page) and action buttons (Clear, Theme)
- Center: full-screen writing area with Copy All button
- Right sidebar: frontmatter field reference with individual copy buttons for each field
- Warning message about refresh losing content
- Stats bar showing words, lines, and characters
v1.14.0
Released December 20, 2025
Write page Notion-like UI
- Redesigned
/writepage with full-screen, distraction-free writing experience - Floating header with home link, type selector, and action buttons
- Collapsible frontmatter panel on the right
- Removed borders from writing area for cleaner look
- Improved typography and spacing
v1.13.0
Released December 20, 2025
Markdown write page
- New
/writepage for drafting markdown content (not linked in navigation) - Content type selector for Blog Post or Page with appropriate frontmatter templates
- Frontmatter reference with copy buttons for each field
- Theme toggle matching site themes
- Word, line, and character counts
- localStorage persistence for content, type, and font preference
- Works with Grammarly and browser spellcheck
- Copy all button for easy content transfer
- Clear button to reset content
Access at yourdomain.com/write. Content stored in localStorage only.
v1.12.2
Released December 20, 2025
Centralized font-size CSS variables
- All font sizes now use CSS variables for easier customization
- Base scale from
--font-size-3xs(10px) to--font-size-hero(64px) - Component-specific variables for blog headings, navigation, search, stats, and more
- Mobile responsive overrides at 768px breakpoint
Edit src/styles/global.css to customize font sizes across the entire site by changing the :root variables.
v1.12.1
Released December 20, 2025
Open Graph image fix
- Posts with
imagein frontmatter now display their specific OG image when shared - Posts without images fall back to
og-default.svg - Pages now supported with
og:typeset to "website" instead of "article" - Relative image paths (like
/images/v17.png) resolve to absolute URLs
The /meta/post endpoint in convex/http.ts now passes the image field from posts and pages to the meta HTML generator. If no post matches the slug, it checks for a page with that slug.
v1.12.0
Released December 20, 2025
Dedicated blog page with configurable navigation
- New
/blogpage for dedicated post listing - Enable/disable via
siteConfig.blogPage.enabled - Control navigation position with
siteConfig.blogPage.order - Centralized site configuration in
src/config/siteConfig.ts - Flexible post display: homepage only, blog page only, or both
Configuration options:
// src/config/siteConfig.ts
blogPage: {
enabled: true, // Enable /blog route
showInNav: true, // Show in navigation
title: "Blog", // Page title
order: 0, // Nav order (lower = first)
},
displayOnHomepage: true, // Show posts on homepage
The Blog link now integrates with page navigation ordering. Set order: 5 to place it after pages with order 0-4, or order: 0 to keep it first.
New files: src/config/siteConfig.ts, src/pages/Blog.tsx
v1.11.1
Released December 20, 2025
Fix historical stats display and chunked backfilling
- Stats page now shows all historical page views correctly
- Changed
getStatsto use direct counting until aggregates are fully backfilled - Backfill mutation now processes 500 records at a time (chunked)
- Prevents memory limit issues with large datasets (16MB Convex limit)
- Schedules itself to continue processing until complete
v1.11.0
Released December 20, 2025
Aggregate component for efficient stats
- Replaced O(n) table scans with O(log n) aggregate counts
- Uses
@convex-dev/aggregatepackage for TableAggregate - Three aggregates: totalPageViews, pageViewsByPath, uniqueVisitors
- Backfill mutation for existing page view data
- Updated
convex/convex.config.tswith aggregate component registration - Updated
convex/stats.tsto use aggregate counts in getStats query - Updated
prds/howstatsworks.mdwith old vs new implementation comparison
Performance improvement: Stats queries now use pre-computed counts instead of scanning all page view records.
v1.10.0
Released December 20, 2025
Fork configuration documentation
- Added "Files to Update When Forking" section to docs and setup guide
- Lists all 9 configuration files users need to update when forking
- Includes backend configuration examples for Convex files
- Code snippets for
convex/http.ts,convex/rss.ts,src/pages/Post.tsx
Site branding updates
- Updated
public/robots.txtwith sitemap URL and header - Updated
public/llms.txtwith site name and description - Updated
public/.well-known/ai-plugin.jsonfor AI plugins - Updated
public/openapi.yamlAPI title and site name - Updated
convex/http.tsSITE_URL and SITE_NAME constants
Same fork documentation added to README.md for discoverability.
v1.9.0
Released December 20, 2025
Scroll-to-top button
- Appears after scrolling 300px (configurable)
- Uses Phosphor ArrowUp icon for consistency
- Smooth scroll animation (configurable)
- Works with all four themes (dark, light, tan, cloud)
- Enabled by default (can be disabled in Layout.tsx)
- Fade-in animation when appearing
- Responsive sizing for mobile devices
New component: src/components/ScrollToTop.tsx
Configuration via ScrollToTopConfig interface in src/components/Layout.tsx. Uses passive scroll listener for performance.
v1.8.0
Released December 20, 2025
Mobile menu and Generate Skill feature
- Mobile menu with hamburger navigation
- Slide-out drawer on mobile and tablet views
- Accessible with keyboard navigation (Escape to close)
- Focus trap for screen reader support
- Page links and Home link in drawer
- Auto-closes on route change
- Generate Skill option in CopyPageDropdown
- Formats post/page content as an AI agent skill file
- Downloads as
{slug}-skill.mdwith skill structure - Includes metadata, when to use, and instructions sections
New component: MobileMenu.tsx with HamburgerButton
v1.7.0
Released December 20, 2025
Raw markdown files and CopyPageDropdown improvements
- Static raw markdown files at
/raw/{slug}.md- Generated during
npm run syncandnpm run sync:prodinpublic/raw/directory - Each published post and page gets a corresponding static
.mdfile - Includes metadata header (type, date, reading time, tags)
- Generated during
- View as Markdown option in CopyPageDropdown
- Opens raw
.mdfile in new tab - Available on all post and page views
- Opens raw
- Perplexity added to AI service options in CopyPageDropdown
- Research articles directly in Perplexity with full content
- Featured image support for posts and pages
imagefield displays as square thumbnail in card view- Non-square images automatically cropped to center
- Improved markdown table CSS styling
- GitHub-style tables with proper borders
- Mobile responsive with horizontal scroll
- Theme-aware alternating row colors
New files: public/raw/*.md (generated), updated _redirects
v1.6.1
Released December 18, 2025
Documentation updates
- Added AGENTS.md with codebase instructions for AI coding agents
- Added Firecrawl import to all "When to sync vs deploy" tables
- Clarified import workflow: creates local files only, no
import:prodneeded - Updated docs: README, setup-guide, how-to-publish, docs page, about-this-blog
- Renamed
content/pages/changelog.mdtochangelog-page.mdto avoid confusion with root changelog
v1.6.0
Released December 18, 2025
Content import and LLM API enhancements
- Firecrawl content importer for external URLs
npm run import <url>scrapes and creates local markdown drafts- Creates drafts in
content/blog/with frontmatter - Then sync to dev (
npm run sync) or prod (npm run sync:prod) - No separate
import:prodcommand (import creates local files only)
- New
/api/exportendpoint for batch content fetching - AI plugin discovery at
/.well-known/ai-plugin.json - OpenAPI 3.0 specification at
/openapi.yaml - Enhanced
llms.txtwith complete API documentation
New dependencies: @mendable/firecrawl-js
New files: scripts/import-url.ts, public/.well-known/ai-plugin.json, public/openapi.yaml
v1.5.0
Released December 17, 2025
Frontmatter-controlled featured items
- Add
featured: trueto any post or page frontmatter - Use
featuredOrderto control display order (lower = first) - Featured items sync instantly with
npm run sync(no redeploy needed)
New Convex queries:
getFeaturedPosts: returns posts withfeatured: truegetFeaturedPages: returns pages withfeatured: true
Schema updates with featured and featuredOrder fields and by_featured index.
v1.4.0
Released December 17, 2025
Featured section with list/card view toggle
- Card view displays title and excerpt in a responsive grid
- Toggle button in featured header to switch between views
- View preference saved to localStorage
Logo gallery with continuous marquee scroll
- Clickable logos with configurable URLs
- CSS only animation for smooth infinite scrolling
- Configurable speed, position, and title
- Grayscale logos with color on hover
- Responsive sizing across breakpoints
- 5 sample logos included
New frontmatter field
excerptfield for posts and pages- Used for card view descriptions
- Falls back to description field for posts
v1.3.0
Released December 17, 2025
Real-time search with Command+K
- Search icon in top nav using Phosphor Icons
- Modal with keyboard navigation (arrow keys, Enter, Escape)
- Full text search across posts and pages using Convex search indexes
- Result snippets with context around search matches
- Distinguishes between posts and pages with type badges
Search uses Convex full text search with reactive queries. Results deduplicate from title and content searches. Title matches sort first.
v1.2.0
Released December 15, 2025
Real-time stats page at /stats
- Active visitors count with per-page breakdown
- Total page views and unique visitors
- Views by page sorted by popularity
Page view tracking via event records pattern (no write conflicts). Active session heartbeat system with 30s interval and 2min timeout. Cron job for stale session cleanup every 5 minutes.
New Convex tables: pageViews and activeSessions.
v1.1.0
Released December 14, 2025
Netlify Edge Functions for dynamic Convex HTTP proxying
rss.tsproxies/rss.xmland/rss-full.xmlsitemap.tsproxies/sitemap.xmlapi.tsproxies/api/postsand/api/post
Vite dev server proxy for RSS, sitemap, and API endpoints. Edge functions dynamically read VITE_CONVEX_URL from environment.
v1.0.0
Released December 14, 2025
Initial release
- Markdown posts with frontmatter parsing
- Static pages support (About, Projects, Contact)
- Four theme options: Dark, Light, Tan (default), Cloud
- Syntax highlighting for code blocks
- Year-grouped post list on home page
- Individual post pages with share buttons
SEO and discovery
- Dynamic sitemap at
/sitemap.xml - JSON-LD structured data for blog posts
- RSS feeds at
/rss.xmland/rss-full.xml - AI agent discovery with
llms.txt robots.txtwith rules for AI crawlers
API endpoints
/api/postsfor JSON list of all posts/api/post?slug=xxxfor single post as JSON or markdown
Copy Page dropdown for sharing to ChatGPT and Claude.
Technical stack
- React 18 with TypeScript
- Convex for real-time database
- react-markdown for rendering
- react-syntax-highlighter for code blocks
- Netlify deployment with edge functions