docs: add changelog entries for v1.33.1 through v1.37.0

Add missing changelog entries to content/pages/changelog-page.md:

v1.34.0 (2025-12-26): Blog page featured layout with hero post
- blogFeatured frontmatter field for posts
- Hero card displays first featured post with landscape image
- 2-column featured row for remaining featured posts
- 3-column grid for regular posts

v1.35.0 (2025-12-26): Image support at top of posts and pages
- showImageAtTop frontmatter field
- Full-width image display above post header
- Works for both posts and pages

v1.36.0 (2025-12-27): Social footer component
- Customizable social links (8 platform types)
- Copyright with auto-updating year
- showSocialFooter frontmatter field for per-page control
- Configurable via siteConfig.socialFooter

v1.37.0 (2025-12-27): Newsletter Admin UI
- Three-column admin interface at /newsletter-admin
- Subscriber management with search and filters
- Send newsletter panel (post selection or custom email)
- Weekly digest automation (Sunday 9am UTC)
- Developer notifications (subscriber alerts, weekly stats)
- Markdown-to-HTML conversion for custom emails
This commit is contained in:
Wayne Sutton
2025-12-27 15:32:07 -08:00
parent c312a4c808
commit a87db9d171
55 changed files with 7753 additions and 1260 deletions

View File

@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>ModelContextProtocol</title><path d="M15.688 2.343a2.588 2.588 0 00-3.61 0l-9.626 9.44a.863.863 0 01-1.203 0 .823.823 0 010-1.18l9.626-9.44a4.313 4.313 0 016.016 0 4.116 4.116 0 011.204 3.54 4.3 4.3 0 013.609 1.18l.05.05a4.115 4.115 0 010 5.9l-8.706 8.537a.274.274 0 000 .393l1.788 1.754a.823.823 0 010 1.18.863.863 0 01-1.203 0l-1.788-1.753a1.92 1.92 0 010-2.754l8.706-8.538a2.47 2.47 0 000-3.54l-.05-.049a2.588 2.588 0 00-3.607-.003l-7.172 7.034-.002.002-.098.097a.863.863 0 01-1.204 0 .823.823 0 010-1.18l7.273-7.133a2.47 2.47 0 00-.003-3.537z"></path><path d="M14.485 4.703a.823.823 0 000-1.18.863.863 0 00-1.204 0l-7.119 6.982a4.115 4.115 0 000 5.9 4.314 4.314 0 006.016 0l7.12-6.982a.823.823 0 000-1.18.863.863 0 00-1.204 0l-7.119 6.982a2.588 2.588 0 01-3.61 0 2.47 2.47 0 010-3.54l7.12-6.982z"></path></svg>

After

Width:  |  Height:  |  Size: 978 B

View File

