Skip to content

Latest commit

 

History

History
1260 lines (1124 loc) · 85 KB

File metadata and controls

1260 lines (1124 loc) · 85 KB

Markdown Blog - Tasks

To Do

Current Status

Session updates complete on 2026-03-20.

  • convex-doctor blog post and cleanup (2026-03-20)

    • Created featured blog post: "How convex-doctor took markdown.fast from 42 to 100"
    • Generated before/after comparison image, added benchmark and 100/100 score screenshots
    • Post covers what convex-doctor is, the 17 pass journey, AI models used (Claude Opus 4.6, GPT Codex 5.3), and recommendation
    • Reverted .unique() to .first() in authAdmin.ts and dashboardAuth.ts (runtime errors with duplicate rows)
    • Cleaned up duplicate PRD files from prds/ root (kept remaining passes in prds/convex-doctor/)
    • Added convex-doctor skill and always-on cursor rule
    • Synced to Convex
  • Convex doctor seventeenth pass (2026-03-20 21:30 UTC)

    • Added by_storageid index on aiImageGenerationJobs for _storage FK lookup
    • Extracted sendContactEmail helpers (buildContactHtml, buildContactText) in contactActions.ts
    • Extracted stats.ts helpers: updatePageViewAggregates, buildPageStats, collectVisitorLocations, getTopPathStats
    • Added 7 rule suppressions to convex-doctor.toml for by-design patterns (auth awareness, schema nesting, optional fields, ordered .first(), domain-organized files, multi-step handlers)
    • convex-doctor improved from 92/100 with 0 errors / 39 warnings to 100/100 with 0 errors / 0 warnings / 18 infos
  • Convex doctor sixteenth pass (2026-03-20 20:15 UTC)

    • Batched fetchPostsByIds and fetchPagesByIds into one fetchSearchDocsByIds internal query, merged completeSemanticSearchJob and failSemanticSearchJob into one finalizeSemanticSearchJob mutation, and extracted a finalize helper so semanticSearchJob uses fewer ctx.run* call sites (7 to 4 in the handler)
    • Converted authComponent.ts from registered internalQuery functions to plain async helpers (authUserGetByIdHelper, authUserListHelper) so callers in dashboardAuth.ts and authAdmin.ts avoid the double runQuery hop that triggered perf/helper-vs-run
    • Also updated askAI.node.ts to use the batched fetchSearchDocsByIds query
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 91/100 with 0 errors / 43 warnings to 92/100 with 0 errors / 39 warnings
  • Convex doctor fifteenth pass (2026-03-20 09:10 UTC)

    • Batched sendPostNewsletter prefetch into getPostNewsletterSendContextInternal so the action uses one internal query plus the final recordPostSent mutation
    • Routed auth bootstrap and admin email resolution through internal.authComponent.* forwarders and added convex-doctor.toml so component forwarders and generated output do not dominate the score
    • Tightened viewCounts slug reads to .unique() where the app assumes one document per slug
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor reached 91/100 with 0 errors and 43 warnings; remaining .first() hits are intentional (ordered picks and keys that are not unique by design)
  • Convex doctor fourteenth pass (2026-03-20 08:51 UTC)

    • Collapsed queued URL import success handling so imported post creation and job completion now happen in one internal mutation, with helper-routed failure finalization
    • Extracted shared markdown frontmatter builders for post and page export queries so the export handlers stay thin without changing the file format
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 85/100 with 1 error / 54 warnings to 86/100 with 1 error / 49 warnings
    • The highest-signal remaining issues are now sendPostNewsletter chaining, the auth component direct-function-ref, and the reduced .first() list
  • Convex doctor thirteenth pass (2026-03-20 08:33 UTC)

    • Refactored AI chat response generation to run from a queued snapshot, finalize through one mutation, and stop duplicating the newest user message in provider prompts
    • Refactored queued image generation to run from the scheduled job snapshot and finalize image metadata plus job state through one patch-based internal finalizer
    • Extracted both AI action handlers into helper functions, which reduced inline orchestration and removed the remaining replace warning in the image job flow
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 84/100 with 1 error / 60 warnings to 85/100 with 1 error / 54 warnings, which moved the repo into the Healthy band
    • The highest-signal remaining issues are now importFromUrlJob chaining, the auth component direct-function-ref, and the reduced .first() list
  • Convex doctor twelfth pass (2026-03-20 08:18 UTC)

    • Moved semantic search off the browser action path by replacing the public action with a queued semanticSearchJobs flow and reactive SearchModal job polling
    • Added follow-up auth-awareness signals to recordPageView, heartbeat, and versions.isEnabled, and converted the new semantic search request error to ConvexError
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 81/100 with 1 error / 64 warnings to 84/100 with 1 error / 60 warnings
    • The remaining top findings are now mostly structural: the direct auth component reference, generateResponse run-call chaining, and the reduced .first() list
  • Convex doctor eleventh pass (2026-03-20 08:15 UTC)

    • Replaced browser resolveDirectUpload calls in both media upload UIs with the existing getDirectStorageUrl query and made resolveDirectUpload internal-only
    • Added non-breaking auth-awareness to search and converted newsletter sent-post slug lookups to .unique()
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 80/100 with 1 error / 68 warnings to 81/100 with 1 error / 64 warnings
    • The next concrete browser-action follow-up after this pass was semantic search
  • Convex doctor tenth pass (2026-03-20 08:24 UTC)

    • Replaced the direct Dashboard importFromUrl browser action with a queued importUrlJobs flow using convex/importJobs.ts, an internal importFromUrlJob, and reactive Dashboard job state
    • Tightened the remaining safe versionControlSettings.by_key lookup in versions.getStats from .first() to .unique()
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • The targeted importFromUrl public action warning was removed, while convex-doctor settled at 80/100 with 1 error / 68 warnings
    • The next obvious browser-action follow-up is resolveDirectUpload
  • Convex doctor ninth pass (2026-03-20 08:16 UTC)

    • Moved files.setFileExpiration from a public action to an internal action, removing the last browser-callable file-maintenance action path
    • Added non-breaking auth-awareness to posts.incrementViewCount, which cleared that warning without changing intended public behavior
    • Tightened clearly unique-by-design indexed lookups from .first() to .unique() across version settings, CMS slug checks, newsletter subscriber email, dashboard admin identity checks, and embedding post-by-slug lookup
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor held at 81/100 while findings improved from 1 error / 84 warnings to 1 error / 68 warnings
    • The next obvious follow-ups are importFromUrl, the remaining direct auth component reference, the reduced set of .first() warnings, and structural ctx.runQuery chain warnings
  • Convex doctor eighth pass (2026-03-20 08:10 UTC)

    • Moved files.getDownloadUrl from a public action to an internal action, which removed the direct browser action path without changing any current app flow
    • Refactored convex/rss.ts to export plain helper functions and wrapped them in convex/http.ts, clearing the old RSS handler syntax warning
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 78/100 with 1 error / 89 warnings to 81/100 with 1 error / 84 warnings
    • The next obvious follow-up is files.setFileExpiration, which is now the remaining public action warning in that area
  • Convex doctor seventh pass (2026-03-20 08:01 UTC)

    • Batched version snapshots in syncPostsPublic and syncPagesPublic through versions.createVersionsBatch, which removed per-item scheduler usage while preserving pre-update snapshot content
    • Converted files.commitFile from a public action to a public mutation and updated both upload UIs to use useMutation
    • Added explicit high bounds to the remaining safe .collect() paths touched in convex/posts.ts, convex/pages.ts, convex/newsletter.ts, and convex/authAdmin.ts
    • Added explicit return validators across convex/files.ts list, info, download, delete, expiration, and count functions
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 67/100 with 17 errors / 98 warnings to 78/100 with 1 error / 89 warnings
  • Convex doctor sixth pass (2026-03-20 08:36 UTC)

    • Added auth-awareness to syncPagesPublic and syncPostsPublic so the sync mutations keep their current behavior while reducing false-positive security warnings
    • Moved embedding refresh entrypoints to convex/embeddingsAdmin.ts so the sync script now queues internal embedding work instead of calling a public action directly
    • Refactored Ask AI stream handlers into plain helpers wrapped in convex/http.ts, which cleared the streamResponse old-syntax warning
    • Added a return validator to askAI.getStreamBody that matches the streaming component contract without guessing the shape
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 66/100 with 17 errors / 110 warnings to 67/100 with 17 errors / 98 warnings
    • Remaining high-value follow-ups are the sync version-snapshot scheduler loop, commitFile, remaining unbounded collects, and the auth component direct-function-ref warning
  • Convex doctor fifth pass (2026-03-20 08:16 UTC)

    • Moved Dashboard image generation off the direct public action path into a persisted job flow using aiImageGenerationJobs
    • Added convex/aiImageJobs.ts with request, status, and internal completion/failure handlers for reactive image generation state
    • Updated src/pages/Dashboard.tsx to request image jobs and render success and failure state from the job record
    • Added explicit query bounds across remaining public content, newsletter, and stats reads touched in this pass
    • Final verification completed: npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor returned to 66/100 while findings dropped from 28 errors / 130 warnings to 17 errors / 110 warnings
    • Remaining meaningful follow-ups are syncPagesPublic, generateMissingEmbeddings, the components.auth.public.userList direct-function-ref warning, and the legacy streamResponse syntax warning
  • Convex doctor fourth pass (2026-03-20 06:46 UTC)

    • Refactored convex/aiChatActions.ts so generateResponse is helper-driven and smaller without changing chat behavior
    • Removed the extra storage URL query hop by resolving storage URLs directly in the action
    • Added auth-awareness to regeneratePostEmbedding, isConfigured, subscribe, unsubscribe, and related public utility flows
    • Final verification completed: npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor stayed at 68/100 while warnings dropped from 136 to 130
    • generateResponse dropped from 209 lines to 69 lines and its Convex call chain dropped from 5 to 4
  • Convex doctor third pass (2026-03-19 07:26 UTC)

    • Query cleanup completed across convex/posts.ts, convex/pages.ts, and convex/stats.ts
    • Replaced the remaining safe collect then filter pipelines with explicit iteration without changing return shapes
    • Added auth-awareness to bootstrap and public contact/setup flows where public access is intentional
    • Converted safe unique-by-design lookups to .unique() for slugs, stream IDs, session/context pairs, storage IDs, and dashboard admin subject/email lookups
    • Final verification completed: npx tsc --noEmit, npm run build, and npx convex-doctor@latest
    • convex-doctor improved from 66/100 to 68/100
  • Convex doctor second pass (2026-03-18)

    • Deep-dive follow-up completed with verified score improvement from 42 to 66
    • AI chat now queues responses through a mutation-scheduled internal action flow
    • Ask AI sessions and AI chat sessions now record authenticated ownership
    • Added auth checks to public AI chat/image flows without breaking current UX
    • Added CORS preflight support for /raw/, /rss.xml, /rss-full.xml, /sitemap.xml, /api/posts, /api/post, /api/export, and /meta/post
    • Replaced new Date(...) sorting in post queries with deterministic ISO string comparison
    • Final verification completed: npx tsc --noEmit, npm run build, and npx convex-doctor@latest
  • Convex doctor remediation (2026-03-18)

    • Phase 1: Auth hardening and internal API misuse fixes
    • Phase 2: Deterministic queries (removed Date.now from getStats and getStatsForSummary)
    • Phase 3: Performance (N+1 elimination, batch storage URL resolution, bounded embedding queries)
    • Phase 4: Schema alignment (index naming, redundant index removal)
    • Phase 5: Architecture (ConvexError, console.log cleanup)

