From fa9651f62eeedb120bc1024e651635f848e2ff55 Mon Sep 17 00:00:00 2001
From: Wayne Sutton
Date: Tue, 23 Dec 2025 17:01:22 -0800
Subject: [PATCH] docs: update changelog page with v1.24.3 and v1.24.4 releases
- Added v1.24.4 entry documenting showInNav field and hardcodedNavItems configuration
- Added v1.24.3 entry documenting inner page logo configuration
- Includes configuration examples and updated file lists
- Maintains consistent format with existing changelog entries
---
TASK.md | 11 ++++-
changelog.md | 55 +++++++++++++++++++++++
content/blog/setup-guide.md | 77 ++++++++++++++++++++++++++++++--
content/pages/changelog-page.md | 73 ++++++++++++++++++++++++++++++
content/pages/docs.md | 48 +++++++++++++++++++-
content/pages/projects.md | 1 +
convex/pages.ts | 14 +++++-
convex/schema.ts | 1 +
files.md | 11 ++---
public/raw/about.md | 2 +-
public/raw/changelog.md | 75 ++++++++++++++++++++++++++++++-
public/raw/contact.md | 2 +-
public/raw/docs.md | 50 +++++++++++++++++++--
public/raw/projects.md | 2 +-
public/raw/setup-guide.md | 77 ++++++++++++++++++++++++++++++--
scripts/sync-posts.ts | 3 ++
src/components/FeaturedCards.tsx | 5 ++-
src/components/Layout.tsx | 18 +++++++-
src/config/siteConfig.ts | 30 +++++++++++++
src/pages/Home.tsx | 9 ++--
src/pages/Write.tsx | 2 +
src/styles/global.css | 2 +-
22 files changed, 537 insertions(+), 31 deletions(-)
diff --git a/TASK.md b/TASK.md
index fa261c1..4f16a1c 100644
--- a/TASK.md
+++ b/TASK.md
@@ -15,7 +15,7 @@
## Current Status
-v1.24.2 deployed. Mobile menu redesigned with sidebar integration and typography standardization.
+v1.24.4 deployed. Added `showInNav` field for pages and hardcoded navigation items configuration for React routes.
## Completed
@@ -172,6 +172,15 @@ v1.24.2 deployed. Mobile menu redesigned with sidebar integration and typography
- [x] SidebarContext created to share sidebar data between components
- [x] Mobile menu typography standardized with CSS variables
- [x] Font-family standardized using inherit for consistency
+- [x] `showInNav` field for pages to control navigation visibility
+- [x] Pages can be published but hidden from navigation menu
+- [x] Defaults to `true` for backwards compatibility
+- [x] Pages with `showInNav: false` remain accessible via direct URL, searchable, and available via API
+- [x] Hardcoded navigation items configuration in siteConfig.ts
+- [x] Add React route pages (like /stats, /write) to navigation via hardcodedNavItems
+- [x] Configure navigation order, title, and visibility per route
+- [x] Navigation combines Blog link, hardcoded nav items, and markdown pages
+- [x] All nav items sorted by order field (lower = first)
## Deployment Steps
diff --git a/changelog.md b/changelog.md
index 870341c..2e41225 100644
--- a/changelog.md
+++ b/changelog.md
@@ -4,6 +4,61 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.24.4] - 2025-12-23
+
+### Added
+
+- `showInNav` field for pages to control navigation visibility
+ - Pages can be published and accessible but hidden from navigation menu
+ - Set `showInNav: false` in page frontmatter to hide from nav
+ - Defaults to `true` for backwards compatibility (all existing pages show in nav)
+ - Pages with `showInNav: false` remain:
+ - Published and accessible via direct URL
+ - Searchable via search indexes
+ - Available via API endpoints
+ - Just hidden from the navigation menu
+ - Matches the pattern used for `blogPage.showInNav` in siteConfig.ts
+- Hardcoded navigation items configuration for React routes
+ - Add React route pages (like `/stats`, `/write`) to navigation via `siteConfig.hardcodedNavItems`
+ - Configure navigation order, title, and visibility per route
+ - Set `showInNav: false` to hide from nav while keeping route accessible
+ - Navigation combines Blog link, hardcoded nav items, and markdown pages
+ - All nav items sorted by `order` field (lower = first)
+ - Example: Configure `/stats` and `/write` routes in `siteConfig.ts`
+
+### Technical
+
+- Updated `convex/schema.ts`: Added optional `showInNav` field to pages table
+- Updated `convex/pages.ts`: `getAllPages` query filters out pages where `showInNav === false`
+- Updated `scripts/sync-posts.ts`: Parses `showInNav` from page frontmatter
+- Updated `src/pages/Write.tsx`: Added `showInNav` field to page template and PAGE_FIELDS reference
+- Updated `src/config/siteConfig.ts`: Added `HardcodedNavItem` interface and `hardcodedNavItems` config array
+- Updated `src/components/Layout.tsx`: Reads `hardcodedNavItems` from siteConfig and combines with Blog link and pages
+
+### Documentation
+
+- Updated `content/pages/docs.md`: Added `showInNav` to static pages frontmatter table
+- Updated `content/blog/setup-guide.md`: Added `showInNav` to static pages frontmatter table
+
+## [1.24.3] - 2025-12-23
+
+### Added
+
+- Inner page logo configuration
+ - Logo displays in header on blog page, individual posts, and static pages
+ - Desktop: logo positioned on the left (before back button)
+ - Mobile: logo positioned on the right (smaller size for compact header)
+ - Configurable via `siteConfig.innerPageLogo.enabled` and `siteConfig.innerPageLogo.size`
+ - Does not affect homepage logo (controlled separately)
+ - Logo links to homepage when clicked
+
+### Technical
+
+- Updated `src/config/siteConfig.ts`: Added `InnerPageLogoConfig` interface and `innerPageLogo` config option
+- Updated `src/pages/Blog.tsx`: Added logo to header navigation
+- Updated `src/pages/Post.tsx`: Added logo to header navigation for both posts and pages
+- Updated `src/styles/global.css`: Added CSS for desktop (left) and mobile (right) logo positioning with responsive sizing
+
## [1.24.2] - 2025-12-23
### Changed
diff --git a/content/blog/setup-guide.md b/content/blog/setup-guide.md
index 8444529..a98ded0 100644
--- a/content/blog/setup-guide.md
+++ b/content/blog/setup-guide.md
@@ -570,10 +570,12 @@ To use a different letter or icon, edit the SVG directly or replace the file.
### Change the Site Logo
-The logo appears on the homepage. Edit `src/pages/Home.tsx`:
+The site uses two logo configurations:
+
+**Homepage logo:** Edit `src/config/siteConfig.ts`:
```typescript
-const siteConfig = {
+export default {
logo: "/images/logo.svg", // Set to null to hide the logo
// ...
};
@@ -581,6 +583,17 @@ const siteConfig = {
Replace `public/images/logo.svg` with your own logo file. Recommended: SVG format, 512x512 pixels.
+**Inner page logo:** Shows on blog page, individual posts, and static pages. Configure in `src/config/siteConfig.ts`:
+
+```typescript
+innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+},
+```
+
+The inner page logo appears in the top left corner on desktop and top right on mobile. It uses the same logo file as the homepage logo. Set `enabled: false` to hide it on inner pages while keeping the homepage logo.
+
### Change the Default Open Graph Image
The default OG image is used when a post does not have an `image` field in its frontmatter. Replace `public/images/og-default.svg` with your own image.
@@ -601,6 +614,7 @@ Edit `src/config/siteConfig.ts` to customize:
export default {
name: "Your Name",
title: "Your Title",
+ logo: "/images/logo.svg", // null to hide homepage logo
intro: "Your introduction...",
bio: "Your bio...",
@@ -611,7 +625,28 @@ export default {
title: "Blog", // Nav link and page title
order: 0, // Nav order (lower = first)
},
- displayOnHomepage: true, // Show posts on homepage
+
+ // Hardcoded navigation items for React routes
+ hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+ ],
+
+ // Inner page logo configuration
+ innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+ },
// Featured section options
featuredViewMode: "list", // 'list' or 'cards'
@@ -827,6 +862,39 @@ Cards display post thumbnails (from `image` frontmatter field), titles, excerpts
**View preference:** User's view mode choice is saved to localStorage and persists across page visits.
+### Hardcoded Navigation Items
+
+Add React route pages (like `/stats`, `/write`) to the navigation menu via `siteConfig.ts`. These pages are React components, not markdown files.
+
+Configure in `src/config/siteConfig.ts`:
+
+```typescript
+hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+],
+```
+
+Navigation combines three sources in this order:
+
+1. Blog link (if `blogPage.enabled` and `blogPage.showInNav` are true)
+2. Hardcoded nav items (from `hardcodedNavItems` array)
+3. Markdown pages (from `content/pages/` with `showInNav: true`)
+
+All items sort by `order` field (lower numbers first), then alphabetically by title.
+
+**Hide from navigation:** Set `showInNav: false` to keep a route accessible but hidden from the nav menu. The route still works at its URL, just won't appear in navigation links.
+
### Scroll-to-top button
A scroll-to-top button appears after scrolling down on posts and pages. Configure it in `src/components/Layout.tsx`:
@@ -922,6 +990,7 @@ Your page content here...
| `slug` | Yes | URL path (e.g., `/about`) |
| `published` | Yes | Set `true` to show |
| `order` | No | Display order (lower = first) |
+| `showInNav` | No | Show in navigation menu (default: `true`) |
| `authorName` | No | Author display name shown next to date |
| `authorImage` | No | Round author avatar image URL |
| `layout` | No | Set to `"sidebar"` for docs-style layout with TOC |
@@ -930,6 +999,8 @@ Your page content here...
Pages appear automatically in the navigation when published.
+**Hide pages from navigation:** Set `showInNav: false` in page frontmatter to keep a page published and accessible via direct URL, but hidden from the navigation menu. Useful for pages like `/projects` that you want to link directly but not show in the main nav. Pages with `showInNav: false` remain searchable and available via API endpoints.
+
**Sidebar layout:** Add `layout: "sidebar"` to any post or page frontmatter to enable a docs-style layout with a table of contents sidebar. The sidebar extracts headings (H1, H2, H3) automatically and provides smooth scroll navigation. Only appears if headings exist in the content.
### Update SEO Meta Tags
diff --git a/content/pages/changelog-page.md b/content/pages/changelog-page.md
index c5e8b01..875e51c 100644
--- a/content/pages/changelog-page.md
+++ b/content/pages/changelog-page.md
@@ -8,6 +8,79 @@ layout: "sidebar"
All notable changes to this project.
+## v1.24.4
+
+Released December 23, 2025
+
+**Navigation visibility control and hardcoded nav items**
+
+- `showInNav` field for pages to control navigation visibility
+ - Pages can be published and accessible but hidden from navigation menu
+ - Set `showInNav: false` in page frontmatter to hide from nav
+ - Defaults to `true` for backwards compatibility (all existing pages show in nav)
+ - Pages with `showInNav: false` remain:
+ - Published and accessible via direct URL
+ - Searchable via search indexes
+ - Available via API endpoints
+ - Just hidden from the navigation menu
+ - Matches the pattern used for `blogPage.showInNav` in siteConfig.ts
+
+- Hardcoded navigation items configuration for React routes
+ - Add React route pages (like `/stats`, `/write`) to navigation via `siteConfig.hardcodedNavItems`
+ - Configure navigation order, title, and visibility per route
+ - Set `showInNav: false` to hide from nav while keeping route accessible
+ - Navigation combines Blog link, hardcoded nav items, and markdown pages
+ - All nav items sorted by `order` field (lower = first)
+
+Example configuration:
+
+```typescript
+// src/config/siteConfig.ts
+hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true,
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+],
+```
+
+Updated files: `convex/schema.ts`, `convex/pages.ts`, `scripts/sync-posts.ts`, `src/pages/Write.tsx`, `src/config/siteConfig.ts`, `src/components/Layout.tsx`
+
+Documentation updated: `content/pages/docs.md`, `content/blog/setup-guide.md`
+
+## v1.24.3
+
+Released December 23, 2025
+
+**Inner page logo configuration**
+
+- Logo displays in header on blog page, individual posts, and static pages
+- Desktop: logo positioned on the left (before back button)
+- Mobile: logo positioned on the right (smaller size for compact header)
+- Configurable via `siteConfig.innerPageLogo.enabled` and `siteConfig.innerPageLogo.size`
+- Does not affect homepage logo (controlled separately)
+- Logo links to homepage when clicked
+
+Configuration:
+
+```typescript
+// src/config/siteConfig.ts
+innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+},
+```
+
+Updated files: `src/config/siteConfig.ts`, `src/pages/Blog.tsx`, `src/pages/Post.tsx`, `src/styles/global.css`
+
## v1.24.2
Released December 23, 2025
diff --git a/content/pages/docs.md b/content/pages/docs.md
index a9e73d1..447b4ce 100644
--- a/content/pages/docs.md
+++ b/content/pages/docs.md
@@ -121,6 +121,7 @@ Content here...
| `slug` | Yes | URL path |
| `published` | Yes | `true` to show |
| `order` | No | Nav order (lower = first) |
+| `showInNav` | No | Show in navigation menu (default: `true`) |
| `excerpt` | No | Short text for card view |
| `image` | No | Thumbnail for featured card view |
| `featured` | No | `true` to show in featured section |
@@ -129,6 +130,8 @@ Content here...
| `authorImage` | No | Round author avatar image URL |
| `layout` | No | Set to `"sidebar"` for docs-style layout with TOC |
+**Hide pages from navigation:** Set `showInNav: false` to keep a page published and accessible via direct URL, but hidden from the navigation menu. Pages with `showInNav: false` remain searchable and available via API endpoints. Useful for pages you want to link directly but not show in the main nav.
+
### Sidebar layout
Posts and pages can use a docs-style layout with a table of contents sidebar. Add `layout: "sidebar"` to the frontmatter:
@@ -320,7 +323,7 @@ Edit `src/config/siteConfig.ts`:
export default {
name: "Site Name",
title: "Tagline",
- logo: "/images/logo.svg", // null to hide
+ logo: "/images/logo.svg", // null to hide homepage logo
intro: "Introduction text...",
bio: "Bio text...",
@@ -331,7 +334,28 @@ export default {
title: "Blog", // Nav link and page title
order: 0, // Nav order (lower = first)
},
- displayOnHomepage: true, // Show posts on homepage
+
+ // Hardcoded navigation items for React routes
+ hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+ ],
+
+ // Inner page logo configuration
+ innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+ },
// Featured section
featuredViewMode: "list", // 'list' or 'cards'
@@ -355,6 +379,21 @@ export default {
};
```
+**Logo configuration:**
+
+- `logo`: Homepage logo path (set to `null` to hide). Uses `public/images/logo.svg` by default.
+- `innerPageLogo`: Logo shown on blog page, posts, and static pages. Desktop: top left. Mobile: top right. Set `enabled: false` to hide on inner pages while keeping homepage logo.
+
+**Navigation structure:**
+
+Navigation combines three sources sorted by `order`:
+
+1. Blog link (if `blogPage.enabled` and `blogPage.showInNav` are true)
+2. Hardcoded nav items (React routes from `hardcodedNavItems`)
+3. Markdown pages (from `content/pages/` with `showInNav: true`)
+
+All items sort by `order` (lower first), then alphabetically by title.
+
### Featured items
Posts and pages appear in the featured section when marked with `featured: true` in frontmatter.
@@ -604,6 +643,11 @@ Mobile sizes defined in `@media (max-width: 768px)` block.
The `npm run sync` command only syncs markdown text content. Images are deployed when Netlify builds your site.
+**Logo options:**
+
+- **Homepage logo:** Configured via `logo` in `siteConfig.ts`. Set to `null` to hide.
+- **Inner page logo:** Configured via `innerPageLogo` in `siteConfig.ts`. Shows on blog page, posts, and static pages. Desktop: top left corner. Mobile: top right corner (smaller). Set `enabled: false` to hide on inner pages while keeping homepage logo.
+
## Search
Press `Command+K` (Mac) or `Ctrl+K` (Windows/Linux) to open the search modal. Click the search icon in the nav or use the keyboard shortcut.
diff --git a/content/pages/projects.md b/content/pages/projects.md
index c1743aa..0ef4d83 100644
--- a/content/pages/projects.md
+++ b/content/pages/projects.md
@@ -2,6 +2,7 @@
title: "Projects"
slug: "projects"
published: true
+showInNav: false
order: 3
---
diff --git a/convex/pages.ts b/convex/pages.ts
index 98e6939..3a4275b 100644
--- a/convex/pages.ts
+++ b/convex/pages.ts
@@ -11,6 +11,7 @@ export const getAllPages = query({
title: v.string(),
published: v.boolean(),
order: v.optional(v.number()),
+ showInNav: v.optional(v.boolean()),
excerpt: v.optional(v.string()),
image: v.optional(v.string()),
featured: v.optional(v.boolean()),
@@ -26,8 +27,14 @@ export const getAllPages = query({
.withIndex("by_published", (q) => q.eq("published", true))
.collect();
+ // Filter out pages where showInNav is explicitly false
+ // Default to true for backwards compatibility (undefined/null = show in nav)
+ const visiblePages = pages.filter(
+ (page) => page.showInNav !== false,
+ );
+
// Sort by order (lower numbers first), then by title
- const sortedPages = pages.sort((a, b) => {
+ const sortedPages = visiblePages.sort((a, b) => {
const orderA = a.order ?? 999;
const orderB = b.order ?? 999;
if (orderA !== orderB) return orderA - orderB;
@@ -40,6 +47,7 @@ export const getAllPages = query({
title: page.title,
published: page.published,
order: page.order,
+ showInNav: page.showInNav,
excerpt: page.excerpt,
image: page.image,
featured: page.featured,
@@ -103,6 +111,7 @@ export const getPageBySlug = query({
content: v.string(),
published: v.boolean(),
order: v.optional(v.number()),
+ showInNav: v.optional(v.boolean()),
excerpt: v.optional(v.string()),
image: v.optional(v.string()),
featured: v.optional(v.boolean()),
@@ -130,6 +139,7 @@ export const getPageBySlug = query({
content: page.content,
published: page.published,
order: page.order,
+ showInNav: page.showInNav,
excerpt: page.excerpt,
image: page.image,
featured: page.featured,
@@ -151,6 +161,7 @@ export const syncPagesPublic = mutation({
content: v.string(),
published: v.boolean(),
order: v.optional(v.number()),
+ showInNav: v.optional(v.boolean()),
excerpt: v.optional(v.string()),
image: v.optional(v.string()),
featured: v.optional(v.boolean()),
@@ -189,6 +200,7 @@ export const syncPagesPublic = mutation({
content: page.content,
published: page.published,
order: page.order,
+ showInNav: page.showInNav,
excerpt: page.excerpt,
image: page.image,
featured: page.featured,
diff --git a/convex/schema.ts b/convex/schema.ts
index 48abab6..5e28d86 100644
--- a/convex/schema.ts
+++ b/convex/schema.ts
@@ -41,6 +41,7 @@ export default defineSchema({
content: v.string(),
published: v.boolean(),
order: v.optional(v.number()), // Display order in nav
+ showInNav: v.optional(v.boolean()), // Show in navigation menu (default: true)
excerpt: v.optional(v.string()), // Short excerpt for card view
image: v.optional(v.string()), // Thumbnail/OG image URL for featured cards
featured: v.optional(v.boolean()), // Show in featured section
diff --git a/files.md b/files.md
index c0f072c..6f70a98 100644
--- a/files.md
+++ b/files.md
@@ -33,7 +33,7 @@ A brief description of each file in the codebase.
| File | Description |
| --------------- | --------------------------------------------------------------------------------------------------------- |
-| `siteConfig.ts` | Centralized site configuration (name, logo, blog page, posts display, GitHub contributions, nav order) |
+| `siteConfig.ts` | Centralized site configuration (name, logo, blog page, posts display, GitHub contributions, nav order, inner page logo settings, hardcoded navigation items for React routes) |
### Pages (`src/pages/`)
@@ -49,7 +49,7 @@ A brief description of each file in the codebase.
| File | Description |
| ------------------------- | ---------------------------------------------------------- |
-| `Layout.tsx` | Page wrapper with search button, theme toggle, mobile menu (left-aligned on mobile), and scroll-to-top |
+| `Layout.tsx` | Page wrapper with search button, theme toggle, mobile menu (left-aligned on mobile), and scroll-to-top. Combines Blog link, hardcoded nav items, and markdown pages for navigation |
| `ThemeToggle.tsx` | Theme switcher (dark/light/tan/cloud) |
| `PostList.tsx` | Year-grouped blog post list or card grid (supports list/cards view modes) |
| `BlogPost.tsx` | Markdown renderer with syntax highlighting and collapsible sections (details/summary) |
@@ -149,10 +149,11 @@ Markdown files for static pages like About, Projects, Contact, Changelog.
| `slug` | URL path for the page |
| `published` | Whether page is public |
| `order` | Display order in navigation (lower first) |
+| `showInNav` | Show in navigation menu (default: true) |
| `excerpt` | Short excerpt for card view (optional) |
-| `featured` | Show in featured section (optional) |
-| `featuredOrder` | Order in featured section (optional) |
-| `authorName` | Author display name (optional) |
+| `featured` | Show in featured section (optional) |
+| `featuredOrder` | Order in featured section (optional) |
+| `authorName` | Author display name (optional) |
| `authorImage` | Round author avatar image URL (optional) |
## Scripts (`scripts/`)
diff --git a/public/raw/about.md b/public/raw/about.md
index 0b9f7b1..40ff81e 100644
--- a/public/raw/about.md
+++ b/public/raw/about.md
@@ -2,7 +2,7 @@
---
Type: page
-Date: 2025-12-23
+Date: 2025-12-24
---
An open-source publishing framework for AI agents and developers. Write markdown, sync from the terminal. Your content is instantly available to browsers, LLMs, and AI agents. Built on Convex and Netlify.
diff --git a/public/raw/changelog.md b/public/raw/changelog.md
index 832ae7c..495d7fe 100644
--- a/public/raw/changelog.md
+++ b/public/raw/changelog.md
@@ -2,11 +2,84 @@
---
Type: page
-Date: 2025-12-23
+Date: 2025-12-24
---
All notable changes to this project.
+## v1.24.4
+
+Released December 23, 2025
+
+**Navigation visibility control and hardcoded nav items**
+
+- `showInNav` field for pages to control navigation visibility
+ - Pages can be published and accessible but hidden from navigation menu
+ - Set `showInNav: false` in page frontmatter to hide from nav
+ - Defaults to `true` for backwards compatibility (all existing pages show in nav)
+ - Pages with `showInNav: false` remain:
+ - Published and accessible via direct URL
+ - Searchable via search indexes
+ - Available via API endpoints
+ - Just hidden from the navigation menu
+ - Matches the pattern used for `blogPage.showInNav` in siteConfig.ts
+
+- Hardcoded navigation items configuration for React routes
+ - Add React route pages (like `/stats`, `/write`) to navigation via `siteConfig.hardcodedNavItems`
+ - Configure navigation order, title, and visibility per route
+ - Set `showInNav: false` to hide from nav while keeping route accessible
+ - Navigation combines Blog link, hardcoded nav items, and markdown pages
+ - All nav items sorted by `order` field (lower = first)
+
+Example configuration:
+
+```typescript
+// src/config/siteConfig.ts
+hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true,
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+],
+```
+
+Updated files: `convex/schema.ts`, `convex/pages.ts`, `scripts/sync-posts.ts`, `src/pages/Write.tsx`, `src/config/siteConfig.ts`, `src/components/Layout.tsx`
+
+Documentation updated: `content/pages/docs.md`, `content/blog/setup-guide.md`
+
+## v1.24.3
+
+Released December 23, 2025
+
+**Inner page logo configuration**
+
+- Logo displays in header on blog page, individual posts, and static pages
+- Desktop: logo positioned on the left (before back button)
+- Mobile: logo positioned on the right (smaller size for compact header)
+- Configurable via `siteConfig.innerPageLogo.enabled` and `siteConfig.innerPageLogo.size`
+- Does not affect homepage logo (controlled separately)
+- Logo links to homepage when clicked
+
+Configuration:
+
+```typescript
+// src/config/siteConfig.ts
+innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+},
+```
+
+Updated files: `src/config/siteConfig.ts`, `src/pages/Blog.tsx`, `src/pages/Post.tsx`, `src/styles/global.css`
+
## v1.24.2
Released December 23, 2025
diff --git a/public/raw/contact.md b/public/raw/contact.md
index a9490c2..9c73c33 100644
--- a/public/raw/contact.md
+++ b/public/raw/contact.md
@@ -2,7 +2,7 @@
---
Type: page
-Date: 2025-12-23
+Date: 2025-12-24
---
You found the contact page. Nice
diff --git a/public/raw/docs.md b/public/raw/docs.md
index 74dafaa..37844e8 100644
--- a/public/raw/docs.md
+++ b/public/raw/docs.md
@@ -2,7 +2,7 @@
---
Type: page
-Date: 2025-12-23
+Date: 2025-12-24
---
Reference documentation for setting up, customizing, and deploying this markdown framework.
@@ -120,6 +120,7 @@ Content here...
| `slug` | Yes | URL path |
| `published` | Yes | `true` to show |
| `order` | No | Nav order (lower = first) |
+| `showInNav` | No | Show in navigation menu (default: `true`) |
| `excerpt` | No | Short text for card view |
| `image` | No | Thumbnail for featured card view |
| `featured` | No | `true` to show in featured section |
@@ -128,6 +129,8 @@ Content here...
| `authorImage` | No | Round author avatar image URL |
| `layout` | No | Set to `"sidebar"` for docs-style layout with TOC |
+**Hide pages from navigation:** Set `showInNav: false` to keep a page published and accessible via direct URL, but hidden from the navigation menu. Pages with `showInNav: false` remain searchable and available via API endpoints. Useful for pages you want to link directly but not show in the main nav.
+
### Sidebar layout
Posts and pages can use a docs-style layout with a table of contents sidebar. Add `layout: "sidebar"` to the frontmatter:
@@ -319,7 +322,7 @@ Edit `src/config/siteConfig.ts`:
export default {
name: "Site Name",
title: "Tagline",
- logo: "/images/logo.svg", // null to hide
+ logo: "/images/logo.svg", // null to hide homepage logo
intro: "Introduction text...",
bio: "Bio text...",
@@ -330,7 +333,28 @@ export default {
title: "Blog", // Nav link and page title
order: 0, // Nav order (lower = first)
},
- displayOnHomepage: true, // Show posts on homepage
+
+ // Hardcoded navigation items for React routes
+ hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+ ],
+
+ // Inner page logo configuration
+ innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+ },
// Featured section
featuredViewMode: "list", // 'list' or 'cards'
@@ -354,6 +378,21 @@ export default {
};
```
+**Logo configuration:**
+
+- `logo`: Homepage logo path (set to `null` to hide). Uses `public/images/logo.svg` by default.
+- `innerPageLogo`: Logo shown on blog page, posts, and static pages. Desktop: top left. Mobile: top right. Set `enabled: false` to hide on inner pages while keeping homepage logo.
+
+**Navigation structure:**
+
+Navigation combines three sources sorted by `order`:
+
+1. Blog link (if `blogPage.enabled` and `blogPage.showInNav` are true)
+2. Hardcoded nav items (React routes from `hardcodedNavItems`)
+3. Markdown pages (from `content/pages/` with `showInNav: true`)
+
+All items sort by `order` (lower first), then alphabetically by title.
+
### Featured items
Posts and pages appear in the featured section when marked with `featured: true` in frontmatter.
@@ -603,6 +642,11 @@ Mobile sizes defined in `@media (max-width: 768px)` block.
The `npm run sync` command only syncs markdown text content. Images are deployed when Netlify builds your site.
+**Logo options:**
+
+- **Homepage logo:** Configured via `logo` in `siteConfig.ts`. Set to `null` to hide.
+- **Inner page logo:** Configured via `innerPageLogo` in `siteConfig.ts`. Shows on blog page, posts, and static pages. Desktop: top left corner. Mobile: top right corner (smaller). Set `enabled: false` to hide on inner pages while keeping homepage logo.
+
## Search
Press `Command+K` (Mac) or `Ctrl+K` (Windows/Linux) to open the search modal. Click the search icon in the nav or use the keyboard shortcut.
diff --git a/public/raw/projects.md b/public/raw/projects.md
index 4ff47f8..5f6dd6d 100644
--- a/public/raw/projects.md
+++ b/public/raw/projects.md
@@ -2,7 +2,7 @@
---
Type: page
-Date: 2025-12-23
+Date: 2025-12-24
---
This markdown framework is open source and built to be extended. Here is what ships out of the box.
diff --git a/public/raw/setup-guide.md b/public/raw/setup-guide.md
index b0dbb67..433ce03 100644
--- a/public/raw/setup-guide.md
+++ b/public/raw/setup-guide.md
@@ -564,10 +564,12 @@ To use a different letter or icon, edit the SVG directly or replace the file.
### Change the Site Logo
-The logo appears on the homepage. Edit `src/pages/Home.tsx`:
+The site uses two logo configurations:
+
+**Homepage logo:** Edit `src/config/siteConfig.ts`:
```typescript
-const siteConfig = {
+export default {
logo: "/images/logo.svg", // Set to null to hide the logo
// ...
};
@@ -575,6 +577,17 @@ const siteConfig = {
Replace `public/images/logo.svg` with your own logo file. Recommended: SVG format, 512x512 pixels.
+**Inner page logo:** Shows on blog page, individual posts, and static pages. Configure in `src/config/siteConfig.ts`:
+
+```typescript
+innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+},
+```
+
+The inner page logo appears in the top left corner on desktop and top right on mobile. It uses the same logo file as the homepage logo. Set `enabled: false` to hide it on inner pages while keeping the homepage logo.
+
### Change the Default Open Graph Image
The default OG image is used when a post does not have an `image` field in its frontmatter. Replace `public/images/og-default.svg` with your own image.
@@ -595,6 +608,7 @@ Edit `src/config/siteConfig.ts` to customize:
export default {
name: "Your Name",
title: "Your Title",
+ logo: "/images/logo.svg", // null to hide homepage logo
intro: "Your introduction...",
bio: "Your bio...",
@@ -605,7 +619,28 @@ export default {
title: "Blog", // Nav link and page title
order: 0, // Nav order (lower = first)
},
- displayOnHomepage: true, // Show posts on homepage
+
+ // Hardcoded navigation items for React routes
+ hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+ ],
+
+ // Inner page logo configuration
+ innerPageLogo: {
+ enabled: true, // Set to false to hide logo on inner pages
+ size: 28, // Logo height in pixels (keeps aspect ratio)
+ },
// Featured section options
featuredViewMode: "list", // 'list' or 'cards'
@@ -821,6 +856,39 @@ Cards display post thumbnails (from `image` frontmatter field), titles, excerpts
**View preference:** User's view mode choice is saved to localStorage and persists across page visits.
+### Hardcoded Navigation Items
+
+Add React route pages (like `/stats`, `/write`) to the navigation menu via `siteConfig.ts`. These pages are React components, not markdown files.
+
+Configure in `src/config/siteConfig.ts`:
+
+```typescript
+hardcodedNavItems: [
+ {
+ slug: "stats",
+ title: "Stats",
+ order: 10,
+ showInNav: true, // Set to false to hide from nav
+ },
+ {
+ slug: "write",
+ title: "Write",
+ order: 20,
+ showInNav: true,
+ },
+],
+```
+
+Navigation combines three sources in this order:
+
+1. Blog link (if `blogPage.enabled` and `blogPage.showInNav` are true)
+2. Hardcoded nav items (from `hardcodedNavItems` array)
+3. Markdown pages (from `content/pages/` with `showInNav: true`)
+
+All items sort by `order` field (lower numbers first), then alphabetically by title.
+
+**Hide from navigation:** Set `showInNav: false` to keep a route accessible but hidden from the nav menu. The route still works at its URL, just won't appear in navigation links.
+
### Scroll-to-top button
A scroll-to-top button appears after scrolling down on posts and pages. Configure it in `src/components/Layout.tsx`:
@@ -916,6 +984,7 @@ Your page content here...
| `slug` | Yes | URL path (e.g., `/about`) |
| `published` | Yes | Set `true` to show |
| `order` | No | Display order (lower = first) |
+| `showInNav` | No | Show in navigation menu (default: `true`) |
| `authorName` | No | Author display name shown next to date |
| `authorImage` | No | Round author avatar image URL |
| `layout` | No | Set to `"sidebar"` for docs-style layout with TOC |
@@ -924,6 +993,8 @@ Your page content here...
Pages appear automatically in the navigation when published.
+**Hide pages from navigation:** Set `showInNav: false` in page frontmatter to keep a page published and accessible via direct URL, but hidden from the navigation menu. Useful for pages like `/projects` that you want to link directly but not show in the main nav. Pages with `showInNav: false` remain searchable and available via API endpoints.
+
**Sidebar layout:** Add `layout: "sidebar"` to any post or page frontmatter to enable a docs-style layout with a table of contents sidebar. The sidebar extracts headings (H1, H2, H3) automatically and provides smooth scroll navigation. Only appears if headings exist in the content.
### Update SEO Meta Tags
diff --git a/scripts/sync-posts.ts b/scripts/sync-posts.ts
index b1c4538..fcbaefd 100644
--- a/scripts/sync-posts.ts
+++ b/scripts/sync-posts.ts
@@ -63,6 +63,7 @@ interface PageFrontmatter {
slug: string;
published: boolean;
order?: number; // Display order in navigation
+ showInNav?: boolean; // Show in navigation menu (default: true)
excerpt?: string; // Short excerpt for card view
image?: string; // Thumbnail/OG image URL for featured cards
featured?: boolean; // Show in featured section
@@ -78,6 +79,7 @@ interface ParsedPage {
content: string;
published: boolean;
order?: number;
+ showInNav?: boolean; // Show in navigation menu (default: true)
excerpt?: string; // Short excerpt for card view
image?: string; // Thumbnail/OG image URL for featured cards
featured?: boolean; // Show in featured section
@@ -168,6 +170,7 @@ function parsePageFile(filePath: string): ParsedPage | null {
content: content.trim(),
published: frontmatter.published ?? true,
order: frontmatter.order,
+ showInNav: frontmatter.showInNav, // Show in navigation menu (default: true)
excerpt: frontmatter.excerpt, // Short excerpt for card view
image: frontmatter.image, // Thumbnail/OG image URL for featured cards
featured: frontmatter.featured, // Show in featured section
diff --git a/src/components/FeaturedCards.tsx b/src/components/FeaturedCards.tsx
index cf9c5ca..a2905b2 100644
--- a/src/components/FeaturedCards.tsx
+++ b/src/components/FeaturedCards.tsx
@@ -1,4 +1,5 @@
import { useQuery } from "convex/react";
+import { Link } from "react-router-dom";
import { api } from "../../convex/_generated/api";
// Type for featured item from Convex (used for backwards compatibility)
@@ -142,7 +143,7 @@ export default function FeaturedCards({
return (