@@ -8,6 +8,161 @@ Date: 2025-12-27
All notable changes to this project.
![](https://img.shields.io/badge/License-MIT-yellow.svg)
## v1.38.0
Released December 27, 2025
**Newsletter CLI improvements**
- `newsletter:send` now calls `scheduleSendPostNewsletter` mutation directly
- Sends emails in the background instead of printing instructions
- Provides clear success/error feedback
- Shows helpful messages about checking Newsletter Admin for results
- New `newsletter:send:stats` command
- Sends weekly stats summary to your inbox on demand
- Uses `scheduleSendStatsSummary` mutation
- Email sent to AGENTMAIL_INBOX or AGENTMAIL_CONTACT_EMAIL
- New mutation `scheduleSendStatsSummary` in `convex/newsletter.ts`
- Allows CLI to trigger stats summary sending
- Schedules `sendWeeklyStatsSummary` internal action
**Documentation**
- Blog post: "How to use AgentMail with Markdown Sync"
- Complete setup guide for AgentMail integration
- Environment variables configuration
- Newsletter and contact form features
- CLI commands documentation
- Troubleshooting section
- Updated docs.md with new CLI commands
- Updated files.md with new script reference
- Verified all AgentMail features use environment variables (no hardcoded emails)
Updated files: `scripts/send-newsletter.ts`, `scripts/send-newsletter-stats.ts`, `convex/newsletter.ts`, `package.json`, `content/blog/how-to-use-agentmail.md`, `content/pages/docs.md`, `files.md`, `changelog.md`, `content/pages/changelog-page.md`, `TASK.md`
## v1.37.0
Released December 27, 2025
**Newsletter Admin UI**
- Newsletter Admin UI at `/newsletter-admin`
- Three-column layout similar to Write page
- View all subscribers with search and filter (all/active/unsubscribed)
- Stats showing active, total, and sent newsletter counts
- Delete subscribers directly from admin
- Send newsletter panel with two modes:
- Send Post: Select a blog post to send as newsletter
- Write Email: Compose custom email with markdown support
- Markdown-to-HTML conversion for custom emails (headers, bold, italic, links, lists)
- Copy icon on success messages to copy CLI commands
- Theme-aware success/error styling (no hardcoded green)
- Recent newsletters list showing sent history
- Configurable via `siteConfig.newsletterAdmin`
**Weekly Digest automation**
- Cron job runs every Sunday at 9:00 AM UTC
- Automatically sends all posts published in the last 7 days
- Uses AgentMail SDK for email delivery
- Configurable via `siteConfig.weeklyDigest`
**Developer Notifications**
- New subscriber alerts sent via email when someone subscribes
- Weekly stats summary sent every Monday at 9:00 AM UTC
- Uses `AGENTMAIL_CONTACT_EMAIL` or `AGENTMAIL_INBOX` as recipient
- Configurable via `siteConfig.newsletterNotifications`
**Admin queries and mutations**
- `getAllSubscribers`: Paginated subscriber list with search/filter
- `deleteSubscriber`: Remove subscriber from database
- `getNewsletterStats`: Stats for admin dashboard
- `getPostsForNewsletter`: List of posts with sent status
Updated files: `convex/newsletter.ts`, `convex/newsletterActions.ts`, `convex/posts.ts`, `convex/crons.ts`, `src/config/siteConfig.ts`, `src/App.tsx`, `src/styles/global.css`, `src/pages/NewsletterAdmin.tsx`
## v1.36.0
Released December 27, 2025
**Social footer component**
- Social footer component with customizable social links and copyright
- Displays social icons on the left (GitHub, Twitter/X, LinkedIn, and more)
- Shows copyright symbol, site name, and auto-updating year on the right
- Configurable via `siteConfig.socialFooter` in `src/config/siteConfig.ts`
- Supports 8 platform types: github, twitter, linkedin, instagram, youtube, tiktok, discord, website
- Uses Phosphor icons for consistent styling
- Appears below the main footer on homepage, blog posts, and pages
- Can work independently of the main footer when set via frontmatter
**Frontmatter control for social footer**
- `showSocialFooter` field for posts and pages to override siteConfig defaults
- Set `showSocialFooter: false` to hide on specific posts/pages
- Works like existing `showFooter` field pattern
**Social footer configuration options**
- `enabled`: Global toggle for social footer
- `showOnHomepage`, `showOnPosts`, `showOnPages`, `showOnBlogPage`: Per-location visibility
- `socialLinks`: Array of social link objects with platform and URL
- `copyright.siteName`: Site/company name for copyright display
- `copyright.showYear`: Toggle for auto-updating year
Updated files: `src/config/siteConfig.ts`, `convex/schema.ts`, `convex/posts.ts`, `convex/pages.ts`, `scripts/sync-posts.ts`, `src/pages/Home.tsx`, `src/pages/Post.tsx`, `src/pages/Blog.tsx`, `src/styles/global.css`, `src/components/SocialFooter.tsx`
## v1.35.0
Released December 26, 2025
**Image support at top of posts and pages**
- `showImageAtTop` frontmatter field for posts and pages
- Set `showImageAtTop: true` to display the `image` field at the top of the post/page above the header
- Image displays full-width with rounded corners above the post header
- Default behavior: if `showImageAtTop` is not set or `false`, image only used for Open Graph previews and featured card thumbnails
- Works for both blog posts and static pages
- Image appears above the post header when enabled
Updated files: `convex/schema.ts`, `scripts/sync-posts.ts`, `convex/posts.ts`, `convex/pages.ts`, `src/pages/Post.tsx`, `src/pages/Write.tsx`, `src/styles/global.css`
Documentation updated: `content/pages/docs.md`, `content/blog/how-to-publish.md`, `content/blog/using-images-in-posts.md`, `files.md`
## v1.34.0
Released December 26, 2025
**Blog page featured layout with hero post**
- `blogFeatured` frontmatter field for posts to mark as featured on blog page
- First `blogFeatured` post displays as hero card with landscape image, tags, date, title, excerpt, author info, and read more link
- Remaining `blogFeatured` posts display in 2-column featured row with excerpts
- Regular (non-featured) posts display in 3-column grid without excerpts
- New `BlogHeroCard` component (`src/components/BlogHeroCard.tsx`) for hero display
- New `getBlogFeaturedPosts` query returns all published posts with `blogFeatured: true` sorted by date
- `PostList` component updated with `columns` prop (2 or 3) and `showExcerpts` prop
- Card images use 16:10 landscape aspect ratio
- Footer support on blog page via `siteConfig.footer.showOnBlogPage`
Updated files: `convex/schema.ts`, `convex/posts.ts`, `scripts/sync-posts.ts`, `src/pages/Blog.tsx`, `src/components/PostList.tsx`, `src/styles/global.css`
## v1.33.1
Released December 26, 2025
**Article centering in sidebar layouts**
- Article content now centers in the middle column when sidebars are present
- Left sidebar stays flush left, right sidebar stays flush right
- Article uses `margin-left: auto; margin-right: auto` within its `1fr` grid column
- Works with both two-column (left sidebar only) and three-column (both sidebars) layouts
- Consistent `max-width: 800px` for article content across all sidebar configurations
Updated files: `src/styles/global.css`
## v1.33.0
Released December 26, 2025

View File

@@ -7,37 +7,10 @@ Date: 2025-12-27
You found the contact page. Nice
<!-- contactform -->
## The technical way
This site runs on Convex, which means every page view is a live subscription to the database. You are not reading cached HTML. You are reading data that synced moments ago.
If you want to reach out, here is an idea: fork this repo, add a contact form, wire it to a Convex mutation, and deploy. Your message will hit the database in under 100ms. No email server required.
```typescript
// A contact form mutation looks like this
export const submitContact = mutation({
args: {
name: v.string(),
email: v.string(),
message: v.string(),
},
handler: async (ctx, args) => {
await ctx.db.insert("messages", {
...args,
createdAt: Date.now(),
});
},
});
```
## The human way
Open an issue on GitHub. Or find the author on X. Or send a carrier pigeon. Convex does not support those yet, but the team is probably working on it.
## Why Convex
Traditional backends make you write API routes, manage connections, handle caching, and pray nothing breaks at 3am. Convex handles all of that. You write functions. They run in the cloud. Data syncs to clients. Done.
The contact form example above is the entire backend. No Express. No database drivers. No WebSocket setup. Just a function that inserts a row.
That is why this site uses Convex.
If you want to reach out, here is an idea: fork this repo, add a contact form, wire it to a Convex mutation, and deploy. Your message will hit the database in under 100ms. No email server required.

View File

@@ -98,23 +98,31 @@ image: "/images/og-image.png"
Content here...
```
| Field | Required | Description |
| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
| `title` | Yes | Post title |
| `description` | Yes | SEO description |
| `date` | Yes | YYYY-MM-DD format |
| `slug` | Yes | URL path (unique) |
| `published` | Yes | `true` to show |
| `tags` | Yes | Array of strings |
| `readTime` | No | Display time estimate |
| `image` | No | OG image and featured card thumbnail. See [Using Images in Blog Posts](/using-images-in-posts) for markdown and HTML syntax |
| `showImageAtTop` | No | Set `true` to display the image at the top of the post above the header (default: `false`) |
| `excerpt` | No | Short text for card view |
| `featured` | No | `true` to show in featured section |
| `featuredOrder` | No | Order in featured (lower = first) |
| `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 |
| Field | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `title` | Yes | Post title |
| `description` | Yes | SEO description |
| `date` | Yes | YYYY-MM-DD format |
| `slug` | Yes | URL path (unique) |
| `published` | Yes | `true` to show |
| `tags` | Yes | Array of strings |
| `readTime` | No | Display time estimate |
| `image` | No | OG image and featured card thumbnail. See [Using Images in Blog Posts](/using-images-in-posts) for markdown and HTML syntax |
| `showImageAtTop` | No | Set `true` to display the image at the top of the post above the header (default: `false`) |
| `excerpt` | No | Short text for card view |
| `featured` | No | `true` to show in featured section |
| `featuredOrder` | No | Order in featured (lower = first) |
| `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 |
| `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) |
| `showFooter` | No | Show footer on this post (overrides siteConfig default) |
| `footer` | No | Footer markdown content (overrides siteConfig.defaultContent) |
| `showSocialFooter` | No | Show social footer on this post (overrides siteConfig default) |
| `aiChat` | No | Enable AI chat in right sidebar. Set `true` to enable (requires `rightSidebar: true` and `siteConfig.aiChat.enabledOnContent: true`). Set `false` to explicitly hide even if global config is enabled. |
| `blogFeatured` | No | Show as featured on blog page (first becomes hero, rest in 2-column row) |
| `newsletter` | No | Override newsletter signup display (`true` to show, `false` to hide) |
| `contactForm` | No | Enable contact form on this post |
### Static pages
@@ -131,22 +139,28 @@ order: 1
Content here...
```
| Field | Required | Description |
| --------------- | -------- | ----------------------------------------------------------------------------- |
| `title` | Yes | Nav link text |
| `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 |
| `showImageAtTop` | No | Set `true` to display the image at the top of the page above the header (default: `false`) |
| `featured` | No | `true` to show in featured section |
| `featuredOrder` | No | Order in featured (lower = first) |
| `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 |
| `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) |
| Field | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `title` | Yes | Nav link text |
| `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 |
| `showImageAtTop` | No | Set `true` to display the image at the top of the page above the header (default: `false`) |
| `featured` | No | `true` to show in featured section |
| `featuredOrder` | No | Order in featured (lower = first) |
| `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 |
| `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) |
| `showFooter` | No | Show footer on this page (overrides siteConfig default) |
| `footer` | No | Footer markdown content (overrides siteConfig.defaultContent) |
| `showSocialFooter` | No | Show social footer on this page (overrides siteConfig default) |
| `aiChat` | No | Enable AI chat in right sidebar. Set `true` to enable (requires `rightSidebar: true` and `siteConfig.aiChat.enabledOnContent: true`). Set `false` to explicitly hide even if global config is enabled. |
| `newsletter` | No | Override newsletter signup display (`true` to show, `false` to hide) |
| `contactForm` | No | Enable contact form on this page |
**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.
@@ -799,11 +813,86 @@ The `/stats` page displays real-time analytics:
All stats update automatically via Convex subscriptions.
## Newsletter Admin
The Newsletter Admin page at `/newsletter-admin` provides a UI for managing subscribers and sending newsletters.
**Features:**
- View and search all subscribers (search bar in header)
- Filter by status (all, active, unsubscribed)
- Delete subscribers
- Send blog posts as newsletters
- Write and send custom emails with markdown support
- View recent newsletter sends (last 10, includes both posts and custom emails)
- Email statistics dashboard with:
- Total emails sent
- Newsletters sent count
- Active subscribers
- Retention rate
- Detailed summary table
**Configuration:**
Enable in `src/config/siteConfig.ts`:
```typescript
newsletterAdmin: {
enabled: true, // Enable /newsletter-admin route
showInNav: false, // Hide from navigation (access via direct URL)
},
```
**Environment Variables (Convex):**
| Variable | Description |
| ------------------------- | --------------------------------------------------- |
| `AGENTMAIL_API_KEY` | Your AgentMail API key |
| `AGENTMAIL_INBOX` | Your AgentMail inbox (e.g., `inbox@agentmail.to`) |
| `AGENTMAIL_CONTACT_EMAIL` | Optional contact form recipient (defaults to inbox) |
**Note:** If environment variables are not configured, users will see the error message: "AgentMail Environment Variables are not configured in production. Please set AGENTMAIL_API_KEY and AGENTMAIL_INBOX." when attempting to send newsletters or use contact forms.
**Sending Newsletters:**
The admin UI supports two sending modes:
1. **Send Post**: Select a published blog post to send as a newsletter
2. **Write Email**: Compose a custom email with markdown formatting
Custom emails support markdown syntax:
- `# Heading` for headers
- `**bold**` and `*italic*` for emphasis
- `[link text](url)` for links
- `- item` for bullet lists
**CLI Commands:**
You can send newsletters via command line:
```bash
# Send a blog post to all subscribers
npm run newsletter:send <post-slug>
# Send weekly stats summary to your inbox
npm run newsletter:send:stats
```
Example:
```bash
npm run newsletter:send setup-guide
```
The `newsletter:send` command calls the `scheduleSendPostNewsletter` mutation directly and sends emails in the background. Check the Newsletter Admin page or recent sends to see results.
## API endpoints
| Endpoint | Description |
| ------------------------------ | --------------------------- |
| `/stats` | Real-time analytics |
| `/newsletter-admin` | Newsletter management UI |
| `/rss.xml` | RSS feed (descriptions) |
| `/rss-full.xml` | RSS feed (full content) |
| `/sitemap.xml` | XML sitemap |