Session updates complete on 2026-03-01.

  • Rybbit analytics integration (2026-03-01)
    • Added Rybbit analytics script to index.html
    • Script loads with defer attribute for non-blocking page load

Session updates complete on 2026-02-27.

  • WSL 2 Convex setup docs hardening (2026-02-27)

    • Verified GitHub issue #7 (WSL 2 Convex setup failure) remains relevant for manual setup docs
    • Added WSL 2 fallback login flow to docs: npx convex login --no-open --login-flow paste
    • Added first-run initialization fallback: npx convex dev --once
  • TypeScript error fixes (2026-02-27)

    • Removed unused variables pathsWithCounts and allPathsFromAggregate in convex/stats.ts
    • Fixed fetchpriority to fetchPriority (React camelCase) in Layout.tsx, Home.tsx, and Post.tsx (6 instances total)
    • npx tsc --noEmit now passes with zero errors

Session updates complete on 2026-02-22.

  • Button border radius consistency fix (2026-02-22)

    • Added missing CSS variables (--border-radius-sm, --border-radius-md, --border-radius-lg) to :root
    • Fixed inconsistent button styling across Write page and Dashboard
    • Mode toggles and action buttons now all have matching 6px border radius
  • Media Library and router fixes (2026-02-22)

    • Fixed Media Library to show image preview and embed code (MD/HTML/URL) after uploading with convex/r2 providers
    • Recent uploads persist to sessionStorage across page refreshes
    • Fixed image clipping in media grid (4:3 contain instead of 1:1 cover)
    • Fixed ImageUploadModal Media Library tab gating (no longer requires Bunny CDN)
    • Dynamic usage text based on active media provider
    • Added React Router v7 future flags to eliminate deprecation warnings
    • Removed unused logo preload from index.html
  • Heartbeat write conflict elimination (2026-02-22)

    • Increased backend dedup window from 20s to 45s (HEARTBEAT_DEDUP_MS in convex/stats.ts)
    • Increased frontend debounce from 20s to 45s and interval from 30s to 45s (usePageTracking.ts)
    • Added BroadcastChannel cross-tab coordination (only leader tab sends heartbeats)
    • Tab leadership election with automatic handoff when tabs close
    • Heartbeat completely disabled when statsPage.enabled: false in siteConfig

