mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 04:09:14 +00:00
30 KiB
30 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[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