mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 04:09:14 +00:00
- Move mobile nav controls to left side (hamburger, search, theme) - Add sidebar TOC to mobile menu when page has sidebar layout - Hide desktop sidebar on mobile since accessible via hamburger - Standardize mobile menu typography with CSS variables - Use font-family inherit for consistent fonts across menu elements
37 KiB
37 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[1.24.2] - 2025-12-23
Changed
- Mobile menu redesigned for better sidebar integration
- Mobile navigation controls moved to left side (hamburger, search, theme toggle)
- Hamburger menu order: hamburger first, then search, then theme toggle
- Sidebar table of contents now appears in mobile menu when page has sidebar layout
- Desktop sidebar hidden on mobile (max-width: 768px) since it's accessible via hamburger menu
- Back button and CopyPageDropdown remain visible above main content on mobile
- Mobile menu typography standardized
- All mobile menu elements now use CSS variables for font sizes
- Font-family standardized using
inheritto match body font from global.css - Mobile menu TOC links use consistent font sizing with desktop sidebar
- Added CSS variables:
--font-size-mobile-toc-titleand--font-size-mobile-toc-link
Technical
- Updated
src/components/Layout.tsx: Reordered mobile nav controls, added sidebar context integration - Updated
src/components/MobileMenu.tsx: Added sidebar headings rendering in mobile menu - Updated
src/pages/Post.tsx: Provides sidebar headings to context for mobile menu - Updated
src/context/SidebarContext.tsx: New context for sharing sidebar data between components - Updated
src/styles/global.css: Mobile menu positioning, sidebar hiding on mobile, font standardization
[1.24.1] - 2025-12-23
Fixed
- Sidebar navigation anchor links now work correctly when sections are collapsed or expanded
- Fixed navigation scroll calculation to use proper header offset (80px)
- Expand ancestors before scrolling to ensure target is visible
- Use requestAnimationFrame to ensure DOM updates complete before scrolling
- Removed auto-expand from scroll handler to prevent interfering with manual collapse/expand
- Collapse button now properly isolated from link clicks with event handlers
Changed
- Updated
extractHeadings.tsto filter out headings inside code blocks- Prevents sidebar from showing example headings from markdown code examples
- Removes fenced code blocks (```) and indented code blocks before extracting headings
- Ensures sidebar only shows actual page headings, not code examples
Technical
- Updated
src/components/PageSidebar.tsx: Improved navigation logic and collapse button event handling - Updated
src/utils/extractHeadings.ts: AddedremoveCodeBlocksfunction to filter code before heading extraction
[1.24.0] - 2025-12-23
Added
- Sidebar layout support for blog posts
- Blog posts can now use
layout: "sidebar"frontmatter field (previously only available for pages) - Enables docs-style layout with table of contents sidebar for long-form posts
- Same features as page sidebar: automatic TOC extraction, active heading highlighting, smooth scroll navigation
- Mobile responsive: stacks to single column below 1024px
- Blog posts can now use
Changed
- Updated
Post.tsxto handle sidebar layout for both posts and pages - Updated
Write.tsxto includelayoutfield in blog post frontmatter reference
Technical
- Updated
convex/schema.ts: Added optionallayoutfield to posts table - Updated
scripts/sync-posts.ts: Parseslayoutfield from post frontmatter - Updated
convex/posts.ts: Includeslayoutfield in queries, mutations, and sync operations - Reuses existing sidebar components and CSS (no new components needed)
Documentation
- Updated
docs.md: Addedlayoutfield to blog posts frontmatter table, updated sidebar layout section - Updated
setup-guide.md: Clarified sidebar layout works for both posts and pages - Updated
how-to-publish.md: Addedlayoutfield to frontmatter reference table
[1.23.0] - 2025-12-23
Added
- Collapsible sections in markdown using HTML
<details>and<summary>tags- Create expandable/collapsible content in blog posts and pages
- Use
<details open>attribute for sections that start expanded - Supports nested collapsible sections
- Theme-aware styling for all four themes (dark, light, tan, cloud)
- Works with all markdown content inside: lists, code blocks, bold, italic, etc.
Technical
- Added
rehype-rawpackage to allow raw HTML pass-through in react-markdown - Added
rehype-sanitizepackage to strip dangerous tags while allowing safe ones - Custom sanitize schema allows
details,summarytags and theopenattribute - Updated
src/components/BlogPost.tsxwith rehype plugins - CSS styles for collapsible sections in
src/styles/global.css
Documentation
- Updated
markdown-with-code-examples.mdwith collapsible section examples - Updated
docs.mdwith collapsible sections documentation - Updated
files.mdwith BlogPost.tsx description change
[1.22.0] - 2025-12-21
Added
- Sidebar layout for pages with table of contents
- Add
layout: "sidebar"to page frontmatter to enable docs-style layout - Left sidebar displays table of contents extracted from H1, H2, H3 headings
- Two-column grid layout: 220px sidebar + flexible content area
- Sidebar only appears if headings exist in the page content
- Active heading highlighting on scroll
- Smooth scroll navigation to sections
- CopyPageDropdown remains in top navigation for sidebar pages
- Mobile responsive: stacks to single column below 1024px
- Add
Technical
- New utility:
src/utils/extractHeadings.tsfor parsing markdown headings - New component:
src/components/PageSidebar.tsxfor TOC navigation - Updated
convex/schema.ts: Added optionallayoutfield to pages table - Updated
scripts/sync-posts.ts: Parseslayoutfield from page frontmatter - Updated
convex/pages.ts: Includeslayoutfield in queries and mutations - Updated
src/pages/Post.tsx: Conditionally renders sidebar layout - CSS grid layout with sticky sidebar positioning
- Full-width container breaks out of main-content constraints
[1.21.0] - 2025-12-21
Added
- Blog page view mode toggle (list and card views)
- Toggle button in blog header to switch between list and card views
- Card view displays posts in a 3-column grid with thumbnails, titles, excerpts, and metadata
- List view shows year-grouped posts (existing behavior)
- View preference saved to localStorage
- Default view mode configurable via
siteConfig.blogPage.viewMode - Toggle visibility controlled by
siteConfig.blogPage.showViewToggle
- Post cards component
- Displays post thumbnails, titles, excerpts, read time, and dates
- Responsive grid: 3 columns (desktop), 2 columns (tablet), 1 column (mobile)
- Theme-aware styling for all four themes (dark, light, tan, cloud)
- Square thumbnails with hover zoom effect
- Cards without images display with adjusted padding
Changed
- Updated
PostListcomponent to support both list and card view modes - Updated
Blog.tsxto include view toggle button and state management - Updated
siteConfig.tswithblogPage.viewModeandblogPage.showViewToggleoptions
Technical
- New CSS classes:
.post-cards,.post-card,.post-card-image-wrapper,.post-card-content,.post-card-meta - Reuses featured card styling patterns for consistency
- Mobile responsive with adjusted grid columns and image aspect ratios
[1.20.3] - 2025-12-21
Fixed
- Raw markdown files now accessible to AI crawlers (ChatGPT, Perplexity)
- Added
/raw/path bypass in botMeta edge function - AI services were receiving HTML instead of markdown content
- Added
Added
- SEO and AEO improvements
- 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)
Changed
- Fixed URL consistency: openapi.yaml and robots.txt now use www.markdown.fast
[1.20.2] - 2025-12-21
Fixed
- 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 (not just same path)
- Prevents "Documents read from or written to the activeSessions table changed" errors
[1.20.1] - 2025-12-21
Changed
- 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
[1.20.0] - 2025-12-21
Added
- 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
- Visitor count badge showing online visitors
- Configurable via
siteConfig.visitorMap
- New Netlify edge function:
netlify/edge-functions/geo.ts- Returns user geo data from Netlify's automatic geo headers
- Endpoint:
/api/geo
- New React component:
src/components/VisitorMap.tsx- SVG-based world map with simplified continent outlines
- Lightweight (no external map library needed)
- Responsive design scales on mobile
Changed
- Updated
convex/schema.ts: Added optional location fields toactiveSessionstable (city, country, latitude, longitude) - Updated
convex/stats.ts: Heartbeat mutation accepts geo args, getStats returns visitor locations - Updated
src/hooks/usePageTracking.ts: Fetches geo data once on mount, passes to heartbeat - Updated
src/pages/Stats.tsx: Displays VisitorMap above "Currently Viewing" section - Updated
src/config/siteConfig.ts: AddedVisitorMapConfiginterface andvisitorMapconfig option
Documentation
- Updated setup-guide.md with Visitor Map section
- Updated docs.md with Visitor Map configuration
- Updated FORK_CONFIG.md with visitorMap config
- Updated fork-config.json.example with visitorMap option
- Updated fork-configuration-guide.md with visitorMap example
[1.19.1] - 2025-12-21
Added
- GitHub Stars card on Stats page
- Displays live star count from
waynesutton/markdown-siterepository - Fetches from GitHub public API (no token required)
- Uses Phosphor GithubLogo icon
- Updates on page load
- Displays live star count from
Changed
- Stats page now displays 6 cards in a single row (previously 5)
- Updated CSS grid for 6-column layout on desktop
- Responsive breakpoints adjusted for 6 cards (3x2 tablet, 2x3 mobile, 1x6 small mobile)
Technical
- Added
useStateanduseEffecttosrc/pages/Stats.tsxfor GitHub API fetch - Added
GithubLogoimport from@phosphor-icons/react - Updated
.stats-cards-moderngrid torepeat(6, 1fr) - Updated responsive nth-child selectors for proper borders
[1.19.0] - 2025-12-21
Added
- 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)
- Example:
authorName: "Your Name"andauthorImage: "/images/authors/photo.png"
- New optional
- Author images directory at
public/images/authors/- Place author avatar images here
- Recommended: square images (they display as circles)
- Write page updated with new frontmatter field reference
- Shows
authorNameandauthorImageoptions for both posts and pages
- Shows
Technical
- Updated
convex/schema.tswith authorName and authorImage fields - Updated
scripts/sync-posts.tsinterfaces and parsing - Updated
convex/posts.tsandconvex/pages.tsqueries and mutations - Updated
src/pages/Post.tsxto render author info - Updated
src/pages/Write.tsxwith new field definitions - CSS styles for
.post-author,.post-author-image,.post-author-name
Documentation
- Updated frontmatter tables in setup-guide.md, docs.md, files.md, README.md
- Added example usage in about-this-blog.md
[1.18.1] - 2025-12-21
Changed
- CopyPageDropdown AI services now use raw markdown URLs for better AI parsing
- ChatGPT, Claude, and Perplexity receive
/raw/{slug}.mdURLs instead of page URLs - AI services can fetch and parse clean markdown content directly
- Includes metadata headers (type, date, reading time, tags) for structured parsing
- No HTML parsing required by AI services
- ChatGPT, Claude, and Perplexity receive
Technical
- Renamed
buildUrlFromPageUrltobuildUrlFromRawMarkdownin AIService interface - Handler builds raw markdown URL from page origin and slug
- Updated prompt text to reference "raw markdown file URL"
[1.18.0] - 2025-12-20
Added
- Automated fork configuration with
npm run configure- Copy
fork-config.json.exampletofork-config.json - Edit JSON with your site information
- Run
npm run configureto apply all changes automatically - Updates all 11 configuration files in one command
- Copy
- Two options for fork setup
- Option 1: Automated (recommended): JSON config + single command
- Option 2: Manual: Follow step-by-step guide in
FORK_CONFIG.md
FORK_CONFIG.mdcomprehensive fork guide- YAML template for AI agent configuration
- Manual code snippets for each file
- AI agent prompt for automated updates
fork-config.json.exampletemplate with all configuration options- Site name, URL, description
- Creator social links (Twitter, LinkedIn, GitHub)
- Bio and intro text
- Logo gallery settings
- GitHub contributions config
- Blog page and theme options
Technical
- New script:
scripts/configure-fork.ts - New npm command:
npm run configure - Reads JSON config and updates 11 files with string replacements
- Updates: siteConfig.ts, Home.tsx, Post.tsx, http.ts, rss.ts, index.html, llms.txt, robots.txt, openapi.yaml, ai-plugin.json, ThemeContext.tsx
[1.17.0] - 2025-12-20
Added
- GitHub contributions graph on homepage
- Displays yearly contribution activity with theme-aware colors
- Fetches data from public API (no GitHub token required)
- Year navigation with Phosphor icons (CaretLeft, CaretRight)
- Click graph to visit GitHub profile
- Configurable via
siteConfig.gitHubContributions
- Theme-specific contribution colors
- Dark theme: GitHub green on dark background
- Light theme: Standard GitHub green
- Tan theme: Warm brown tones matching site palette
- Cloud theme: Gray-blue tones
- Mobile responsive design
- Scales down on tablets and phones
- Day labels hidden on small screens for space
- Touch-friendly navigation buttons
Technical
- New component:
src/components/GitHubContributions.tsx - Uses
github-contributions-api.jogruber.depublic API - CSS variables for contribution level colors per theme
- Configuration interface:
GitHubContributionsConfig - Set
enabled: falsein siteConfig to disable
[1.16.0] - 2025-12-21
Added
- Public markdown writing page at
/write(not linked in navigation)- Three-column Cursor docs-style layout
- Left sidebar: Home link, content type selector (Blog Post/Page), actions (Clear, Theme, Font)
- Center: Full-height writing area with title, Copy All button, and borderless textarea
- Right sidebar: Frontmatter reference with copy icon for each field
- Font switcher in Actions section
- Toggle between Serif and Sans-serif fonts
- Font preference saved to localStorage
- Theme toggle matching the rest of the app (Moon, Sun, Half2Icon, Cloud)
- localStorage persistence for content, type, and font preference
- Word, line, and character counts in status bar
- Warning banner: "Refresh loses content"
- Grammarly and browser spellcheck compatible
- Works with all four themes (dark, light, tan, cloud)
Technical
- New component:
src/pages/Write.tsx - Route:
/write(added tosrc/App.tsx) - Three localStorage keys:
markdown_write_content,markdown_write_type,markdown_write_font - CSS Grid layout (220px | 1fr | 280px)
- Uses Phosphor icons: House, Article, File, Trash, CopySimple, Warning, Check
- Uses lucide-react and radix-ui icons for theme toggle (consistent with ThemeToggle.tsx)
[1.15.1] - 2025-12-21
Fixed
- Theme toggle icons on
/writepage now matchThemeToggle.tsxcomponent- dark: Moon icon (lucide-react)
- light: Sun icon (lucide-react)
- tan: Half2Icon (radix-ui) - consistent with rest of app
- cloud: Cloud icon (lucide-react)
- Content type switching (Blog Post/Page) now always updates writing area template
Technical
- Replaced Phosphor icons (Moon, Sun, Leaf, CloudSun) with lucide-react and radix-ui icons
handleTypeChangenow always regenerates template when switching types
[1.15.0] - 2025-12-21
Changed
- Redesigned
/writepage with three-column Cursor docs-style layout- Left sidebar: Home link, content type selector (Blog Post/Page), actions (Clear, Theme)
- Center: Full-height writing area with title, Copy All button, and borderless textarea
- Right sidebar: Frontmatter reference with copy icon for each field
- Frontmatter fields panel with per-field copy buttons
- Each frontmatter field shows name, example value, and copy icon
- Click to copy individual field syntax to clipboard
- Required fields marked with red asterisk
- Fields update dynamically when switching between Blog Post and Page
- Warning banner for unsaved content
- "Refresh loses content" warning in left sidebar with warning icon
- Helps users remember localStorage persistence limitations
- Enhanced status bar
- Word, line, and character counts in sticky footer
- Save hint with content directory path
Technical
- Three-column CSS Grid layout (220px sidebar | 1fr main | 280px right sidebar)
- Theme toggle cycles through dark, light, tan, cloud with matching icons
- Collapsible sidebars on mobile (stacked layout)
- Uses Phosphor icons: House, Article, File, Trash, CopySimple, Warning, Check
[1.14.0] - 2025-12-20
Changed
- Redesigned
/writepage with Notion-like minimal UI- Full-screen distraction-free writing experience
- Removed site header for focused writing environment
- Wider writing area (900px max-width centered)
- Borderless textarea with transparent background
- Own minimal header with home link, type selector, and icon buttons
- Improved toolbar design
- Home icon link to return to main site
- Clean dropdown for content type selection (no borders)
- Collapsible frontmatter fields panel (hidden by default)
- Theme toggle in toolbar (cycles through dark, light, tan, cloud)
- Icon buttons with subtle hover states
- Copy button with inverted theme colors
- Enhanced status bar
- Sticky footer with word/line/character counts
- Save hint with content directory path
- Dot separators between stats
Technical
- Write page now renders without Layout component wrapper
- Added Phosphor icons: House, Sun, Moon, CloudSun, Leaf, Info, X
- CSS restructured for minimal aesthetic (
.write-wrapper,.write-header, etc.) - Mobile responsive with hidden copy text and save hint on small screens
[1.13.0] - 2025-12-20
Added
- Public markdown writing page at
/write(not linked in navigation)- Dropdown to select between "Blog Post" and "Page" content types
- Frontmatter fields reference panel with required/optional indicators
- Copy button using Phosphor CopySimple icon
- Clear button to reset content to template
- Status bar showing lines, words, and characters count
- Usage hint with instructions for saving content
- localStorage persistence for writing session
- Content persists across page refreshes within same browser
- Each browser has isolated content (session privacy)
- Content type selection saved separately
- Auto-generated frontmatter templates
- Blog post template with all common fields
- Page template with navigation fields
- Current date auto-populated in templates
Technical
- New component:
src/pages/Write.tsx - Route:
/write(added tosrc/App.tsx) - CSS styles added to
src/styles/global.css - Works with all four themes (dark, light, tan, cloud)
- Plain textarea for Grammarly and browser spellcheck compatibility
- Mobile responsive design with adjusted layout for smaller screens
- No Convex backend required (localStorage only)
[1.12.2] - 2025-12-20
Added
- Centralized font-size configuration using CSS variables in
global.css- Base size scale from 10px to 64px with semantic names
- Component-specific variables for consistent sizing
- Mobile responsive overrides at 768px breakpoint
- All hardcoded font sizes converted to CSS variables for easier customization
Technical
- Font sizes defined in
:rootselector with--font-size-*naming convention - Mobile breakpoint uses same variables with smaller values
- Base scale: 3xs (10px), 2xs (11px), xs (12px), sm (13px), md (14px), base (16px), lg (17px), xl (18px), 2xl (20px), 3xl (24px), 4xl (28px), 5xl (32px), 6xl (36px), hero (64px)
[1.12.1] - 2025-12-20
Fixed
- Open Graph images now use post/page
imagefield from frontmatter- Posts with images in frontmatter display their specific OG image
- Posts without images fall back to
og-default.svg - Pages now supported with appropriate
og:typeset to "website" - Relative image paths resolved to absolute URLs
Changed
- Renamed
generatePostMetaHtmltogenerateMetaHtmlinconvex/http.ts /meta/postendpoint now checks for pages if no post found- Meta HTML generation accepts optional
imageandtypeparameters
Technical
- Updated
convex/http.tswith image resolution logic - Handles both absolute URLs and relative paths for images
- Deployed to production Convex
[1.12.0] - 2025-12-20
Added
- Dedicated blog page at
/blogwith configurable display- Enable/disable via
siteConfig.blogPage.enabled - Show/hide from navigation via
siteConfig.blogPage.showInNav - Custom page title via
siteConfig.blogPage.title - Navigation order via
siteConfig.blogPage.order(lower = first)
- Enable/disable via
- Centralized site configuration in
src/config/siteConfig.ts- Moved all site settings from
Home.tsxto dedicated config file - Easier to customize when forking
- Moved all site settings from
- Flexible post display options
displayOnHomepage: Show posts on the homepageblogPage.enabled: Show posts on dedicated/blogpage- Both can be enabled for dual display
Changed
- Navigation now combines Blog link with pages and sorts by order
- Blog link position controlled by
siteConfig.blogPage.order - Pages sorted by frontmatter
orderfield (lower = first) - Items without order default to 999 (appear last, alphabetically)
- Blog link position controlled by
Home.tsximports siteConfig instead of defining inlineLayout.tsxuses unified nav item sorting for desktop and mobile
Technical
- New file:
src/config/siteConfig.ts - New page:
src/pages/Blog.tsx - Updated:
src/App.tsx(conditional blog route) - Updated:
src/components/Layout.tsx(nav item ordering) - Updated:
src/styles/global.css(blog page styles)
[1.11.1] - 2025-12-20
Fixed
- Stats page now shows all historical page views correctly
- Changed
getStatsto use direct counting until aggregates are fully backfilled - Ensures accurate stats display even if aggregate backfilling is incomplete
- Changed
Changed
- Chunked backfilling for aggregate component
- Backfill mutation now processes 500 records at a time
- Prevents memory limit issues with large datasets (16MB Convex limit)
- Schedules itself to continue processing until complete
- Progress visible in Convex dashboard logs
Technical
backfillAggregatesChunkinternal mutation handles pagination- Uses
ctx.scheduler.runAfterto chain batch processing - Tracks seen session IDs across chunks for unique visitor counting
[1.11.0] - 2025-12-20
Added
- Aggregate component for efficient O(log n) stats counts
- Replaces O(n) table scans with pre-computed denormalized counts
- Uses
@convex-dev/aggregatepackage for TableAggregate - Three aggregates: totalPageViews, pageViewsByPath, uniqueVisitors
- Backfill mutation for existing page view data
stats:backfillAggregatespopulates counts from existing data- Idempotent and safe to run multiple times
Changed
recordPageViewmutation now updates aggregate components- Inserts into pageViewsByPath aggregate for per-page counts
- Inserts into totalPageViews aggregate for global count
- Inserts into uniqueVisitors aggregate for new sessions only
getStatsquery now uses aggregate counts- O(log n) count operations instead of O(n) table scans
- Consistent fast response times regardless of data size
- Still queries posts/pages for title matching
Technical
- New file:
convex/convex.config.ts(updated with aggregate component registrations) - Three TableAggregate instances with different namespacing strategies
- Performance improvement scales better with growing page view data
Documentation
- Updated
prds/howstatsworks.mdwith old vs new implementation comparison - Added aggregate component usage examples and configuration
[1.10.0] - 2025-12-20
Added
- Fork configuration documentation
- "Files to Update When Forking" section in docs.md and setup-guide.md
- Lists all 9 files with site-specific configuration
- Backend configuration examples for Convex files
- Code snippets for
convex/http.ts,convex/rss.ts,src/pages/Post.tsx
- Same documentation added to README.md for discoverability
Changed
- Updated site branding across all configuration files
public/robots.txt: Updated sitemap URL and headerpublic/llms.txt: Updated site name and descriptionpublic/.well-known/ai-plugin.json: Updated name and description for AI pluginspublic/openapi.yaml: Updated API title and site name exampleconvex/http.ts: Updated SITE_URL and SITE_NAME constants
Documentation
- Setup guide table of contents now includes fork configuration sections
- Docs page configuration section expanded with backend file list
- All AI discovery files reflect new "markdown sync site" branding
[1.9.0] - 2025-12-20
Added
- 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
Technical
- New component:
src/components/ScrollToTop.tsx- Configurable via
ScrollToTopConfiginterface - Exports
defaultScrollToTopConfigfor customization - Uses passive scroll listener for performance
- Configurable via
- Configuration options in Layout.tsx
scrollToTopConfig - CSS styles added to global.css with theme-specific shadows
[1.8.0] - 2025-12-20
Added
- 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
- Smooth CSS transform animations
- 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
- Uses Download icon from lucide-react
Changed
- Layout.tsx now includes hamburger button and MobileMenu component
- Desktop navigation hidden on mobile, mobile menu hidden on desktop
- Improved responsive navigation across all breakpoints
Technical
- New component:
src/components/MobileMenu.tsx - HamburgerButton exported from MobileMenu for Layout use
- New
formatAsSkill()function for skill file generation - New
handleDownloadSkill()handler with blob download logic - Uses browser File API for client-side file download
- CSS styles for mobile menu in global.css
[1.7.0] - 2025-12-20
Added
- Static raw markdown files at
/raw/{slug}.md- Generated during
npm run sync(development) ornpm run sync:prod(production) inpublic/raw/directory - Each published post and page gets a corresponding static
.mdfile - SEO indexable and accessible to AI agents
- 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
- Sends full markdown content via URL parameter
- Research articles directly in Perplexity
- Featured image support for posts and pages
imagefield in frontmatter displays as square thumbnail in card view- Non-square images automatically cropped to center
- Recommended size: 400x400px minimum (800x800px for retina)
Changed
- CopyPageDropdown now accepts
slugprop for raw file links - Updated
_redirectsto serve/raw/*files directly - Improved markdown table CSS styling
- GitHub-style tables with proper borders
- Mobile responsive with horizontal scroll
- Theme-aware alternating row colors
- Hover states for better readability
Technical
- Updated
scripts/sync-posts.tsto generatepublic/raw/files - Files are regenerated on each sync (old files cleaned up)
- Only published posts and pages generate raw files
- CopyPageDropdown uses FileText icon from lucide-react for View as Markdown
[1.6.1] - 2025-12-18
Added
- AGENTS.md with codebase instructions for AI coding agents
Changed
- Added Firecrawl import to all "When to sync vs deploy" tables in docs
- Clarified import workflow: creates local files only, no
import:prodneeded - Updated README, setup-guide, how-to-publish, docs page, about-this-blog
- Renamed
content/pages/changelog.mdtochangelog-page.mdto avoid confusion with root changelog
[1.6.0] - 2025-12-18
Added
- Firecrawl content importer for external URLs
- New
npm run import <url>command - Scrapes URLs and converts to local markdown drafts
- Creates drafts in
content/blog/with frontmatter - Uses Firecrawl API (requires
FIRECRAWL_API_KEYin.env.local) - Then sync to dev (
npm run sync) or prod (npm run sync:prod) - No separate
import:prodcommand needed (import creates local files only)
- New
- New API endpoint
/api/exportfor batch content fetching- Returns all posts with full markdown content
- Single request for LLM ingestion
- AI plugin discovery at
/.well-known/ai-plugin.json- Standard format for AI tool integration
- OpenAPI 3.0 specification at
/openapi.yaml- Full API documentation
- Describes all endpoints, parameters, and responses
- Enhanced
llms.txtwith complete API documentation- Added all new endpoints
- Improved quick start section
- Added response schema documentation
Technical
- New script:
scripts/import-url.ts - New package dependency:
@mendable/firecrawl-js - Updated
netlify/edge-functions/api.tsfor/api/exportproxy - Updated
convex/http.tswith export endpoint - Created
public/.well-known/directory
[1.5.0] - 2025-12-17
Added
- 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)
- Add
- New Convex queries for featured content
getFeaturedPosts: returns posts withfeatured: truegetFeaturedPages: returns pages withfeatured: true
- Schema updates with
featuredandfeaturedOrderfields- Added
by_featuredindex for efficient queries
- Added
Changed
- Home.tsx now queries featured items from Convex instead of siteConfig
- FeaturedCards component uses Convex queries for real-time updates
- Removed hardcoded
featuredItemsandfeaturedEssaysfrom siteConfig
Technical
- Updated sync script to parse
featuredandfeaturedOrderfrom frontmatter - Added index on
featuredfield in posts and pages tables - Both list and card views now use frontmatter data
[1.4.0] - 2025-12-17
Added
- 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 for easy customization
- New
excerptfield for posts and pages frontmatter- Used for card view descriptions
- Falls back to description field for posts
- Expanded
siteConfigin Home.tsxfeaturedViewMode: 'list' or 'cards'showViewToggle: enable user togglelogoGallery: full configuration object
Technical
- New components:
FeaturedCards.tsx,LogoMarquee.tsx - Updated schema with optional excerpt field
- Updated sync script to parse excerpt from frontmatter
- CSS uses theme variables for all four themes
- Mobile responsive grid (3 to 2 to 1 columns for cards)
[1.3.0] - 2025-12-17
Added
- Real-time search with Command+K keyboard shortcut
- 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 indexes for pages table (title and content)
- New
@phosphor-icons/reactdependency for search icon
Technical
- Uses Convex full text search with reactive queries
- Deduplicates results from title and content searches
- Sorts results with title matches first
- Mobile responsive modal design
- All four themes supported (dark, light, tan, cloud)
[1.2.0] - 2025-12-15
Added
- Real-time stats page at
/statswith live visitor tracking- 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 (30s interval, 2min timeout)
- Cron job for stale session cleanup every 5 minutes
- New Convex tables:
pageViewsandactiveSessions - Stats link in homepage footer
Technical
- Uses anonymous session UUIDs (no PII stored)
- All stats update in real-time via Convex subscriptions
- Mobile responsive stats grid (4 to 2 to 1 columns)
- Theme support with CSS variables (dark, light, tan, cloud)
[1.1.0] - 2025-12-14
Added
- 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
Changed
- Replaced hardcoded Convex URLs in netlify.toml with edge functions
- Edge functions dynamically read
VITE_CONVEX_URLfrom environment - Updated setup guide, docs, and README with edge function documentation
Fixed
- RSS feeds and sitemap now work without manual URL configuration
- Local development properly proxies API routes to Convex
[1.0.0] - 2025-12-14
Added
- Initial project setup with Vite, React, TypeScript
- Convex backend with posts, pages, viewCounts, and siteConfig tables
- Markdown blog post support with frontmatter parsing
- Static pages support (About, Projects, Contact) with navigation
- Four theme options: Dark, Light, Tan (default), Cloud
- Font configuration option in global.css with serif (New York) as default
- Syntax highlighting for code blocks using custom Prism themes
- Year-grouped post list on home page
- Individual post pages with share buttons
- SEO optimization with dynamic sitemap at
/sitemap.xml - JSON-LD structured data injection for blog posts
- RSS feeds at
/rss.xmland/rss-full.xml(full content for LLMs) - AI agent discovery with
llms.txtfollowing llmstxt.org standard robots.txtwith rules for AI crawlers- API endpoints for LLM access:
/api/posts- JSON list of all posts/api/post?slug=xxx- Single post as JSON or markdown
- Copy Page dropdown for sharing to ChatGPT, Claude
- Open Graph and Twitter Card meta tags
- Netlify edge function for social media crawler detection
- Build-time markdown sync from
content/blog/to Convex - Responsive design for mobile, tablet, and desktop
Security
- All HTTP endpoints properly escape HTML and XML output
- Convex queries use indexed lookups
- External links use rel="noopener noreferrer"
- No console statements in production code
Technical Details
- React 18 with TypeScript
- Convex for real-time database
- react-markdown for rendering
- react-syntax-highlighter for code blocks
- date-fns for date formatting
- lucide-react for icons
- Netlify deployment with edge functions
- SPA 404 fallback configured