Session updates complete on 2026-02-21.

  • Stats performance optimizations (2026-02-21)
    • Stats tracking now respects statsPage.enabled config (no DB writes when disabled)
    • Removed expensive full table scan fallback in getStats query
    • Added uniquePaths aggregate component for O(log n) path tracking
    • Paginated pageStats to return top 50 pages by views
    • Updated Stats page UI to show "Top Pages by Views" with count indicator

Session updates complete on 2026-02-16.

  • @robelest/convex-auth integration fully working (2026-02-16)

    • Auth client properly initialized in ConvexAuthWrapper component
    • Email lookup from auth component fixes admin verification (JWT only has subject, not email)
    • GitHub OAuth flow tested and working with wayne@convex.dev
    • Dashboard accessible to admins, non-admins redirected with notice
    • Sign out working correctly in convex-auth mode
    • Documentation created: prds/adding-robel-auth.md with full migration guide
    • Fork setup instructions updated in FORK_CONFIG.md
  • Auth + hosting migration implementation completed on 2026-02-16.

  • Default architecture now targets Convex Auth + Convex self-hosting with legacy compatibility retained for WorkOS + Netlify.

  • Server-side dashboard admin authorization is enforced and upload endpoints are locked down.

  • TypeScript checks and Convex codegen both pass after migration updates.

  • Mode wording is now aligned across README.md, FORK_CONFIG.md, and fork-config.json.example.

  • Full migration validation pass completed: lint, typecheck, Convex codegen, and production build all pass.

  • Dashboard auth/access hardening follow-up completed:

    • Fixed convex-auth sign out in Dashboard.
    • Fixed false "dashboard access open" warning in authenticated convex-auth mode.
    • Added strict primary admin email gate support for dashboard access.
    • Fixed Version Control dashboard crash caused by versions:getStats full-table read.
  • Dashboard rich text editor migrated off Quill to a lightweight built-in editor.

  • Lint and typecheck both pass.

  • Production dependency audit is clean (npm audit --omit=dev -> 0 vulnerabilities).

  • Ask AI modal and docs navigation smoke-tested locally.

