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()inauthAdmin.tsanddashboardAuth.ts(runtime errors with duplicate rows) - Cleaned up duplicate PRD files from
prds/root (kept remaining passes inprds/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_storageidindex onaiImageGenerationJobsfor_storageFK lookup - Extracted
sendContactEmailhelpers (buildContactHtml,buildContactText) incontactActions.ts - Extracted
stats.tshelpers:updatePageViewAggregates,buildPageStats,collectVisitorLocations,getTopPathStats - Added 7 rule suppressions to
convex-doctor.tomlfor by-design patterns (auth awareness, schema nesting, optional fields, ordered.first(), domain-organized files, multi-step handlers) convex-doctorimproved from 92/100 with 0 errors / 39 warnings to 100/100 with 0 errors / 0 warnings / 18 infos
- Added
-
Convex doctor sixteenth pass (2026-03-20 20:15 UTC)
- Batched
fetchPostsByIdsandfetchPagesByIdsinto onefetchSearchDocsByIdsinternal query, mergedcompleteSemanticSearchJobandfailSemanticSearchJobinto onefinalizeSemanticSearchJobmutation, and extracted afinalizehelper sosemanticSearchJobuses fewerctx.run*call sites (7 to 4 in the handler) - Converted
authComponent.tsfrom registeredinternalQueryfunctions to plain async helpers (authUserGetByIdHelper,authUserListHelper) so callers indashboardAuth.tsandauthAdmin.tsavoid the doublerunQueryhop that triggeredperf/helper-vs-run - Also updated
askAI.node.tsto use the batchedfetchSearchDocsByIdsquery - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from 91/100 with 0 errors / 43 warnings to 92/100 with 0 errors / 39 warnings
- Batched
-
Convex doctor fifteenth pass (2026-03-20 09:10 UTC)
- Batched
sendPostNewsletterprefetch intogetPostNewsletterSendContextInternalso the action uses one internal query plus the finalrecordPostSentmutation - Routed auth bootstrap and admin email resolution through
internal.authComponent.*forwarders and addedconvex-doctor.tomlso component forwarders and generated output do not dominate the score - Tightened
viewCountsslug reads to.unique()where the app assumes one document per slug - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorreached 91/100 with 0 errors and 43 warnings; remaining.first()hits are intentional (ordered picks and keys that are not unique by design)
- Batched
-
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, andnpx convex-doctor@latest convex-doctorimproved from85/100with1 error / 54 warningsto86/100with1 error / 49 warnings- The highest-signal remaining issues are now
sendPostNewsletterchaining, 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
replacewarning in the image job flow - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from84/100with1 error / 60 warningsto85/100with1 error / 54 warnings, which moved the repo into theHealthyband- The highest-signal remaining issues are now
importFromUrlJobchaining, 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
semanticSearchJobsflow and reactiveSearchModaljob polling - Added follow-up auth-awareness signals to
recordPageView,heartbeat, andversions.isEnabled, and converted the new semantic search request error toConvexError - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from81/100with1 error / 64 warningsto84/100with1 error / 60 warnings- The remaining top findings are now mostly structural: the direct auth component reference,
generateResponserun-call chaining, and the reduced.first()list
- Moved semantic search off the browser action path by replacing the public action with a queued
-
Convex doctor eleventh pass (2026-03-20 08:15 UTC)
- Replaced browser
resolveDirectUploadcalls in both media upload UIs with the existinggetDirectStorageUrlquery and maderesolveDirectUploadinternal-only - Added non-breaking auth-awareness to
searchand converted newsletter sent-post slug lookups to.unique() - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from80/100with1 error / 68 warningsto81/100with1 error / 64 warnings- The next concrete browser-action follow-up after this pass was semantic search
- Replaced browser
-
Convex doctor tenth pass (2026-03-20 08:24 UTC)
- Replaced the direct Dashboard
importFromUrlbrowser action with a queuedimportUrlJobsflow usingconvex/importJobs.ts, an internalimportFromUrlJob, and reactive Dashboard job state - Tightened the remaining safe
versionControlSettings.by_keylookup inversions.getStatsfrom.first()to.unique() - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest - The targeted
importFromUrlpublic action warning was removed, whileconvex-doctorsettled at80/100with1 error / 68 warnings - The next obvious browser-action follow-up is
resolveDirectUpload
- Replaced the direct Dashboard
-
Convex doctor ninth pass (2026-03-20 08:16 UTC)
- Moved
files.setFileExpirationfrom 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, andnpx convex-doctor@latest convex-doctorheld at81/100while findings improved from1 error / 84 warningsto1 error / 68 warnings- The next obvious follow-ups are
importFromUrl, the remaining direct auth component reference, the reduced set of.first()warnings, and structuralctx.runQuerychain warnings
- Moved
-
Convex doctor eighth pass (2026-03-20 08:10 UTC)
- Moved
files.getDownloadUrlfrom a public action to an internal action, which removed the direct browser action path without changing any current app flow - Refactored
convex/rss.tsto export plain helper functions and wrapped them inconvex/http.ts, clearing the old RSS handler syntax warning - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from78/100with1 error / 89 warningsto81/100with1 error / 84 warnings- The next obvious follow-up is
files.setFileExpiration, which is now the remaining public action warning in that area
- Moved
-
Convex doctor seventh pass (2026-03-20 08:01 UTC)
- Batched version snapshots in
syncPostsPublicandsyncPagesPublicthroughversions.createVersionsBatch, which removed per-item scheduler usage while preserving pre-update snapshot content - Converted
files.commitFilefrom a public action to a public mutation and updated both upload UIs to useuseMutation - Added explicit high bounds to the remaining safe
.collect()paths touched inconvex/posts.ts,convex/pages.ts,convex/newsletter.ts, andconvex/authAdmin.ts - Added explicit return validators across
convex/files.tslist, info, download, delete, expiration, and count functions - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from67/100with17 errors / 98 warningsto78/100with1 error / 89 warnings
- Batched version snapshots in
-
Convex doctor sixth pass (2026-03-20 08:36 UTC)
- Added auth-awareness to
syncPagesPublicandsyncPostsPublicso the sync mutations keep their current behavior while reducing false-positive security warnings - Moved embedding refresh entrypoints to
convex/embeddingsAdmin.tsso 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 thestreamResponseold-syntax warning - Added a return validator to
askAI.getStreamBodythat matches the streaming component contract without guessing the shape - Final verification completed:
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latest convex-doctorimproved from66/100with17 errors / 110 warningsto67/100with17 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
- Added auth-awareness to
-
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.tswith request, status, and internal completion/failure handlers for reactive image generation state - Updated
src/pages/Dashboard.tsxto 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, andnpx convex-doctor@latest convex-doctorreturned to66/100while findings dropped from28 errors / 130 warningsto17 errors / 110 warnings- Remaining meaningful follow-ups are
syncPagesPublic,generateMissingEmbeddings, thecomponents.auth.public.userListdirect-function-ref warning, and the legacystreamResponsesyntax warning
- Moved Dashboard image generation off the direct public action path into a persisted job flow using
-
Convex doctor fourth pass (2026-03-20 06:46 UTC)
- Refactored
convex/aiChatActions.tssogenerateResponseis 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, andnpx convex-doctor@latest convex-doctorstayed at68/100while warnings dropped from136to130generateResponsedropped from209lines to69lines and its Convex call chain dropped from5to4
- Refactored
-
Convex doctor third pass (2026-03-19 07:26 UTC)
- Query cleanup completed across
convex/posts.ts,convex/pages.ts, andconvex/stats.ts - Replaced the remaining safe
collect then filterpipelines 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, andnpx convex-doctor@latest convex-doctorimproved from66/100to68/100
- Query cleanup completed across
-
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, andnpx 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
deferattribute for non-blocking page load
- Added Rybbit analytics script to
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
pathsWithCountsandallPathsFromAggregateinconvex/stats.ts - Fixed
fetchprioritytofetchPriority(React camelCase) inLayout.tsx,Home.tsx, andPost.tsx(6 instances total) npx tsc --noEmitnow passes with zero errors
- Removed unused variables
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
- Added missing CSS variables (
-
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_MSinconvex/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: falsein siteConfig
- Increased backend dedup window from 20s to 45s (
Session updates complete on 2026-02-21.
- Stats performance optimizations (2026-02-21)
- Stats tracking now respects
statsPage.enabledconfig (no DB writes when disabled) - Removed expensive full table scan fallback in
getStatsquery - Added
uniquePathsaggregate component for O(log n) path tracking - Paginated
pageStatsto return top 50 pages by views - Updated Stats page UI to show "Top Pages by Views" with count indicator
- Stats tracking now respects
Session updates complete on 2026-02-16.
-
@robelest/convex-auth integration fully working (2026-02-16)
- Auth client properly initialized in
ConvexAuthWrappercomponent - 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.mdwith full migration guide - Fork setup instructions updated in
FORK_CONFIG.md
- Auth client properly initialized in
-
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, andfork-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-authsign 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:getStatsfull-table read.
- Fixed
-
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.
-
Convex doctor sixteenth pass (2026-03-20 20:15 UTC)
- Created PRD at
prds/convex-doctor-sixteenth-pass.md - Merged
fetchPostsByIds+fetchPagesByIdsintofetchSearchDocsByIdsandcompleteSemanticSearchJob+failSemanticSearchJobintofinalizeSemanticSearchJob - Extracted
finalizehelper insemanticSearch.tsto centralize mutation calls (7ctx.run*call sites to 4) - Updated
askAI.node.tsto use batchedfetchSearchDocsByIds - Converted
authComponent.tsfrom registered internalQuery to plain async helpers; updatedauthAdmin.tsanddashboardAuth.tsto import directly - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestat 92/100, 0 errors, 39 warnings
- Created PRD at
-
Convex doctor seventeenth pass (2026-03-20 21:30 UTC)
- Created PRD at
prds/convex-doctor-seventeenth-pass.md - Added
by_storageidindex onaiImageGenerationJobsfor_storageFK - Extracted
sendContactEmailhelpers (buildContactHtml,buildContactText) incontactActions.ts - Extracted
stats.tshelpers:updatePageViewAggregates,buildPageStats,collectVisitorLocations,getTopPathStats - Added 7 rule suppressions to
convex-doctor.tomlfor by-design patterns - Verified
npx convex codegen,npm run build, andnpx convex-doctorat 100/100, 0 errors, 0 warnings, 18 infos
- Created PRD at
-
Convex doctor fifteenth pass (2026-03-20 09:10 UTC)
- Created follow-up PRD at
prds/convex-doctor-fifteenth-pass.md - Added
getPostNewsletterSendContextInternaland reducedsendPostNewsletterto one batched internal query plusrecordPostSent - Added
convex/authComponent.tsforwarders; updatedauthAdminanddashboardAuthto callinternal.authComponent.* - Switched
viewCountsslug queries inconvex/posts.tsto.unique() - Added root
convex-doctor.toml(ignore forwarder and_generated, disablecorrectness/generated-code-modified) - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestat 91/100, 0 errors, 43 warnings
- Created follow-up PRD at
-
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.tsand reduced inline action orchestration inconvex/importAction.ts - Extracted shared frontmatter helpers in
convex/cms.tsfor markdown export queries - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith findings improved to1 error / 49 warnings
- Created follow-up PRD at
-
Convex doctor thirteenth pass (2026-03-20 08:33 UTC)
- Created follow-up PRD at
prds/convex-doctor-thirteenth-pass.md - Reduced AI chat
generateResponserun-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
replaceusage in the image job flow - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith findings improved to1 error / 54 warnings
- Created follow-up PRD at
-
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.tsxto debounce job requests and render results from the current job record - Added auth-awareness follow-ups in
convex/stats.tsandconvex/versions.ts - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith findings improved to1 error / 60 warnings
- Created follow-up PRD at
-
Convex doctor eleventh pass (2026-03-20 08:15 UTC)
- Created follow-up PRD at
prds/convex-doctor-eleventh-pass.md - Replaced browser
resolveDirectUploadusage with the existinggetDirectStorageUrlquery - Made
resolveDirectUploadinternal-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, andnpx convex-doctor@latestwith findings reduced to1 error / 64 warnings
- Created follow-up PRD at
-
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 inversions.getStats - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestafter removing theimportFromUrlpublic action warning
- Created follow-up PRD at
-
Convex doctor ninth pass (2026-03-20 08:16 UTC)
- Created follow-up PRD at
prds/convex-doctor-ninth-pass.md - Moved
files.setFileExpirationoff 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, andnpx convex-doctor@latestwith findings reduced to1 error / 68 warnings
- Created follow-up PRD at
-
Convex doctor eighth pass (2026-03-20 08:10 UTC)
- Created follow-up PRD at
prds/convex-doctor-eighth-pass.md - Moved
files.getDownloadUrloff the public action path by making it internal-only - Refactored RSS handlers to helper-wrapped routes in
convex/rss.tsandconvex/http.ts - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith findings reduced to1 error / 84 warnings
- Created follow-up PRD at
-
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.commitFileoff 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, andnpx convex-doctor@latestwith findings reduced to1 error / 89 warnings
- Created follow-up PRD at
-
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, andnpx convex-doctor@latestwith warnings reduced to98
- Created follow-up PRD at
-
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.tsandconvex/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, andconvex/authAdmin.ts - Verified
npx convex codegen,npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith findings reduced to17 errors / 110 warnings
- Created follow-up PRD at
-
Convex doctor fourth pass (2026-03-20 06:46 UTC)
- Created follow-up PRD at
prds/convex-doctor-fourth-pass.md - Refactored
convex/aiChatActions.tsinto helper-driven orchestration and removed the extra storage URL query hop - Removed unused
getStorageUrlsBatchinternal query fromconvex/aiChats.ts - Added auth-awareness to
regeneratePostEmbedding,isConfigured,subscribe, andunsubscribe - Verified
npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith warnings reduced to130
- Created follow-up PRD at
-
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 filterpipelines inconvex/posts.ts,convex/pages.ts, andconvex/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()inposts,pages,askAI,aiChats,stats, andauthAdmin - Verified
npx tsc --noEmit,npm run build, andnpx convex-doctor@latestwith final score68/100
- Created follow-up PRD at
-
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.generateResponseto 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, andnpx convex-doctor@latestwith final score66/100
- Created follow-up PRD at
-
Convex doctor remediation (2026-03-18)
- Phase 1: Added auth to
streamResponseHTTP action andgenerateResponsepublic action - Created
isCurrentUserDashboardAdminInternalinternal query inconvex/authAdmin.ts - Replaced all
api.*withinternal.*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
createPostInternalinternal mutation incms.ts - Phase 2: Removed
Date.now()fromstats.getStatsquery (now acceptsnowarg) - Removed
Date.now()fromnewsletter.getStatsForSummary(now acceptsnowarg) - Updated Stats.tsx and Dashboard.tsx StatsSection with 60-second tick interval
- Updated
newsletterActions.tsto passnow: Date.now()togetStatsForSummary - Phase 3: Replaced collect-then-filter in
embeddingsQueries.tswith async iteration - Created
getAllPostsWithContentInternalbatch query to eliminate N+1 in export and RSS - Created
getStorageUrlsBatchinternal query to batch-resolve image URLs in AI chat - Refactored
generateResponseto batch-resolve all storage URLs in one query - Phase 4: Renamed
by_docsSectiontoby_docs_sectionin schema and all callers - Removed redundant
by_sessionindex fromaiChatstable (prefix ofby_session_and_context) - Updated
clearAllChatsto useby_session_and_contextindex prefix - Phase 5: Replaced
throw new Error(...)withConvexErrorindashboardAuth.tsandauthAdmin.ts - Added
ConvexErrortoaiChatActions.tsauth check - Removed debug
console.logcalls fromdashboardAuth.ts - Created PRD:
prds/convex-doctor-remediation.md
- Phase 1: Added auth to
-
Rybbit analytics integration (2026-03-01)
- Added Rybbit analytics script to
index.htmlwith site ID24731ca420a4 - Script loads with
deferfor non-blocking page rendering
- Added Rybbit analytics script to
-
WSL 2 Convex setup docs hardening (2026-02-27)
- Added WSL 2 fallback login flow in
content/blog/setup-guide.mdusingnpx convex login --no-open --login-flow paste - Added README fallback setup commands using
npx convex dev --oncefor first-time initialization
- Added WSL 2 fallback login flow in
-
TypeScript error fixes (2026-02-27)
- Removed unused
pathsWithCountsandallPathsFromAggregatevariables inconvex/stats.ts - Fixed
fetchprioritytofetchPriorityinsrc/components/Layout.tsx - Fixed
fetchprioritytofetchPriorityinsrc/pages/Home.tsx - Fixed
fetchprioritytofetchPriorityinsrc/pages/Post.tsx(4 instances) - Verified
npx tsc --noEmitpasses with zero errors
- Removed unused
-
Media Library and router fixes (2026-02-22)
- Added
RecentUploadtracking with preview and MD/HTML/URL copy buttons for convex/r2 providers - Persisted recent uploads to
sessionStoragefor 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
- Added
-
Heartbeat write conflict elimination (2026-02-22)
- Increased
HEARTBEAT_DEDUP_MSfrom 20s to 45s inconvex/stats.ts - Increased
HEARTBEAT_INTERVAL_MSfrom 30s to 45s inusePageTracking.ts - Increased
HEARTBEAT_DEBOUNCE_MSfrom 20s to 45s inusePageTracking.ts - Added BroadcastChannel for cross-tab coordination (only leader tab sends heartbeats)
- Added tab leadership election with claim/close/heartbeat_sent messages
- Added
isStatsEnabledcheck tosendHeartbeatcallback for complete disabling - Created PRD documentation:
prds/fix-heartbeat-write-conflicts.md
- Increased
-
Stats performance optimizations (2026-02-21)
- Added
statsPage.enabledcheck inusePageTracking.tsto prevent DB writes when stats disabled - Removed full table scan fallback in
convex/stats.ts(trust aggregate counts) - Added
uniquePathsaggregate component inconvex/convex.config.ts - Updated
recordPageViewand backfill to populateuniquePathsaggregate - Paginated
pageStatsto return top 50 pages by views ingetStatsquery - Updated
src/pages/Stats.tsxwith "Top Pages by Views" section title - Added
.stats-section-subtitleCSS class for showing count indicator
- Added
-
Convex-first docs wording cleanup (2026-02-18)
- Updated
content/pages/about.mdto describe Convex self-hosted default deployment - Updated
content/pages/docs.mdto treat Netlify as optional legacy mode - Updated
content/pages/docs-content.mddeploy guidance to usenpm run deployby default - Updated
content/pages/footer.mdmessaging to Convex-first wording while preserving legacy note
- Updated
-
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-syncpost-setup guidance for deferred auth setup - Added GitHub template one-click path docs in
README.mdandFORK_CONFIG.md - Added auth setup status query (
authAdmin:getAuthSetupStatus) and dashboard first-admin guidance
- Updated deploy scripts to use CLI-driven self-hosting flow (
-
@robelest/convex-auth GitHub OAuth integration (2026-02-16)
- Fixed auth client initialization in
src/AppWithWorkOS.tsxwithConvexAuthWrapper - Fixed email lookup from auth component in
convex/dashboardAuth.tsusingcomponents.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
- Fixed auth client initialization in
-
Migration docs consistency pass (2026-02-16)
- Aligned Default/Legacy/Local fallback mode wording across
README.md,FORK_CONFIG.md, andfork-config.json.example - Updated
FORK_CONFIG.mddashboard authentication section to match admin-only server enforcement - Added
compat.legacyDocstofork-config.json.example - Re-ran
npm run lint,npm run typecheck,npx convex codegen, andnpm run build
- Aligned Default/Legacy/Local fallback mode wording across
-
Auth + hosting migration baseline implementation (2026-02-16)
- Added dual mode config contract (
auth.mode,hosting.mode,media.provider) insiteConfig - 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,authAdminAPIs, 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 typecheckandnpx convex codegen
- Added dual mode config contract (
-
Remove Quill dependency and replace Dashboard rich text editor (2026-02-16)
- Replaced Quill integration in
src/pages/Dashboard.tsxwith a simplecontentEditableeditor 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=devreports 0 vulnerabilities
- Replaced Quill integration in
-
Fix pre-existing TypeScript errors so
npm run typecheckpasses (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 lintandnpm run typecheckboth pass
- Updated
-
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_storageIdindex toaiGeneratedImagestable in schema.ts - Added
deleteGeneratedImagemutation 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)
- Added
-
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.jsonroot 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
- Created
-
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.showInHeadertoggle to Dashboard Config - Added
askAI.enabledtoggle 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
askAIconfig tofork-config.json.example - Added Ask AI Configuration section to
FORK_CONFIG.md - Added Ask AI (header chat) section to
docs-dashboard.md - Added Ask AI (header chat) section to
how-to-use-the-markdown-sync-dashboard.md - Updated changelog.md, task.md, changelog-page.md
- Added
-
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-demotedclass in BlogPost.tsx - DOM order fix: Article before sidebar in DOM, CSS
orderfor 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
SemanticSearchConfiginterface tositeConfig.ts - Added
semanticSearch.enabledtoggle (default: false to avoid blocking forks) - Updated
SearchModal.tsxto conditionally show mode toggle - Updated
sync-posts.tsto skip embedding generation when disabled - Updated
src/pages/Dashboard.tsxwith semantic search config option - Updated
FORK_CONFIG.mdwith Semantic Search Configuration section - Updated
fork-config.json.examplewith semanticSearch option - Updated
docs-semantic-search.mdwith enable/disable section - Updated
docs.mdwith semantic search configuration note
- Added
-
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.tswith embedding generation actions - New
convex/embeddingsQueries.tswith queries and mutations for embedding storage - New
convex/semanticSearch.tswith vector search action - New
convex/semanticSearchQueries.tswith internal queries - Added
embeddingfield andby_embeddingvector index to posts and pages - Updated SearchModal.tsx with mode toggle and semantic search integration
- Documentation pages:
docs-search.mdanddocs-semantic-search.md
-
Dashboard Cloud CMS features
- Dual source architecture:
source: "dashboard"vssource: "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:dbandnpm run export:db:prod - New
convex/cms.tswith CRUD mutations - New
convex/importAction.tswith Firecrawl action - New
scripts/export-db-posts.tsfor bulk export - Updated sync mutations to preserve dashboard content
- Dual source architecture:
-
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-collapsedto adjust grid when sidebar collapsed - Added CSS rules for
.write-layout.sidebar-collapsed.frontmatter-collapsedfor both sidebars collapsed - Added responsive tablet styles for frontmatter collapsed state
- Frontmatter toggle now works consistently in both focus mode and normal mode
- Added CSS rules for
-
Fork configuration improvements
- Updated
scripts/configure-fork.tsto 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.mdwith complete file list (14 files, was 11) - Updated
content/blog/fork-configuration-guide.mdwith accurate file count - Added missing options to
fork-config.json.example(statsPage, mcpServer, imageLightbox)
- Updated
-
Search result highlighting and scroll-to-match
- Created
useSearchHighlighting.tshook 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
- Created
-
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
siteConfigimport andgetGitHubRawUrlfunction - URLs now constructed using
window.location.originfor consistency
- Changed ChatGPT, Claude, Perplexity links from GitHub raw URLs to
-
Update raw/index.md to include home.md and footer.md content
- Updated
generateHomepageIndexfunction inscripts/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
- Updated
-
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?.contentpattern - 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
defaultThemefield to siteConfig.ts (type:Theme) - Added
Themetype 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
updateThemeContexttoupdateThemeConfigin 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
- Added
-
Docs sidebar group icons via frontmatter
- Added
docsSectionGroupIconfrontmatter 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
- Added
-
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 page -
BlogHeroCardcomponent 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: true -
PostListcomponent 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)
- 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
- Newsletter signup
- Comments system
- Draft preview mode