30 KiB
Markdown Blog - Tasks
To Do
- docs pages
- fix site confg link
- npm package
Current Status
v2.6.0 ready. Multi-model AI chat and image generation in Dashboard.
Completed
-
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, GPT-4o, Gemini 2.0 Flash)
- Lazy API key validation with friendly setup instructions per provider
- Image generation with Nano Banana (gemini-2.0-flash-exp-image-generation) and Nano Banana Pro (imagen-3.0-generate-002)
- Aspect ratio selector for images (1:1, 16:9, 9:16, 4:3, 3:4)
- Generated images stored in Convex storage with session tracking
- New
aiDashboardconfiguration in siteConfig.ts - New
convex/aiImageGeneration.tsfor Gemini image generation - New
aiGeneratedImagestable in schema for tracking generated images - Updated aiChatActions.ts with multi-provider support (Anthropic, OpenAI, Google)
- Updated AIChatView.tsx with selectedModel prop
- CSS styles for AI Agent tabs, model selectors, and image display
- Updated files.md, changelog.md, TASK.md, changelog-page.md
-
Social footer icons in header navigation
- Added
showInHeaderoption tositeConfig.socialFooterconfig - Exported
platformIconsfrom SocialFooter.tsx for reuse - Updated Layout.tsx to render social icons in header (left of search)
- Added CSS styles for
.header-social-linksand.header-social-link - Added showInHeader to configure-fork.ts for automated setup
- Updated FORK_CONFIG.md, fork-config.json.example, docs.md, setup-guide.md
- Added
-
YouTube and Twitter/X embed support with domain whitelisting
- Added
ALLOWED_IFRAME_DOMAINSconstant for whitelisted domains (YouTube, Twitter/X) - Added
iframeto sanitize schema with allowed attributes - Added custom iframe component handler with domain validation
- Auto-adds
sandboxandloading="lazy"attributes for security - Non-whitelisted iframes silently blocked
- Added
.embed-containerCSS styles for responsive embeds - Updated markdown-with-code-examples.md with Embeds section
- Works on both blog posts and pages
- Updated files.md, TASK.md, changelog.md, changelog-page.md
- Added
-
Author pages at
/author/:authorSlugwith post list- Added
by_authorNameindex to posts table in convex/schema.ts - Added
getAllAuthorsandgetPostsByAuthorqueries in convex/posts.ts - Created AuthorPage.tsx component with view mode toggle (list/cards)
- Added
/author/:authorSlugroute in App.tsx - Made authorName clickable in Post.tsx (links to author page)
- Added author link styles and author page styles to global.css
- Added author pages to sitemap in convex/http.ts
- Updated files.md with AuthorPage.tsx documentation
- Saved implementation plan to prds/authorname-blogs.md
- Added
-
Homepage intro loading flash fix
- Removed "Loading..." text from Suspense fallback in main.tsx
- Fixed Home.tsx conditional to render nothing while homeIntro query loads (undefined vs null)
- Home intro content now appears without any visible loading state or fallback
- Matches loading pattern used by Post.tsx for docs pages
-
ES module compatibility fix for configure-fork.ts
- Fixed
__dirname is not definederror when runningnpm run configure - Added
fileURLToPathimport fromurlmodule - Created ES module equivalent of
__dirnameusingimport.meta.url - Updated files.md, changelog.md, changelog-page.md, TASK.md
- Fixed
-
Footer content via markdown page (footer.md)
- Created
content/pages/footer.mdfor managing footer content via markdown sync - Footer content syncs with
npm run syncwithout redeploy needed - Falls back to
siteConfig.footer.defaultContentwhen page not found - Updated Home.tsx and Blog.tsx to fetch footer page by slug
- Updated files.md, changelog.md, changelog-page.md, FORK_CONFIG.md with documentation
- Created
-
CLAUDE.md and Claude skills documentation
- Created CLAUDE.md in root with project instructions for Claude Code
- Created .claude/skills/ directory with three focused skill files
- frontmatter.md: Complete frontmatter syntax and all 25+ field options
- convex.md: Convex patterns specific to this app (indexes, idempotent mutations, conflict prevention)
- sync.md: How sync commands work and content flow from markdown to database
- Updated sync-discovery-files.ts to automatically update CLAUDE.md during sync
- Updated files.md, changelog.md, changelog-page.md, TASK.md with feature documentation
-
Image lightbox for blog posts and pages
- Added ImageLightboxConfig interface to siteConfig.ts with enabled option
- Created ImageLightbox component in BlogPost.tsx with backdrop, close button, keyboard support
- Updated img renderer to add click handler and clickable cursor when lightbox enabled
- Added CSS styles for lightbox backdrop, image, close button, and caption
- Added imageLightboxEnabled to Dashboard config generator
- Updated documentation: docs.md, setup-guide.md, files.md, changelog.md, changelog-page.md
- Images show pointer cursor and hover effect when lightbox is enabled
- Lightbox closes on backdrop click, Escape key, or close button
- Alt text displayed as caption in lightbox
- Default configuration: enabled: true (lightbox active by default)
-
Stats page configuration option for public/private access
- Added StatsPageConfig interface to siteConfig.ts with enabled and showInNav options
- Updated App.tsx to conditionally render /stats route based on config
- Updated Stats.tsx to check if enabled and show disabled message if not
- Updated Layout.tsx to hide stats nav item when disabled
- Default configuration: enabled: true (public), showInNav: true (visible in nav)
- Follows same pattern as NewsletterAdmin for consistency
- Updated files.md with stats page configuration notes
- Updated changelog.md with v1.43.0 entry
- Updated TASK.md with completed task
-
Honeypot bot protection for contact and newsletter forms
- Added honeypot state and hidden field to ContactForm.tsx
- Added honeypot state and hidden field to NewsletterSignup.tsx
- Hidden "Website" field for contact form bot detection
- Hidden "Fax" field for newsletter signup bot detection
- Bots receive fake success message (no data submitted)
- CSS positioning (position: absolute, left: -9999px) hides fields from users
- aria-hidden="true" and tabIndex={-1} for accessibility
- Different field names per form to avoid pattern detection
- Updated files.md with honeypot protection notes
- Updated changelog.md with v1.42.0 entry
-
Blog heading styles for home intro content
- Added generateSlug, getTextContent, HeadingAnchor helper functions to Home.tsx
- Updated ReactMarkdown components to include h1-h6 with blog-h* classes
- Added clickable anchor links (#) that appear on hover for each heading
- Automatic ID generation from heading text for anchor navigation
- Added blog styling for lists (blog-ul, blog-ol, blog-li), blockquotes (blog-blockquote), horizontal rules (blog-hr), and links (blog-link)
- Updated files.md, changelog.md, changelog-page.md, TASK.md with feature documentation
- Home intro headings now match blog post typography and spacing
-
Synced home intro content via markdown file (home.md)
- Created content/pages/home.md (slug: home-intro) for homepage intro text
- Home.tsx fetches content from Convex via getPageBySlug query
- Added textAlign frontmatter field for pages (left/center/right, default: left)
- Added featuredTitle to siteConfig.ts for configurable featured section title
- Full markdown support with links, headings, lists, blockquotes, horizontal rules
- External links automatically open in new tab
- Fallback to siteConfig.bio if home-intro page not found (loading/error states)
- Content syncs with npm run sync (no redeploy needed for homepage text changes)
- Updated convex/schema.ts with textAlign field
- Updated convex/pages.ts with textAlign in queries and mutations
- Updated scripts/sync-posts.ts to parse textAlign from frontmatter
- Updated src/styles/global.css with home-intro-content styles
- Updated files.md, changelog.md, TASK.md documentation
-
HTTP-based MCP Server on Netlify
- Created netlify/edge-functions/mcp.ts with JSON-RPC 2.0 implementation
- Added @modelcontextprotocol/sdk dependency to package.json
- Configured Netlify rate limiting (50 req/min public, 1000 req/min authenticated)
- Implemented optional authentication via Authorization header
- Added /mcp edge function route to netlify.toml
- Created blog post "How to Use the MCP Server" with fork setup instructions
- Updated documentation (docs.md, setup-guide.md, files.md, changelog.md, README.md)
- Added MCP configuration to siteConfig.ts
- Seven tools implemented: list_posts, get_post, list_pages, get_page, get_homepage, search_content, export_all
- CORS support for MCP clients
- Manual JSON-RPC implementation (no SDK dependency on Deno runtime)
-
Newsletter CLI improvements
- Updated newsletter:send to call scheduleSendPostNewsletter mutation directly
- Added newsletter:send:stats command for weekly stats summary
- Created scheduleSendStatsSummary mutation in convex/newsletter.ts
- Created send-newsletter-stats.ts script
- Verified all AgentMail features use environment variables (no hardcoded emails)
- Updated documentation (docs.md, files.md, changelog.md, changelog-page.md, TASK.md)
- Created blog post "How to use AgentMail with Markdown Sync"
-
showImageAtTop frontmatter field for posts and pages
- Added showImageAtTop optional boolean field to convex/schema.ts for posts and pages
- Updated scripts/sync-posts.ts to parse showImageAtTop from frontmatter
- Updated convex/posts.ts and convex/pages.ts queries and mutations to include showImageAtTop
- Updated src/pages/Post.tsx to conditionally render image at top when showImageAtTop: true
- Added CSS styles for .post-header-image and .post-header-image-img
- Updated src/pages/Write.tsx to include showImageAtTop in POST_FIELDS and PAGE_FIELDS
- Updated documentation: docs.md, how-to-publish.md, using-images-in-posts.md, files.md
- Image displays full-width above post header with rounded corners
- Default behavior: image only used for OG and featured cards when showImageAtTop not set
-
Blog page featured layout with hero post
blogFeaturedfrontmatter field for posts to mark as featured on blog pageBlogHeroCardcomponent for the hero featured post (first blogFeatured post)- Featured row displays remaining blogFeatured posts in 2-column grid with excerpts
- Regular posts display in 3-column grid without excerpts
getBlogFeaturedPostsquery returns all published posts withblogFeatured: truePostListcomponent updated withcolumnsprop (2 or 3) andshowExcerptsprop- Schema updated with
blogFeaturedfield andby_blogFeaturedindex - sync-posts.ts updated to parse
blogFeaturedfrontmatter - Hero card displays landscape image, tags, date, title, excerpt, author info, and read more link
- Featured row shows excerpts for blogFeatured posts
- Regular posts hide excerpts for cleaner grid layout
- Responsive design: hero stacks on mobile, grids adjust columns at breakpoints
- CSS styles for
.blog-hero-section,.blog-hero-card,.blog-featured-row,.post-cards-2col - Card images use 16:10 landscape aspect ratio matching Giga.ai style
- Footer support on blog page via
siteConfig.footer.showOnBlogPage
-
AI Chat Write Agent (Agent) integration
- AIChatView component created with Anthropic Claude API integration
- Write page AI Agent mode toggle (replaces textarea when active)
- RightSidebar AI chat support via frontmatter aiChat: true field
- Per-session, per-context chat history stored in Convex (aiChats table)
- Page content context support for AI responses
- Markdown rendering for AI responses with copy functionality
- Error handling for missing API keys with user-friendly messages
- System prompt configurable via Convex environment variables
- Anonymous session authentication using localStorage session ID
- Chat history limited to last 20 messages for context efficiency
- Title changes to "Agent" when in AI chat mode on Write page
- Toggle button text changes between "Agent" and "Text Editor"
- SiteConfig.aiChat configuration with enabledOnWritePage and enabledOnContent flags
- Schema updated with aiChats table and aiChat fields on posts/pages tables
- sync-posts.ts updated to handle aiChat frontmatter field
- Documentation updated across all files
-
Fixed AI chat scroll prevention in Write page
- Added viewport height constraints (100vh) to write-layout to prevent page-level scrolling
- Updated write-main with max-height: 100vh and overflow: hidden when AI chat is active
- Added min-height: 0 to flex children (write-ai-chat-container, ai-chat-view, ai-chat-messages) for proper flex behavior
- Input container fixed at bottom with flex-shrink: 0
- Sidebars (left and right) scroll internally with overflow-y: auto
- Delayed focus in AIChatView (100ms setTimeout) to prevent scroll jump on mount
- Added preventScroll: true to all focus() calls in AIChatView
- Toggle button preserves scroll position using requestAnimationFrame
- useEffect scrolls to top when switching to AI chat mode
- Messages area scrolls internally while input stays fixed at bottom (ChatGPT-style behavior)
-
Custom homepage configuration feature
- Added HomepageConfig interface to siteConfig.ts
- Updated App.tsx to conditionally render homepage based on config
- Updated Post.tsx to accept optional props for homepage mode (slug, isHomepage, homepageType)
- Back button hidden when Post component is used as homepage
- Original homepage route accessible at /home when custom homepage is set
- SEO metadata uses page/post frontmatter when used as homepage
- Updated configure-fork.ts to support homepage configuration
- Updated FORK_CONFIG.md with homepage documentation
- Updated fork-config.json.example with homepage option
- All existing features (sidebar, footer, right sidebar) work correctly with custom homepage
-
Image support in footer component with size control
- Footer sanitize schema updated to allow width, height, style, class attributes on images
- Footer image component handler updated to pass through size attributes
- CSS styles added for footer images (.site-footer-image-wrapper, .site-footer-image, .site-footer-image-caption)
- Images support lazy loading and optional captions from alt text
- Security verified: rehypeSanitize sanitizes style attributes to remove dangerous CSS
- Updated files.md, changelog.md with image support documentation
-
Customizable footer component with markdown support
- Footer component created (src/components/Footer.tsx) with ReactMarkdown rendering
- Footer configuration added to siteConfig.ts (FooterConfig interface with defaultContent)
- Footer content can be set in frontmatter footer field (markdown) or siteConfig.defaultContent
- Footer can be enabled/disabled globally and per-page type
- showFooter and footer frontmatter fields added for posts and pages
- Footer renders inside article tag at bottom for posts/pages
- Footer maintains current position on homepage
- Updated Home.tsx to use Footer component with defaultContent
- Updated Post.tsx to render Footer inside article based on showFooter
- Added CSS styles for site-footer (.site-footer, .site-footer-content, .site-footer-text, .site-footer-link)
- Updated schema.ts, posts.ts, pages.ts with showFooter and footer fields
- Updated sync-posts.ts to parse showFooter and footer frontmatter
- Updated Write.tsx to include showFooter and footer in frontmatter reference
- Sidebars flush to bottom when footer is enabled (min-height ensures proper extension)
- Updated files.md, changelog.md with footer feature documentation
-
Fixed right sidebar default behavior: now requires explicit
rightSidebar: truein frontmatter -
Pages/posts without rightSidebar frontmatter render normally with CopyPageDropdown in nav
-
Fixed TypeScript errors: Added rightSidebar to syncPosts and syncPostsPublic args validators
-
Right sidebar feature with CopyPageDropdown support
-
RightSidebar component created
-
Three-column layout CSS (left sidebar, main content, right sidebar)
-
Right sidebar configuration in siteConfig.ts
-
rightSidebar frontmatter field for posts and pages
-
Updated Post.tsx to conditionally render right sidebar
-
Updated schema.ts, posts.ts, pages.ts to handle rightSidebar field
-
Updated sync-posts.ts to parse rightSidebar frontmatter
-
Updated Write.tsx to include rightSidebar option
-
Responsive behavior: right sidebar hidden below 1135px
-
CopyPageDropdown automatically moves from nav to right sidebar when enabled
-
Font family configuration system with siteConfig integration
-
Added FontContext.tsx for global font state management
-
Monospace font option added to FONT SWITCHER (IBM Plex Mono)
-
CSS variable --font-family for dynamic font updates
-
Write page font switcher updated to support serif/sans/monospace
-
Fork configuration support for fontFamily option
-
Documentation updated (setup-guide.md, docs.md)
-
Font preference persistence with localStorage
-
SiteConfig default font detection and override logic
-
Plain text code blocks now wrap text properly instead of horizontal overflow
-
Updated inline vs block code detection logic in BlogPost.tsx
-
Added
pre-wrapstyling for text blocks via SyntaxHighlighter props -
RSS feed validation errors fixed by standardizing URLs to www.markdown.fast
-
Updated index.html meta tags (og:url, og:image, twitter:domain, twitter:url, twitter:image, JSON-LD)
-
Updated convex/rss.ts and convex/http.ts SITE_URL constants
-
Updated public/robots.txt, public/openapi.yaml, and public/llms.txt with www URLs
-
RSS exclusions confirmed in netlify.toml for botMeta edge function
-
Discovery files sync script (sync-discovery-files.ts)
-
Automated updates for AGENTS.md and llms.txt with current app data
-
New npm scripts: sync:discovery, sync:discovery:prod, sync:all, sync:all:prod
-
Fork configuration updated to support gitHubRepo config
-
Backward compatibility for legacy githubUsername/githubRepo fields
-
Documentation updated across all files with new sync commands
-
Homepage post limit configuration (homePostsLimit in siteConfig.postsDisplay)
-
Optional "read more" link below limited post list (homePostsReadMore config)
-
Customizable link text and destination URL
-
CSS styling for read more link with hover effects
-
Conditional rendering logic to show link only when posts are limited
-
Tag pages at
/tags/[tag]route with view mode toggle -
Related posts component for blog post footers (up to 3 related posts by shared tags)
-
Tag links in post footers now navigate to tag archive pages
-
Open in AI links (ChatGPT, Claude, Perplexity) re-enabled using GitHub raw URLs
-
gitHubRepoconfiguration in siteConfig.ts for AI service URL construction -
by_tagsindex added to posts table in convex/schema.ts -
New Convex queries:
getAllTags,getPostsByTag,getRelatedPosts -
Sitemap updated to include dynamically generated tag pages
-
Documentation updated with git push requirement for AI links
-
Mobile responsive styling for tag pages and related posts
-
Fixed sidebar border width consistency using box-shadow instead of border-right
-
Hidden sidebar scrollbar while maintaining scroll functionality
-
Added top border and border-radius to sidebar wrapper using CSS variables
-
Updated CSS documentation for sidebar border implementation
-
Fixed mobile menu breakpoint to match sidebar hide breakpoint (1024px)
-
Mobile hamburger menu now shows whenever sidebar is hidden
-
add MIT Licensed. Do whatevs.
-
Blog page view mode toggle (list and card views)
-
Post cards component with thumbnails, titles, excerpts, and metadata
-
View preference saved to localStorage
-
Default view mode configurable in siteConfig.blogPage.viewMode
-
Toggle visibility controlled by siteConfig.blogPage.showViewToggle
-
Responsive grid: 3 columns (desktop), 2 columns (tablet), 1 column (mobile)
-
Theme-aware styling for all four themes
-
Raw markdown files now accessible to AI crawlers (ChatGPT, Perplexity)
-
Added /raw/ path bypass in botMeta edge function
-
Sitemap now includes static pages (about, docs, contact, etc.)
-
Security headers added to netlify.toml
-
Link header pointing to llms.txt for AI discovery
-
Preconnect hints for Convex backend
-
Fixed URL consistency in openapi.yaml and robots.txt
-
Write conflict prevention: increased dedup windows, added heartbeat jitter
-
Visitor map styling: removed box-shadow, increased land dot contrast and opacity
-
Real-time visitor map on stats page showing live visitor locations
-
Netlify edge function for geo detection (geo.ts)
-
VisitorMap component with dotted world map and pulsing dots
-
Theme-aware colors for all four themes (dark, light, tan, cloud)
-
visitorMap config option in siteConfig.ts to enable/disable
-
Privacy friendly: no IP addresses stored, only city/country/coordinates
-
Documentation updated: setup-guide, docs, FORK_CONFIG, fork-config.json.example
-
Author display for posts and pages with authorName and authorImage frontmatter fields
-
Round avatar image displayed next to date and read time on post/page views
-
Write page updated with new frontmatter field reference
-
Documentation updated: setup-guide.md, docs.md, files.md, README.md, AGENTS.md
-
PRD created: prds/howto-Frontmatter.md with reusable prompt for future updates
-
GitHub Stars card on Stats page with live count from repository
-
CopyPageDropdown AI services now use raw markdown URLs for better AI parsing
-
ChatGPT, Claude, and Perplexity receive /raw/{slug}.md URLs instead of page URLs
-
Automated fork configuration with npm run configure
-
FORK_CONFIG.md comprehensive guide with two options (automated + manual)
-
fork-config.json.example template with all configuration options
-
scripts/configure-fork.ts for automated updates
-
Updates all 11 configuration files in one command
-
GitHub contributions graph on homepage with theme-aware colors
-
Year navigation with Phosphor icons (CaretLeft, CaretRight)
-
Click graph to visit GitHub profile
-
Configurable via siteConfig.gitHubContributions
-
Theme-specific contribution colors for all 4 themes
-
Mobile responsive design with scaled cells
-
Public /write page with three-column layout (not linked in nav)
-
Left sidebar: Home link, content type selector, actions (Clear, Theme, Font)
-
Center: Writing area with Copy All button and borderless textarea
-
Right sidebar: Frontmatter reference with per-field copy buttons
-
Font switcher to toggle between Serif and Sans-serif fonts
-
Font preference persistence in localStorage
-
Theme toggle icons matching ThemeToggle.tsx (Moon, Sun, Half2Icon, Cloud)
-
Content type switching (Blog Post/Page) updates writing area template
-
Word, line, and character counts in status bar
-
Warning banner about refresh losing content
-
localStorage persistence for content, type, and font
-
Redesign /write page with three-column Cursor docs-style layout
-
Add per-field copy icons to frontmatter reference panel
-
Add refresh warning message in left sidebar
-
Left sidebar with home link, content type selector, and actions
-
Right sidebar with frontmatter fields and copy buttons
-
Center area with title, Copy All button, and borderless textarea
-
Theme toggle with matching icons for all four themes
-
Redesign /write page with wider layout and modern Notion-like UI
-
Remove header from /write page (standalone writing experience)
-
Add inline theme toggle and home link to Write page toolbar
-
Collapsible frontmatter fields panel
-
Add markdown write page with copy option at /write
-
Centralized font-size CSS variables in global.css
-
Base size scale with semantic naming (3xs to hero)
-
Component-specific font-size variables
-
Mobile responsive font-size overrides
-
Open Graph image fix for posts and pages with frontmatter images
-
Dedicated blog page with configurable display options
-
Blog page navigation order via siteConfig.blogPage.order
-
Centralized siteConfig.ts for site configuration
-
Posts display toggle for homepage and/or blog page
-
move home to the top of the mobile menu
-
Fork configuration documentation in docs.md and setup-guide.md
-
"Files to Update When Forking" section with all 9 configuration files
-
Backend configuration examples for Convex files
-
Site branding updates across all AI discovery files
-
Fork documentation added to README.md
-
Blog post updated with v1.9.0 and v1.10.0 features
-
Scroll-to-top button with configurable threshold
-
Scroll-to-top documentation in docs.md and setup-guide.md
-
Mobile menu with hamburger navigation for mobile and tablet
-
Generate Skill feature in CopyPageDropdown
-
Project setup with Vite + React + TypeScript
-
Convex schema for posts, viewCounts, siteConfig, pages
-
Build-time markdown sync script
-
Theme system (dark/light/tan/cloud)
-
Default theme configuration (tan)
-
Home page with year-grouped post list
-
Post page with markdown rendering
-
Static pages support (About, Projects, Contact)
-
Syntax highlighting for code blocks
-
Open Graph and Twitter Card meta tags
-
Netlify edge function for bot detection
-
RSS feed support (standard and full content)
-
API endpoints for LLMs (/api/posts, /api/post)
-
Copy Page dropdown for AI tools
-
Sample blog posts and pages
-
Security audit completed
-
TypeScript type-safety verification
-
Netlify build configuration verified
-
SPA 404 fallback configured
-
Mobile responsive design
-
Edge functions for dynamic Convex HTTP proxying
-
Vite dev server proxy for local development
-
Real-time stats page at /stats
-
Page view tracking with event records pattern
-
Active session heartbeat system
-
Cron job for stale session cleanup
-
Stats link in homepage footer
-
Real-time search with Command+K shortcut
-
Search modal with keyboard navigation
-
Full text search indexes for posts and pages
-
Featured section with list/card view toggle
-
Logo gallery with continuous marquee scroll
-
Frontmatter-controlled featured items (featured, featuredOrder)
-
Featured items sync with npm run sync (no redeploy needed)
-
Firecrawl content importer (npm run import)
-
/api/export endpoint for batch content fetching
-
AI plugin discovery at /.well-known/ai-plugin.json
-
OpenAPI 3.0 spec at /openapi.yaml
-
AGENTS.md for AI coding agents
-
Static raw markdown files at /raw/{slug}.md
-
View as Markdown option in CopyPageDropdown
-
Perplexity added to AI service options
-
Featured image support with square thumbnails in card view
-
Improved markdown table CSS styling
-
Aggregate component integration for efficient stats counting (O(log n) vs O(n))
-
Three aggregate components: pageViewsByPath, totalPageViews, uniqueVisitors
-
Chunked backfilling mutation for existing page view data
-
Aggregate component registration in convex.config.ts
-
Stats query updated to use aggregate counts
-
Aggregate component documentation in prds/howstatsworks.md
-
Sidebar navigation anchor links fixed for collapsed/expanded sections
-
Navigation scroll calculation with proper header offset (80px)
-
Expand ancestors before scrolling to ensure target visibility
-
Removed auto-expand from scroll handler to preserve manual collapse state
-
Collapse button event handling improved to prevent link navigation
-
Heading extraction updated to filter out code blocks
-
Sidebar no longer shows example headings from markdown code examples
-
Mobile menu redesigned with left-aligned navigation controls
-
Hamburger menu order changed (hamburger, search, theme toggle)
-
Sidebar table of contents integrated into mobile menu
-
Desktop sidebar hidden on mobile when sidebar layout is enabled
-
SidebarContext created to share sidebar data between components
-
Mobile menu typography standardized with CSS variables
-
Font-family standardized using inherit for consistency
-
showInNavfield for pages to control navigation visibility -
Pages can be published but hidden from navigation menu
-
Defaults to
truefor backwards compatibility -
Pages with
showInNav: falseremain accessible via direct URL, searchable, and available via API -
Hardcoded navigation items configuration in siteConfig.ts
-
Add React route pages (like /stats, /write) to navigation via hardcodedNavItems
-
Configure navigation order, title, and visibility per route
-
Navigation combines Blog link, hardcoded nav items, and markdown pages
-
All nav items sorted by order field (lower = first)
Deployment Steps
- Run
npx convex devto initialize Convex - Set
CONVEX_DEPLOY_KEYin Netlify environment variables - Connect repo to Netlify and deploy
- Edge functions automatically handle RSS, sitemap, and API routes
Someday Features TBD
- Newsletter signup
- Comments system
- Draft preview mode