Completed

  • Convex doctor sixteenth pass (2026-03-20 20:15 UTC)

    • Created PRD at prds/convex-doctor-sixteenth-pass.md
    • Merged fetchPostsByIds + fetchPagesByIds into fetchSearchDocsByIds and completeSemanticSearchJob + failSemanticSearchJob into finalizeSemanticSearchJob
    • Extracted finalize helper in semanticSearch.ts to centralize mutation calls (7 ctx.run* call sites to 4)
    • Updated askAI.node.ts to use batched fetchSearchDocsByIds
    • Converted authComponent.ts from registered internalQuery to plain async helpers; updated authAdmin.ts and dashboardAuth.ts to import directly
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest at 92/100, 0 errors, 39 warnings
  • Convex doctor seventeenth pass (2026-03-20 21:30 UTC)

    • Created PRD at prds/convex-doctor-seventeenth-pass.md
    • Added by_storageid index on aiImageGenerationJobs for _storage FK
    • Extracted sendContactEmail helpers (buildContactHtml, buildContactText) in contactActions.ts
    • Extracted stats.ts helpers: updatePageViewAggregates, buildPageStats, collectVisitorLocations, getTopPathStats
    • Added 7 rule suppressions to convex-doctor.toml for by-design patterns
    • Verified npx convex codegen, npm run build, and npx convex-doctor at 100/100, 0 errors, 0 warnings, 18 infos
  • Convex doctor fifteenth pass (2026-03-20 09:10 UTC)

    • Created follow-up PRD at prds/convex-doctor-fifteenth-pass.md
    • Added getPostNewsletterSendContextInternal and reduced sendPostNewsletter to one batched internal query plus recordPostSent
    • Added convex/authComponent.ts forwarders; updated authAdmin and dashboardAuth to call internal.authComponent.*
    • Switched viewCounts slug queries in convex/posts.ts to .unique()
    • Added root convex-doctor.toml (ignore forwarder and _generated, disable correctness/generated-code-modified)
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest at 91/100, 0 errors, 43 warnings
  • Convex doctor fourteenth pass (2026-03-20 08:51 UTC)

    • Created follow-up PRD at prds/convex-doctor-fourteenth-pass.md
    • Collapsed queued URL import completion into one internal mutation in convex/importJobs.ts and reduced inline action orchestration in convex/importAction.ts
    • Extracted shared frontmatter helpers in convex/cms.ts for markdown export queries
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings improved to 1 error / 49 warnings
  • Convex doctor thirteenth pass (2026-03-20 08:33 UTC)

    • Created follow-up PRD at prds/convex-doctor-thirteenth-pass.md
    • Reduced AI chat generateResponse run-call chaining by scheduling the chat snapshot and finalizing through one internal mutation
    • Reduced queued image-generation job churn by scheduling the job snapshot and finalizing status plus generated-image metadata through one internal mutation
    • Extracted AI action orchestration into helper functions and removed the remaining replace usage in the image job flow
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings improved to 1 error / 54 warnings
  • Convex doctor twelfth pass (2026-03-20 08:18 UTC)

    • Created follow-up PRD at prds/convex-doctor-twelfth-pass.md
    • Moved semantic search to a queued mutation-plus-job flow with persisted job status in convex/semanticSearchJobs.ts
    • Updated src/components/SearchModal.tsx to debounce job requests and render results from the current job record
    • Added auth-awareness follow-ups in convex/stats.ts and convex/versions.ts
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings improved to 1 error / 60 warnings
  • Convex doctor eleventh pass (2026-03-20 08:15 UTC)

    • Created follow-up PRD at prds/convex-doctor-eleventh-pass.md
    • Replaced browser resolveDirectUpload usage with the existing getDirectStorageUrl query
    • Made resolveDirectUpload internal-only and tightened newsletter sent-post lookups to .unique()
    • Added non-breaking auth-awareness to convex/search.ts
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings reduced to 1 error / 64 warnings
  • Convex doctor tenth pass (2026-03-20 08:24 UTC)

    • Created follow-up PRD at prds/convex-doctor-tenth-pass.md
    • Moved Dashboard URL import to a queued mutation-plus-job flow with persisted import status
    • Tightened the remaining safe config-key .first() lookup in versions.getStats
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest after removing the importFromUrl public action warning
  • Convex doctor ninth pass (2026-03-20 08:16 UTC)

    • Created follow-up PRD at prds/convex-doctor-ninth-pass.md
    • Moved files.setFileExpiration off the public action path by making it internal-only
    • Added auth-awareness to posts.incrementViewCount
    • Converted clearly unique-by-design indexed .first() lookups to .unique()
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings reduced to 1 error / 68 warnings
  • Convex doctor eighth pass (2026-03-20 08:10 UTC)

    • Created follow-up PRD at prds/convex-doctor-eighth-pass.md
    • Moved files.getDownloadUrl off the public action path by making it internal-only
    • Refactored RSS handlers to helper-wrapped routes in convex/rss.ts and convex/http.ts
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings reduced to 1 error / 84 warnings
  • Convex doctor seventh pass (2026-03-20 08:01 UTC)

    • Created follow-up PRD at prds/convex-doctor-seventh-pass.md
    • Batched sync version scheduling through versions.createVersionsBatch
    • Moved files.commitFile off the public action path and updated upload UIs to use a mutation
    • Added explicit high bounds to the remaining safe collect-based reads touched in this pass
    • Added explicit return validators across convex/files.ts
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings reduced to 1 error / 89 warnings
  • Convex doctor sixth pass (2026-03-20 08:36 UTC)

    • Created follow-up PRD at prds/convex-doctor-sixth-pass.md
    • Added sync auth-awareness and moved embedding refresh entrypoints to queued mutations in convex/embeddingsAdmin.ts
    • Refactored Ask AI HTTP stream handlers into helper functions wrapped in convex/http.ts
    • Added return validation for askAI.getStreamBody
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with warnings reduced to 98
  • Convex doctor fifth pass (2026-03-20 08:16 UTC)

    • Created follow-up PRD at prds/convex-doctor-fifth-pass.md
    • Added persisted image generation jobs in convex/schema.ts and convex/aiImageJobs.ts
    • Converted Dashboard image generation to a mutation-scheduled internal action flow
    • Added explicit bounds to remaining public list-style reads touched in convex/posts.ts, convex/pages.ts, convex/newsletter.ts, convex/stats.ts, and convex/authAdmin.ts
    • Verified npx convex codegen, npx tsc --noEmit, npm run build, and npx convex-doctor@latest with findings reduced to 17 errors / 110 warnings
  • Convex doctor fourth pass (2026-03-20 06:46 UTC)

    • Created follow-up PRD at prds/convex-doctor-fourth-pass.md
    • Refactored convex/aiChatActions.ts into helper-driven orchestration and removed the extra storage URL query hop
    • Removed unused getStorageUrlsBatch internal query from convex/aiChats.ts
    • Added auth-awareness to regeneratePostEmbedding, isConfigured, subscribe, and unsubscribe
    • Verified npx tsc --noEmit, npm run build, and npx convex-doctor@latest with warnings reduced to 130
  • Convex doctor third pass (2026-03-19 07:26 UTC)

    • Created follow-up PRD at prds/convex-doctor-third-pass.md
    • Removed safe collect then filter pipelines in convex/posts.ts, convex/pages.ts, and convex/stats.ts
    • Added safe auth-awareness checks in convex/authAdmin.ts, convex/contact.ts, and other public setup helpers
    • Converted safe unique-by-design lookups to .unique() in posts, pages, askAI, aiChats, stats, and authAdmin
    • Verified npx tsc --noEmit, npm run build, and npx convex-doctor@latest with final score 68/100
  • Convex doctor second pass (2026-03-18)

    • Created follow-up PRD at prds/convex-doctor-second-pass.md
    • Moved browser AI chat off the direct public action path and onto aiChats.requestAIResponse
    • Converted aiChatActions.generateResponse to an internal action scheduled from a public mutation
    • Added authenticated ownership tracking for aiChats, askAISessions, and generated AI images
    • Hardened public AI chat queries and mutations with auth checks and ownership enforcement
    • Added queued generation state and error state handling to AI chat UI and backend
    • Added CORS OPTIONS handlers for public HTTP endpoints flagged by convex-doctor
    • Converted post query date sorting to deterministic ISO string comparisons
    • Verified npx tsc --noEmit, npm run build, and npx convex-doctor@latest with final score 66/100
  • Convex doctor remediation (2026-03-18)

    • Phase 1: Added auth to streamResponse HTTP action and generateResponse public action
    • Created isCurrentUserDashboardAdminInternal internal query in convex/authAdmin.ts
    • Replaced all api.* with internal.* in server-to-server calls (http.ts, rss.ts, dashboardAuth.ts, importAction.ts)
    • Created internal query equivalents: getAllPostsInternal, getPostBySlugWithContent, getAllTagsInternal, getAllAuthorsInternal, getAllPostsWithContentInternal, getAllPagesInternal, getPageBySlugInternal
    • Created createPostInternal internal mutation in cms.ts
    • Phase 2: Removed Date.now() from stats.getStats query (now accepts now arg)
    • Removed Date.now() from newsletter.getStatsForSummary (now accepts now arg)
    • Updated Stats.tsx and Dashboard.tsx StatsSection with 60-second tick interval
    • Updated newsletterActions.ts to pass now: Date.now() to getStatsForSummary
    • Phase 3: Replaced collect-then-filter in embeddingsQueries.ts with async iteration
    • Created getAllPostsWithContentInternal batch query to eliminate N+1 in export and RSS
    • Created getStorageUrlsBatch internal query to batch-resolve image URLs in AI chat
    • Refactored generateResponse to batch-resolve all storage URLs in one query
    • Phase 4: Renamed by_docsSection to by_docs_section in schema and all callers
    • Removed redundant by_session index from aiChats table (prefix of by_session_and_context)
    • Updated clearAllChats to use by_session_and_context index prefix
    • Phase 5: Replaced throw new Error(...) with ConvexError in dashboardAuth.ts and authAdmin.ts
    • Added ConvexError to aiChatActions.ts auth check
    • Removed debug console.log calls from dashboardAuth.ts
    • Created PRD: prds/convex-doctor-remediation.md
  • Rybbit analytics integration (2026-03-01)

    • Added Rybbit analytics script to index.html with site ID 24731ca420a4
    • Script loads with defer for non-blocking page rendering
  • WSL 2 Convex setup docs hardening (2026-02-27)

    • Added WSL 2 fallback login flow in content/blog/setup-guide.md using npx convex login --no-open --login-flow paste
    • Added README fallback setup commands using npx convex dev --once for first-time initialization
  • TypeScript error fixes (2026-02-27)

    • Removed unused pathsWithCounts and allPathsFromAggregate variables in convex/stats.ts
    • Fixed fetchpriority to fetchPriority in src/components/Layout.tsx
    • Fixed fetchpriority to fetchPriority in src/pages/Home.tsx
    • Fixed fetchpriority to fetchPriority in src/pages/Post.tsx (4 instances)
    • Verified npx tsc --noEmit passes with zero errors
  • Media Library and router fixes (2026-02-22)

    • Added RecentUpload tracking with preview and MD/HTML/URL copy buttons for convex/r2 providers
    • Persisted recent uploads to sessionStorage for refresh survival
    • Fixed image preview clipping (aspect-ratio 4:3 + object-fit contain)
    • Removed Bunny CDN gate from ImageUploadModal Media Library tab
    • Made usage text dynamic based on active media provider
    • Added React Router v7 future flags (v7_startTransition, v7_relativeSplatPath)
    • Removed unused logo preload from index.html
  • Heartbeat write conflict elimination (2026-02-22)

    • Increased HEARTBEAT_DEDUP_MS from 20s to 45s in convex/stats.ts
    • Increased HEARTBEAT_INTERVAL_MS from 30s to 45s in usePageTracking.ts
    • Increased HEARTBEAT_DEBOUNCE_MS from 20s to 45s in usePageTracking.ts
    • Added BroadcastChannel for cross-tab coordination (only leader tab sends heartbeats)
    • Added tab leadership election with claim/close/heartbeat_sent messages
    • Added isStatsEnabled check to sendHeartbeat callback for complete disabling
    • Created PRD documentation: prds/fix-heartbeat-write-conflicts.md
  • Stats performance optimizations (2026-02-21)

    • Added statsPage.enabled check in usePageTracking.ts to prevent DB writes when stats disabled
    • Removed full table scan fallback in convex/stats.ts (trust aggregate counts)
    • Added uniquePaths aggregate component in convex/convex.config.ts
    • Updated recordPageView and backfill to populate uniquePaths aggregate
    • Paginated pageStats to return top 50 pages by views in getStats query
    • Updated src/pages/Stats.tsx with "Top Pages by Views" section title
    • Added .stats-section-subtitle CSS class for showing count indicator
  • Convex-first docs wording cleanup (2026-02-18)

    • Updated content/pages/about.md to describe Convex self-hosted default deployment
    • Updated content/pages/docs.md to treat Netlify as optional legacy mode
    • Updated content/pages/docs-content.md deploy guidance to use npm run deploy by default
    • Updated content/pages/footer.md messaging to Convex-first wording while preserving legacy note
  • Convex one-click deploy readiness pass (2026-02-18)

    • Updated deploy scripts to use CLI-driven self-hosting flow (deploy, upload --build --prod)
    • Added setup and deployment checks: scripts/validate-env.ts, scripts/verify-deploy.ts
    • Added npm scripts: validate:env, validate:env:prod, verify:deploy, verify:deploy:prod
    • Improved create-markdown-sync post-setup guidance for deferred auth setup
    • Added GitHub template one-click path docs in README.md and FORK_CONFIG.md
    • Added auth setup status query (authAdmin:getAuthSetupStatus) and dashboard first-admin guidance
  • @robelest/convex-auth GitHub OAuth integration (2026-02-16)

    • Fixed auth client initialization in src/AppWithWorkOS.tsx with ConvexAuthWrapper
    • Fixed email lookup from auth component in convex/dashboardAuth.ts using components.auth.public.userGetById
    • Added extractUserId() helper to parse userId from "userId|sessionId" format
    • Tested full GitHub OAuth flow with admin email verification
    • Created PRD documentation: prds/adding-robel-auth.md
    • Updated fork setup instructions in FORK_CONFIG.md
  • Migration docs consistency pass (2026-02-16)

    • Aligned Default/Legacy/Local fallback mode wording across README.md, FORK_CONFIG.md, and fork-config.json.example
    • Updated FORK_CONFIG.md dashboard authentication section to match admin-only server enforcement
    • Added compat.legacyDocs to fork-config.json.example
    • Re-ran npm run lint, npm run typecheck, npx convex codegen, and npm run build
  • Auth + hosting migration baseline implementation (2026-02-16)

    • Added dual mode config contract (auth.mode, hosting.mode, media.provider) in siteConfig
    • Added Convex Auth wiring (convex/auth.ts) and preserved legacy WorkOS path (convex/auth.config.ts)
    • Added Convex self-hosting wiring (convex/staticHosting.ts, registerStaticRoutes)
    • Added server-side dashboard admin model (dashboardAdmins, authAdmin APIs, backend admin guards)
    • Added media provider abstraction with direct Convex default and optional ConvexFS/R2 support
    • Updated Dashboard upload components for provider-based upload flows
    • Updated fork and CLI scaffolding defaults to convex-auth + convex-self-hosted + convex media
    • Added custom domain env override support (VITE_CONVEX_SITE_URL, VITE_SITE_URL)
    • Verified with npm run typecheck and npx convex codegen
  • Remove Quill dependency and replace Dashboard rich text editor (2026-02-16)

    • Replaced Quill integration in src/pages/Dashboard.tsx with a simple contentEditable editor and toolbar
    • Kept Markdown and Preview modes unchanged
    • Preserved markdown <-> rich text conversion flow
    • Added rich text image insertion support using existing ImageUploadModal
    • Updated rich text styles in src/styles/global.css
    • Removed Quill dependencies from root and workspace package manifests
    • Verified npm audit --omit=dev reports 0 vulnerabilities
  • Fix pre-existing TypeScript errors so npm run typecheck passes (2026-02-16)

    • Updated src/components/AskAIModal.tsx
    • Updated src/components/Layout.tsx
    • Updated src/hooks/useSearchHighlighting.ts
    • Updated src/pages/Post.tsx
    • Re-verified npm run lint and npm run typecheck both pass
  • Runtime smoke-check after TypeScript fixes (2026-02-16)

    • Ask AI modal open, input, and close flow validated
    • Docs landing and docs page navigation validated
  • AI generated image true delete with confirmation (v2.20.1)

    • Added by_storageId index to aiGeneratedImages table in schema.ts
    • Added deleteGeneratedImage mutation to aiChats.ts
    • Updated Dashboard AIAgentSection with delete button and confirmation dialog
    • Added CSS styles for delete button and confirmation modal
    • Removed Save to Media Library feature (users can download and re-upload)
  • Dashboard frontmatter synchronization and sync warning modal (v2.20.0)

    • Updated ContentItem interface with 19 new frontmatter fields
    • Updated postFrontmatterFields array with all post-specific fields
    • Updated pageFrontmatterFields array with all page-specific fields
    • Updated handleSavePost to include all frontmatter fields
    • Updated handleSavePage to include all frontmatter fields
    • Added SyncWarningModal component for synced content warning
    • Added download and copy buttons to warning modal
    • Added "Save Anyway" option for intentional edits
    • Dashboard-created content bypasses warning
    • Fixed missing unlisted field in sync-posts.ts PostFrontmatter interface
    • Added CSS styles for sync warning modal
    • Created RC1 release blog post at /version-rc1
  • npx create-markdown-sync CLI (v2.19.0)

    • Created packages/create-markdown-sync/ monorepo package
    • Interactive wizard with 13 sections (50+ prompts)
    • Clone template from GitHub via giget
    • Configure site settings automatically
    • Install dependencies and set up Convex
    • Disable WorkOS auth by default (empty auth.config.ts)
    • Start dev server and open browser
    • Clear next steps with docs, deployment, and WorkOS links
    • Template fixes for siteConfig.ts embedded quotes
    • npm publishable package
  • Related posts thumbnail view with toggle (v2.18.2)

    • Added thumbnail view as default for related posts section
    • Card layout with image on left, title/excerpt/meta on right
    • Added view toggle button (same icons as homepage featured section)
    • Added RelatedPostsConfig interface to siteConfig.ts
    • Added relatedPosts config options: defaultViewMode, showViewToggle
    • Added config UI in Dashboard ConfigSection
    • Updated getRelatedPosts query to return image, excerpt, authorName, authorImage
    • Added localStorage persistence for view mode preference
    • Added ~100 lines of CSS for thumbnail card styles
    • Mobile responsive design for thumbnail cards
  • README.md streamlined with docs links (v2.18.1)

    • Reduced from 609 lines to 155 lines
    • Added Documentation section with links to markdown.fast/docs
    • Added Guides subsection with links to specific doc pages
    • Simplified Features section with link to About page
    • Simplified Fork Configuration with doc link
    • Removed detailed sections covered by live docs
  • OpenCode AI development tool integration (v2.18.0)

    • Created .opencode/ directory structure
    • Created opencode.json root configuration
    • Created 3 agents: orchestrator, content-writer, sync-manager
    • Created 6 commands: sync, sync-prod, create-post, create-page, import, deploy
    • Adapted 4 skills from .claude/skills/: frontmatter, sync, convex, content
    • Created sync-helper plugin for content change reminders
    • Created docs-opencode.md documentation page
    • Updated files.md with OpenCode Configuration section
    • Works alongside Claude Code and Cursor without conflicts
  • ConvexFS Media Library with Bunny CDN (v2.17.0)

    • Installed convex-fs package and configured Convex component
    • Created convex/fs.ts with Bunny CDN configuration
    • Created convex/files.ts with file mutations and queries
    • Added ConvexFS routes to convex/http.ts
    • Created MediaLibrary component with upload, copy, delete
    • Added bulk select and delete functionality
    • Enhanced ImageUploadModal with Media Library tab
    • Added size presets (Original, Large, Medium, Small, Thumbnail, Custom)
    • Added image dimensions display with aspect ratio
    • Added file expiration support via setFileExpiration action
    • Created docs-media-setup.md with ConvexFS documentation links
    • Added ~400 lines of CSS for media library and modal styles
  • AI image generation download and copy options (v2.16.4)

    • Added Download button to save generated image to computer
    • Added MD button to copy Markdown code to clipboard
    • Added HTML button to copy HTML code to clipboard
    • Added code preview section showing Markdown and HTML snippets
    • Filename generated from prompt (sanitized and truncated)
    • Added CSS styles for action buttons and code preview
  • Social icons in hamburger menu and Dashboard Config (v2.16.3)

    • Added social icons to MobileMenu below navigation links
    • Removed social icons from mobile header (now only in hamburger menu)
    • Added socialFooter.showInHeader toggle to Dashboard Config
    • Added askAI.enabled toggle to Dashboard Config (new Ask AI card)
    • Added "Configuration alignment" section to CLAUDE.md
    • Added sync comments to siteConfig.ts and Dashboard.tsx ConfigSection
    • Added mobile-menu-social CSS styles
    • Updated files.md, changelog.md, task.md, changelog-page.md
  • Ask AI documentation alignment (v2.16.2)

    • Added askAI config to fork-config.json.example
    • Added Ask AI Configuration section to FORK_CONFIG.md
    • Added Ask AI (header chat) section to docs-dashboard.md
    • Added Ask AI (header chat) section to how-to-use-the-markdown-sync-dashboard.md
    • Updated changelog.md, task.md, changelog-page.md
  • Docs layout scrollbar hiding (v2.16.1)

    • Hidden scrollbars on left sidebar, right sidebar, and main docs content
    • Added body:has(.docs-layout) to prevent page-level scrolling
    • Cross-browser support (IE/Edge, Firefox, Chrome/Safari)
    • Scrolling still works via trackpad, wheel, and touch
    • Updated files.md, changelog.md, task.md, changelog-page.md
  • Version control system (v2.16.0)

    • Added contentVersions and versionControlSettings tables to schema
    • Created convex/versions.ts with 7 functions (isEnabled, setEnabled, createVersion, getVersionHistory, getVersion, restoreVersion, cleanupOldVersions, getStats)
    • Modified cms.ts to capture versions before dashboard edits
    • Modified posts.ts to capture versions before sync updates
    • Modified pages.ts to capture versions before sync updates
    • Added cleanup cron job (daily at 3 AM UTC) for 3-day retention
    • Created VersionHistoryModal component with diff view and restore functionality
    • Added Version Control card in Dashboard Config section with toggle and stats
    • Added History button in Dashboard editor for viewing version history
    • Added ~370 lines of CSS for version modal UI
    • Updated documentation: docs-dashboard.md, FORK_CONFIG.md, files.md, changelog.md, task.md, changelog-page.md
  • Footer not displaying on /docs landing page fix (v2.15.3)

    • DocsPage.tsx was missing Footer component entirely
    • Added Footer import and footerPage query to DocsPage.tsx
    • Added footer rendering logic after BlogPost (same pattern as Post.tsx)
    • Updated getDocsLandingPage query to return showFooter, footer, excerpt, aiChat fields
    • Updated getDocsLandingPost query to return showFooter, footer, aiChat fields
    • Added aiChatEnabled and pageContent props to DocsLayout
  • Additional Core Web Vitals CLS and INP improvements (v2.15.1)

    • Added aspect-ratio to blog images and header images to prevent layout shift
    • Added CSS containment to main content areas
    • Added fetchPriority="high" to logo and header images for faster LCP
    • Added will-change to continuous spin animations and marquee
  • Additional Core Web Vitals fixes (v2.14.1)

    • Fixed docs-skeleton-pulse animation (background-position to transform: translateX())
    • Added will-change to 6 more animated elements (lightbox, modals, chat, toast)
  • Export as PDF option in CopyPageDropdown

    • Added browser print dialog for saving pages as PDF
    • Clean formatted output with markdown syntax stripped
    • Title as heading, metadata on single line, readable content
    • Uses Phosphor FilePdf icon (already installed)
    • Positioned at end of dropdown menu
    • Added formatForPrint function and handleExportPDF handler
    • Updated files.md, changelog.md, task.md documentation
  • Core Web Vitals performance optimizations

    • Fixed non-composited animations in visitor map (SVG r to transform: scale)
    • Removed 5 duplicate @keyframes spin definitions
    • Added will-change hints to animated elements
    • Inlined critical CSS in index.html for faster first paint
    • Added preconnect hints for convex.site
  • Enhanced diff code block rendering with @pierre/diffs

    • Added @pierre/diffs package for Shiki-based diff visualization
    • Created DiffCodeBlock component with unified/split view toggle
    • Updated BlogPost.tsx to route diff/patch blocks to new renderer
    • Added theme-aware CSS styles for diff blocks
    • Added vendor-diffs chunk to Vite config for code splitting
    • Created "How to Use Code Blocks" blog post with examples
    • Updated files.md with DiffCodeBlock documentation
  • Canonical URL mismatch fix (GitHub Issue #6)

    • Raw HTML was serving homepage canonical instead of page-specific canonical
    • Added SEARCH_ENGINE_BOTS array to botMeta.ts for search engine crawler detection
    • Added isSearchEngineBot() helper function
    • Updated condition to serve pre-rendered HTML to search engine bots
    • Added documentation header explaining bot detection configuration
    • Added SEO Bot Configuration section to FORK_CONFIG.md
    • Added SEO and Bot Detection section to setup-guide.md
    • Search engines (Google, Bing, DuckDuckGo, etc.) now receive correct canonical URLs
  • SEO fixes for GitHub Issue #4 (7 issues)

    • Canonical URL: Dynamic canonical link tags for posts and pages in Post.tsx
    • Single H1 per page: Markdown H1s demoted to H2 with .blog-h1-demoted class in BlogPost.tsx
    • DOM order fix: Article before sidebar in DOM, CSS order for visual positioning
    • X-Robots-Tag: HTTP header in netlify.toml (index for public, noindex for dashboard/api)
    • Hreflang tags: Self-referencing hreflang (en, x-default) in index.html, Post.tsx, http.ts
    • og:url consistency: Uses same canonicalUrl variable as canonical link
    • twitter:site: New TwitterConfig in siteConfig.ts with site and creator fields
    • Updated fork-config.json.example with twitter configuration
  • Optional semantic search configuration

    • Added SemanticSearchConfig interface to siteConfig.ts
    • Added semanticSearch.enabled toggle (default: false to avoid blocking forks)
    • Updated SearchModal.tsx to conditionally show mode toggle
    • Updated sync-posts.ts to skip embedding generation when disabled
    • Updated src/pages/Dashboard.tsx with semantic search config option
    • Updated FORK_CONFIG.md with Semantic Search Configuration section
    • Updated fork-config.json.example with semanticSearch option
    • Updated docs-semantic-search.md with enable/disable section
    • Updated docs.md with semantic search configuration note
  • Semantic search with vector embeddings

    • Dual search modes: Keyword (exact match) and Semantic (meaning-based)
    • Toggle between modes in search modal (Cmd+K) with TextAa and Brain icons
    • OpenAI text-embedding-ada-002 for generating 1536-dimension embeddings
    • Similarity scores displayed as percentages in search results
    • Graceful fallback when OPENAI_API_KEY not configured
    • Embeddings generated automatically during npm run sync
    • New convex/embeddings.ts with embedding generation actions
    • New convex/embeddingsQueries.ts with queries and mutations for embedding storage
    • New convex/semanticSearch.ts with vector search action
    • New convex/semanticSearchQueries.ts with internal queries
    • Added embedding field and by_embedding vector index to posts and pages
    • Updated SearchModal.tsx with mode toggle and semantic search integration
    • Documentation pages: docs-search.md and docs-semantic-search.md
  • Dashboard Cloud CMS features

    • Dual source architecture: source: "dashboard" vs source: "sync" coexist independently
    • Direct database operations: "Save to DB" in Write sections, "Save Changes" in editor
    • Source badges in Posts and Pages list views (blue Dashboard, gray Synced)
    • Delete button for dashboard-created content only
    • Delete confirmation modal with warning icon and danger button styling
    • Server-side URL import via Firecrawl (direct to database)
    • Export to markdown for backup or file-based workflow conversion
    • Bulk export script: npm run export:db and npm run export:db:prod
    • New convex/cms.ts with CRUD mutations
    • New convex/importAction.ts with Firecrawl action
    • New scripts/export-db-posts.ts for bulk export
    • Updated sync mutations to preserve dashboard content
  • Rich Text Editor (Quill) in Dashboard

    • Three editing modes: Markdown (default), Rich Text (Quill), Preview
    • Quill toolbar: headers, bold, italic, strikethrough, blockquote, code, lists, links
    • Automatic HTML-to-Markdown conversion on mode switch
    • Theme-aware styling using CSS variables
  • Dashboard UI fixes

    • Fixed source badge overlap with edit pencil in list rows
    • Adjusted grid column widths for proper badge display
    • Added source-badge CSS styles with proper spacing
  • Write page frontmatter sidebar toggle fix

    • Added CSS rules for .write-layout.frontmatter-collapsed to adjust grid when sidebar collapsed
    • Added CSS rules for .write-layout.sidebar-collapsed.frontmatter-collapsed for both sidebars collapsed
    • Added responsive tablet styles for frontmatter collapsed state
    • Frontmatter toggle now works consistently in both focus mode and normal mode
  • Fork configuration improvements

    • Updated scripts/configure-fork.ts to update 3 additional files (DocsPage.tsx, mcp.ts, send-newsletter.ts)
    • Improved updateOpenApiYaml() to handle all example URLs in OpenAPI spec
    • Changed logoGallery hrefs from hardcoded markdown.fast URLs to relative URLs
    • Updated FORK_CONFIG.md with complete file list (14 files, was 11)
    • Updated content/blog/fork-configuration-guide.md with accurate file count
    • Added missing options to fork-config.json.example (statsPage, mcpServer, imageLightbox)
  • Search result highlighting and scroll-to-match

    • Created useSearchHighlighting.ts hook with polling mechanism to wait for content load
    • Search query passed via ?q= URL parameter for highlighting on destination page
    • All matching text highlighted with theme-appropriate colors (dark/light/tan/cloud)
    • First match scrolls into view centered in viewport with header offset
    • Highlights pulse on arrival, fade to subtle after 4 seconds
    • Press Escape to clear highlights
    • Updated SearchModal.tsx, BlogPost.tsx, Post.tsx, global.css
  • Update AI service links to use local /raw URLs

    • Changed ChatGPT, Claude, Perplexity links from GitHub raw URLs to /raw/{slug}.md
    • Simplified AI prompt to "Read this URL and summarize it:"
    • Removed unused siteConfig import and getGitHubRawUrl function
    • URLs now constructed using window.location.origin for consistency
  • Update raw/index.md to include home.md and footer.md content

    • Updated generateHomepageIndex function in scripts/sync-posts.ts
    • Home intro content (slug: home-intro) now displays at top of index.md
    • Footer content (slug: footer) now displays at bottom of index.md
    • Horizontal rule separators between sections
    • Falls back to generic message if home-intro page not found
    • Mirrors actual homepage structure for AI agents reading raw markdown
  • Fix footer not displaying on docs section pages with showFooter: true

    • Added footer.md content query to Post.tsx (matching Home.tsx and Blog.tsx pattern)
    • Updated all 4 Footer component calls to use post.footer || footerPage?.content pattern
    • Footer now falls back to footer.md content when no per-post footer is specified
    • Priority order: per-post frontmatter footer: > synced footer.md content > siteConfig.footer.defaultContent
    • Updated docs.md, files.md, changelog.md, changelog-page.md with fix documentation
  • Centralize defaultTheme in siteConfig.ts

    • Added defaultTheme field to siteConfig.ts (type: Theme)
    • Added Theme type export to siteConfig.ts
    • Updated ThemeContext.tsx to import and use siteConfig.defaultTheme
    • Updated configure-fork.ts to update siteConfig.ts instead of ThemeContext.tsx
    • Renamed updateThemeContext to updateThemeConfig in configure-fork.ts
    • Updated docs.md Theme section with new siteConfig.ts example
    • Updated setup-guide.md "Change the Default Theme" section
    • Updated FORK_CONFIG.md with new theme configuration instructions
    • Updated fork-configuration-guide.md with siteConfig.ts reference
    • Backward compatible: falls back to "tan" if defaultTheme not set
  • Docs sidebar group icons via frontmatter

    • Added docsSectionGroupIcon frontmatter field for posts and pages
    • Icon appears left of the group title expand/collapse chevron
    • Uses Phosphor Icons (55 supported icon names)
    • Icon weight: regular, size: 16px
    • Only one item per group needs to specify the icon
    • Graceful fallback if icon name not recognized
    • Updated sync-posts.ts, schema.ts, posts.ts, pages.ts
    • Updated DocsSidebar.tsx with icon mapping and rendering
    • Added CSS styles for group icons
    • Updated frontmatter.md skill with icon documentation
    • Updated docs.md, files.md, setup-guide.md with new field
  • 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 aiDashboard configuration in siteConfig.ts
    • New convex/aiImageGeneration.ts for Gemini image generation
    • New aiGeneratedImages table 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 showInHeader option to siteConfig.socialFooter config
    • Exported platformIcons from SocialFooter.tsx for reuse
    • Updated Layout.tsx to render social icons in header (left of search)
    • Added CSS styles for .header-social-links and .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
  • YouTube and Twitter/X embed support with domain whitelisting

    • Added ALLOWED_IFRAME_DOMAINS constant for whitelisted domains (YouTube, Twitter/X)
    • Added iframe to sanitize schema with allowed attributes
    • Added custom iframe component handler with domain validation
    • Auto-adds sandbox and loading="lazy" attributes for security
    • Non-whitelisted iframes silently blocked
    • Added .embed-container CSS 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
  • Author pages at /author/:authorSlug with post list

    • Added by_authorName index to posts table in convex/schema.ts
    • Added getAllAuthors and getPostsByAuthor queries in convex/posts.ts
    • Created AuthorPage.tsx component with view mode toggle (list/cards)
    • Added /author/:authorSlug route 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
  • 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 defined error when running npm run configure
    • Added fileURLToPath import from url module
    • Created ES module equivalent of __dirname using import.meta.url
    • Updated files.md, changelog.md, changelog-page.md, TASK.md
  • Footer content via markdown page (footer.md)

    • Created content/pages/footer.md for managing footer content via markdown sync
    • Footer content syncs with npm run sync without redeploy needed
    • Falls back to siteConfig.footer.defaultContent when 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
  • 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

    • blogFeatured frontmatter field for posts to mark as featured on blog page
    • BlogHeroCard component 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
    • getBlogFeaturedPosts query returns all published posts with blogFeatured: true
    • PostList component updated with columns prop (2 or 3) and showExcerpts prop
    • Schema updated with blogFeatured field and by_blogFeatured index
    • sync-posts.ts updated to parse blogFeatured frontmatter
    • 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: true in 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-wrap styling 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

  • gitHubRepo configuration in siteConfig.ts for AI service URL construction

  • by_tags index 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

  • showInNav field for pages to control navigation visibility

  • Pages can be published but hidden from navigation menu

  • Defaults to true for backwards compatibility

  • Pages with showInNav: false remain 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

  1. Run npx convex dev to initialize Convex
  2. Set CONVEX_DEPLOY_KEY in Netlify environment variables
  3. Connect repo to Netlify and deploy
  4. Edge functions automatically handle RSS, sitemap, and API routes

Someday Features TBD

  • Newsletter signup
  • Comments system
  • Draft preview mode