View File

@@ -0,0 +1,242 @@
# How to use AgentMail with Markdown Sync
> Complete guide to setting up AgentMail for newsletters and contact forms in your markdown blog
---
Type: post
Date: 2025-12-27
Reading time: 5 min read
Tags: agentmail, newsletter, email, setup
---
AgentMail provides email infrastructure for your markdown blog, enabling newsletter subscriptions, contact forms, and automated email notifications. This guide covers setup, configuration, and usage.
## What is AgentMail
AgentMail is an email service designed for AI agents and developers. It handles email sending and receiving without OAuth or MFA requirements, making it ideal for automated workflows.
For this markdown blog framework, AgentMail powers:
- Newsletter subscriptions and sending
- Contact forms on posts and pages
- Developer notifications for new subscribers
- Weekly digest emails
- Weekly stats summaries
## Setup
### 1. Create an AgentMail account
Sign up at [agentmail.to](https://agentmail.to) and create an inbox. Your inbox address will look like `yourname@agentmail.to`.
### 2. Get your API key
In the AgentMail dashboard, navigate to API settings and copy your API key. You'll need this for Convex environment variables.
### 3. Configure Convex environment variables
In your Convex dashboard, go to Settings > Environment Variables and add:
| Variable | Description | Required |
|----------|-------------|----------|
| `AGENTMAIL_API_KEY` | Your AgentMail API key | Yes |
| `AGENTMAIL_INBOX` | Your inbox address (e.g., `markdown@agentmail.to`) | Yes |
| `AGENTMAIL_CONTACT_EMAIL` | Contact form recipient (defaults to inbox if not set) | No |
**Important:** Never hardcode email addresses in your code. Always use environment variables.
### 4. Enable features in siteConfig
Edit `src/config/siteConfig.ts` to enable newsletter and contact form features:
```typescript
newsletter: {
enabled: true,
showOnHomepage: true,
showOnBlogPage: true,
showOnPosts: true,
title: "Subscribe to the newsletter",
description: "Get updates delivered to your inbox",
},
contactForm: {
enabled: true,
title: "Get in touch",
description: "Send us a message",
},
```
## Newsletter features
### Subscriber management
The Newsletter Admin page at `/newsletter-admin` provides:
- View all subscribers with search and filters
- Delete subscribers
- Send blog posts as newsletters
- Write and send custom emails with markdown support
- View email statistics dashboard
- Track recent sends (last 10)
### Sending newsletters
**Via CLI:**
```bash
# Send a specific post to all subscribers
npm run newsletter:send setup-guide
# Send weekly stats summary to your inbox
npm run newsletter:send:stats
```
**Via Admin UI:**
1. Navigate to `/newsletter-admin`
2. Select "Send Post" or "Write Email" from the sidebar
3. Choose a post or compose a custom email
4. Click "Send Newsletter"
### Weekly digest
Automated weekly digest emails are sent every Sunday at 9:00 AM UTC. They include all posts published in the last 7 days.
Configure in `siteConfig.ts`:
```typescript
weeklyDigest: {
enabled: true,
},
```
### Developer notifications
Receive email notifications when:
- A new subscriber signs up
- Weekly stats summary (every Monday at 9:00 AM UTC)
Configure in `siteConfig.ts`:
```typescript
newsletterNotifications: {
enabled: true,
},
```
Notifications are sent to `AGENTMAIL_CONTACT_EMAIL` or `AGENTMAIL_INBOX` if contact email is not set.
## Contact forms
### Enable on posts and pages
Add `contactForm: true` to any post or page frontmatter:
```markdown
---
title: "Contact Us"
slug: "contact"
published: true
contactForm: true
---
Your page content here...
```
The contact form includes:
- Name field
- Email field
- Message field
Submissions are stored in Convex and sent via AgentMail to your configured recipient.
### Frontmatter options
| Field | Type | Description |
|-------|------|-------------|
| `contactForm` | boolean | Enable contact form on this post/page |
## Frontmatter options
### Newsletter signup
Control newsletter signup display per post/page:
```markdown
---
title: "My Post"
newsletter: true # Show signup (default: follows siteConfig)
---
```
Or hide it:
```markdown
---
title: "My Post"
newsletter: false # Hide signup even if enabled globally
---
```
## Environment variables
All AgentMail features require these Convex environment variables:
**Required:**
- `AGENTMAIL_API_KEY` - Your AgentMail API key
- `AGENTMAIL_INBOX` - Your inbox address
**Optional:**
- `AGENTMAIL_CONTACT_EMAIL` - Contact form recipient (defaults to inbox)
**Note:** If environment variables are not configured, users will see: "AgentMail Environment Variables are not configured in production. Please set AGENTMAIL_API_KEY and AGENTMAIL_INBOX."
## CLI commands
| Command | Description |
|---------|-------------|
| `npm run newsletter:send <slug>` | Send a blog post to all subscribers |
| `npm run newsletter:send:stats` | Send weekly stats summary to your inbox |
## Troubleshooting
**Emails not sending:**
1. Verify `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` are set in Convex dashboard
2. Check Convex function logs for error messages
3. Ensure your inbox is active in AgentMail dashboard
**Contact form not appearing:**
1. Verify `contactForm: true` is in frontmatter
2. Check `siteConfig.contactForm.enabled` is `true`
3. Run `npm run sync` to sync frontmatter changes
**Newsletter Admin not accessible:**
1. Verify `siteConfig.newsletterAdmin.enabled` is `true`
2. Navigate to `/newsletter-admin` directly (hidden from nav by default)
## Resources
- [AgentMail Documentation](https://docs.agentmail.to)
- [AgentMail Quickstart](https://docs.agentmail.to/quickstart)
- [AgentMail Sending & Receiving Email](https://docs.agentmail.to/sending-receiving-email)
- [AgentMail Inboxes](https://docs.agentmail.to/inboxes)
## Summary
AgentMail integration provides:
- Newsletter subscriptions and sending
- Contact forms on any post or page
- Automated weekly digests
- Developer notifications
- Admin UI for subscriber management
- CLI tools for sending newsletters and stats
All features use Convex environment variables for configuration. No hardcoded emails in your codebase.

View File

@@ -0,0 +1,66 @@
# How to use Firecrawl
> Import external articles as markdown posts using Firecrawl. Get your API key and configure environment variables for local imports and AI chat.
---
Type: post
Date: 2025-01-20
Reading time: 2 min read
Tags: tutorial, firecrawl, import
---
# How to use Firecrawl
You found an article you want to republish or reference. Copying content manually takes time. Firecrawl scrapes web pages and converts them to markdown automatically.
## What it is
Firecrawl is a web scraping service that turns any URL into clean markdown. This app uses it in two places: the import script for creating draft posts, and the AI chat feature for fetching page content.
## Who it's for
Developers who want to import external articles without manual copying. If you republish content or need to reference external sources, Firecrawl saves time.
## The problem it solves
Manually copying content from websites is slow. You copy text, fix formatting, add frontmatter, and handle images. Firecrawl does this automatically.
## How it works
The import script scrapes a URL, extracts the title and description, converts HTML to markdown, and creates a draft post in `content/blog/`. The AI chat feature uses Firecrawl to fetch page content when you share URLs in conversations.
## How to try it
**Step 1: Get your API key**
Visit [firecrawl.dev](https://firecrawl.dev) and sign up. Copy your API key. It starts with `fc-`.
**Step 2: Set up local imports**
Add the key to `.env.local` in your project root:
```
FIRECRAWL_API_KEY=fc-your-api-key-here
```
Now you can import articles:
```bash
npm run import https://example.com/article
```
This creates a draft post in `content/blog/`. Review it, set `published: true`, then run `npm run sync`.
**Step 3: Enable AI chat scraping**
If you use the AI chat feature, set the same key in your Convex Dashboard:
1. Go to [dashboard.convex.dev](https://dashboard.convex.dev)
2. Select your project
3. Open Settings > Environment Variables
4. Add `FIRECRAWL_API_KEY` with your key value
5. Deploy: `npx convex deploy`
The AI chat can now fetch content from URLs you share.
That's it. One API key, two places to set it, and you're done.

View File

@@ -2,8 +2,10 @@
This is the homepage index of all published content.
## Blog Posts (12)
## Blog Posts (14)
- **[How to use AgentMail with Markdown Sync](/raw/how-to-use-agentmail.md)** - Complete guide to setting up AgentMail for newsletters and contact forms in your markdown blog
- Date: 2025-12-27 | Reading time: 5 min read | Tags: agentmail, newsletter, email, setup
- **[Happy holidays and thank you](/raw/happy-holidays-2025.md)** - A quick note of thanks for stars, forks, and feedback. More AI-first publishing features coming in 2026.
- Date: 2025-12-25 | Reading time: 2 min read | Tags: updates, community, ai
- **[Netlify edge functions blocking AI crawlers from static files](/raw/netlify-edge-excludedpath-ai-crawlers.md)** - Why excludedPath in netlify.toml isn't preventing edge functions from intercepting /raw/* requests, and how ChatGPT and Perplexity get blocked while Claude works.
@@ -26,19 +28,22 @@ This is the homepage index of all published content.
- Date: 2025-12-14 | Reading time: 8 min read | Tags: convex, netlify, tutorial, deployment
- **[Using Images in Blog Posts](/raw/using-images-in-posts.md)** - Learn how to add header images, inline images, and Open Graph images to your markdown posts.
- Date: 2025-12-14 | Reading time: 4 min read | Tags: images, tutorial, markdown, open-graph
- **[How to use Firecrawl](/raw/how-to-use-firecrawl.md)** - Import external articles as markdown posts using Firecrawl. Get your API key and configure environment variables for local imports and AI chat.
- Date: 2025-01-20 | Reading time: 2 min read | Tags: tutorial, firecrawl, import
- **[Git commit message best practices](/raw/git-commit-message-best-practices.md)** - A guide to writing clear, consistent commit messages that help your team understand changes and generate better changelogs.
- Date: 2025-01-17 | Reading time: 5 min read | Tags: git, development, best-practices, workflow
## Pages (5)
## Pages (6)
- **[Docs](/raw/docs.md)**
- **[About](/raw/about.md)** - An open-source publishing framework built for AI agents and developers to ship websites, docs, or blogs..
- **[Projects](/raw/projects.md)**
- **[Contact](/raw/contact.md)**
- **[Changelog](/raw/changelog.md)**
- **[Newsletter](/raw/newsletter.md)**
---
**Total Content:** 12 posts, 5 pages
**Total Content:** 14 posts, 6 pages
All content is available as raw markdown files at `/raw/{slug}.md`

28
public/raw/newsletter.md Normal file
View File

@@ -0,0 +1,28 @@
# Newsletter
---
Type: page
Date: 2025-12-27
---
# Newsletter
Stay updated with the latest posts and updates from the markdown sync framework.
## What you will get
When you subscribe, you will receive:
- Notifications when new blog posts are published
- Updates about new features and improvements
- Tips and tricks for getting the most out of markdown sync
## Subscribe
Use the form below to subscribe to our newsletter. We respect your privacy and you can unsubscribe at any time.
## Privacy
We only use your email address to send you newsletter updates. We never share your email with third parties or use it for any other purpose.
To unsubscribe, click the unsubscribe link at the bottom of any newsletter email.

View File

@@ -56,6 +56,7 @@ This guide walks you through forking [this markdown framework](https://github.co
- [Visitor Map](#visitor-map)
- [Logo Gallery](#logo-gallery)
- [Blog page](#blog-page)
- [Hardcoded Navigation Items](#hardcoded-navigation-items)
- [Scroll-to-top button](#scroll-to-top-button)
- [Change the Default Theme](#change-the-default-theme)
- [Change the Font](#change-the-font)
@@ -77,6 +78,7 @@ This guide walks you through forking [this markdown framework](https://github.co
- [Build failures on Netlify](#build-failures-on-netlify)
- [Project Structure](#project-structure)
- [Write Page](#write-page)
- [AI Agent chat](#ai-agent-chat)
- [Next Steps](#next-steps)
## Prerequisites
@@ -181,6 +183,7 @@ export default defineSchema({
Blog posts live in `content/blog/` as markdown files. Sync them to Convex:
**Development:**
```bash
npm run sync # Sync markdown content
npm run sync:discovery # Update discovery files (AGENTS.md, llms.txt)
@@ -188,6 +191,7 @@ npm run sync:all # Sync content + discovery files together
```
**Production:**
```bash
npm run sync:prod # Sync markdown content
npm run sync:discovery:prod # Update discovery files
@@ -324,21 +328,21 @@ Your markdown content here...
### Frontmatter Fields
| Field | Required | Description |
| --------------- | -------- | ----------------------------------------- |
| `title` | Yes | Post title |
| `description` | Yes | Short description for SEO |
| `date` | Yes | Publication date (YYYY-MM-DD) |
| `slug` | Yes | URL path (must be unique) |
| `published` | Yes | Set to `true` to publish |
| `tags` | Yes | Array of topic tags |
| `readTime` | No | Estimated reading time |
| `image` | No | Header/Open Graph image URL |
| `excerpt` | No | Short excerpt for card view |
| `featured` | No | Set `true` to show in featured section |
| `featuredOrder` | No | Order in featured section (lower = first) |
| `authorName` | No | Author display name shown next to date |
| `authorImage` | No | Round author avatar image URL |
| Field | Required | Description |
| --------------- | -------- | ----------------------------------------------------------------------------- |
| `title` | Yes | Post title |
| `description` | Yes | Short description for SEO |
| `date` | Yes | Publication date (YYYY-MM-DD) |
| `slug` | Yes | URL path (must be unique) |
| `published` | Yes | Set to `true` to publish |
| `tags` | Yes | Array of topic tags |
| `readTime` | No | Estimated reading time |
| `image` | No | Header/Open Graph image URL |
| `excerpt` | No | Short excerpt for card view |
| `featured` | No | Set `true` to show in featured section |
| `featuredOrder` | No | Order in featured section (lower = first) |
| `authorName` | No | Author display name shown next to date |
| `authorImage` | No | Round author avatar image URL |
| `rightSidebar` | No | Enable right sidebar with CopyPageDropdown (opt-in, requires explicit `true`) |
### How Frontmatter Works
@@ -403,6 +407,7 @@ The `npm run sync` command only syncs markdown text content. Images are deployed
After adding or editing posts, sync to Convex.
**Development sync:**
```bash
npm run sync # Sync markdown content
npm run sync:discovery # Update discovery files
@@ -420,6 +425,7 @@ VITE_CONVEX_URL=https://your-prod-deployment.convex.cloud
Get your production URL from the [Convex Dashboard](https://dashboard.convex.dev) by selecting your project and switching to the Production deployment.
Then sync:
```bash
npm run sync:prod # Sync markdown content
npm run sync:discovery:prod # Update discovery files
@@ -437,17 +443,17 @@ Both files are gitignored. Each developer creates their own local environment fi
### When to Sync vs Deploy
| What you're changing | Command | Timing |
| -------------------------------- | -------------------------- | -------------------- |
| Blog posts in `content/blog/` | `npm run sync` | Instant (no rebuild) |
| Pages in `content/pages/` | `npm run sync` | Instant (no rebuild) |
| Featured items (via frontmatter) | `npm run sync` | Instant (no rebuild) |
| What you're changing | Command | Timing |
| -------------------------------- | -------------------------- | ----------------------- |
| Blog posts in `content/blog/` | `npm run sync` | Instant (no rebuild) |
| Pages in `content/pages/` | `npm run sync` | Instant (no rebuild) |
| Featured items (via frontmatter) | `npm run sync` | Instant (no rebuild) |
| Site config changes | `npm run sync:discovery` | Updates discovery files |
| Import external URL | `npm run import` then sync | Instant (no rebuild) |
| Images in `public/images/` | Git commit + push | Requires rebuild |
| `siteConfig` in `Home.tsx` | Redeploy | Requires rebuild |
| Logo gallery config | Redeploy | Requires rebuild |
| React components/styles | Redeploy | Requires rebuild |
| Import external URL | `npm run import` then sync | Instant (no rebuild) |
| Images in `public/images/` | Git commit + push | Requires rebuild |
| `siteConfig` in `Home.tsx` | Redeploy | Requires rebuild |
| Logo gallery config | Redeploy | Requires rebuild |
| React components/styles | Redeploy | Requires rebuild |
**Markdown content** syncs instantly via Convex. **Images and source code** require pushing to GitHub for Netlify to rebuild.
@@ -965,15 +971,12 @@ body {
serif;
/* Monospace */
font-family:
"IBM Plex Mono",
"Liberation Mono",
ui-monospace,
monospace;
font-family: "IBM Plex Mono", "Liberation Mono", ui-monospace, monospace;
}
```
Available font options:
- `serif`: New York serif font (default)
- `sans`: System sans-serif fonts
- `monospace`: IBM Plex Mono monospace font
@@ -1097,6 +1100,49 @@ How it works:
- A cron job cleans up stale sessions every 5 minutes
- No personal data is stored (only anonymous UUIDs)
## Newsletter Admin
A newsletter management interface is available at `/newsletter-admin`. Use it to view subscribers, send newsletters, and compose custom emails.
**Features:**
- View and search all subscribers with filtering options (search bar in header)
- Delete subscribers from the admin UI
- Send published blog posts as newsletters
- Write custom emails using markdown formatting
- View recent newsletter sends (last 10, tracks both posts and custom emails)
- Email statistics dashboard with comprehensive metrics
**Setup:**
1. Enable in `src/config/siteConfig.ts`:
```typescript
newsletterAdmin: {
enabled: true,
showInNav: false, // Keep hidden, access via direct URL
},
```
2. Set environment variables in Convex Dashboard:
| Variable | Description |
| ------------------------- | ------------------------------------ |
| `AGENTMAIL_API_KEY` | Your AgentMail API key |
| `AGENTMAIL_INBOX` | Your AgentMail inbox address |
| `AGENTMAIL_CONTACT_EMAIL` | Optional recipient for contact forms |
**Important:** If environment variables are not configured, users will see an error message when attempting to use newsletter or contact form features: "AgentMail Environment Variables are not configured in production. Please set AGENTMAIL_API_KEY and AGENTMAIL_INBOX."
**Sending newsletters:**
Two modes are available:
1. **Send Post**: Select a blog post to send to all active subscribers
2. **Write Email**: Compose custom content with markdown support
The admin UI shows send results and provides CLI commands as alternatives.
## Mobile Navigation
On mobile and tablet screens (under 768px), a hamburger menu provides navigation. The menu slides out from the left with keyboard navigation (Escape to close) and a focus trap for accessibility. It auto-closes when you navigate to a new route.
@@ -1105,23 +1151,23 @@ On mobile and tablet screens (under 768px), a hamburger menu provides navigation
Each post and page includes a share dropdown with options for AI tools:
| Option | Description |
| -------------------- | ------------------------------------------------- |
| Copy page | Copies formatted markdown to clipboard |
| Open in ChatGPT | Opens ChatGPT with raw markdown URL |
| Open in Claude | Opens Claude with raw markdown URL |
| Open in Perplexity | Opens Perplexity with raw markdown URL |
| View as Markdown | Opens raw `.md` file in new tab |
| Download as SKILL.md | Downloads skill file for AI agent training |
| Option | Description |
| -------------------- | ------------------------------------------ |
| Copy page | Copies formatted markdown to clipboard |
| Open in ChatGPT | Opens ChatGPT with raw markdown URL |
| Open in Claude | Opens Claude with raw markdown URL |
| Open in Perplexity | Opens Perplexity with raw markdown URL |
| View as Markdown | Opens raw `.md` file in new tab |
| Download as SKILL.md | Downloads skill file for AI agent training |
**Git push required for AI links:** The "Open in ChatGPT," "Open in Claude," and "Open in Perplexity" options use GitHub raw URLs to fetch content. For these to work, your content must be pushed to GitHub with `git push`. The `npm run sync` command syncs content to Convex for your live site, but AI services fetch directly from GitHub.
| What you want | Command needed |
| ------------------------------------ | ------------------------------ |
| Content visible on your site | `npm run sync` or `sync:prod` |
| What you want | Command needed |
| ------------------------------------ | ------------------------------------------------- |
| Content visible on your site | `npm run sync` or `sync:prod` |
| Discovery files updated | `npm run sync:discovery` or `sync:discovery:prod` |
| AI links (ChatGPT/Claude/Perplexity) | `git push` to GitHub |
| Both content and discovery | `npm run sync:all` or `sync:all:prod` |
| AI links (ChatGPT/Claude/Perplexity) | `git push` to GitHub |
| Both content and discovery | `npm run sync:all` or `sync:all:prod` |
**Download as SKILL.md** formats the content as an Anthropic Agent Skills file with metadata, triggers, and instructions sections.
@@ -1319,7 +1365,7 @@ Enable Agent in the right sidebar on individual posts or pages using the `aiChat
---
title: "My Post"
rightSidebar: true
aiChat: true # Enable Agent in right sidebar
aiChat: true # Enable Agent in right sidebar
---
```