# Documentation --- Type: page Date: 2026-01-06 --- ## Getting started Reference documentation for setting up, customizing, and deploying this markdown framework. **How publishing works:** Write posts in markdown, run `npm run sync` for development or `npm run sync:prod` for production, and they appear on your live site immediately. No rebuild or redeploy needed. Convex handles real-time data sync, so connected browsers update automatically. **Sync commands:** **Development:** - npm run sync - Sync markdown content - npm run sync:discovery - Update discovery files (AGENTS.md, llms.txt) - npm run sync:all - Sync content + discovery files together **Production:** - npm run sync:prod - Sync markdown content - npm run sync:discovery:prod - Update discovery files - npm run sync:all:prod - Sync content + discovery files together ## Quick start ```bash git clone https://github.com/waynesutton/markdown-site.git cd markdown-site npm install npx convex dev npm run sync # development npm run sync:prod # production npm run dev ``` Open `http://localhost:5173` to view locally. ## Requirements - Node.js 18+ - Convex account (free at convex.dev) - Netlify account (free at netlify.com) ## Project structure ``` markdown-site/ ├── content/ │ ├── blog/ # Blog posts (.md) │ └── pages/ # Static pages (.md) ├── convex/ │ ├── schema.ts # Database schema │ ├── posts.ts # Post queries/mutations │ ├── pages.ts # Page queries/mutations │ ├── http.ts # API endpoints │ └── rss.ts # RSS generation ├── netlify/ │ └── edge-functions/ # Netlify edge functions │ ├── rss.ts # RSS proxy │ ├── sitemap.ts # Sitemap proxy │ ├── api.ts # API proxy │ └── botMeta.ts # OG crawler detection ├── src/ │ ├── components/ # React components │ ├── context/ # Theme context │ ├── pages/ # Route components │ └── styles/ # CSS ├── public/ │ ├── images/ # Static images │ ├── raw/ # Generated raw markdown files │ ├── robots.txt # Crawler rules │ └── llms.txt # AI discovery └── netlify.toml # Deployment config ``` ## 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. **Features:** - Real-time results as you type - Keyboard navigation (arrow keys, Enter, Escape) - Result snippets with context around matches - Distinguishes between posts and pages - Works with all four themes Search uses Convex full text search indexes. No configuration needed. ## Copy Page dropdown Each post and page includes a share dropdown with options: | 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 | **Raw markdown URLs:** AI service links use GitHub raw URLs to fetch markdown content. This bypasses Netlify edge functions and provides reliable access for AI services. **Git push required for AI links:** The "Open in ChatGPT," "Open in Claude," and "Open in Perplexity" options use GitHub raw URLs. For these to work, you must push your content 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` | | 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` | **Download as SKILL.md:** Downloads the content formatted as an Anthropic Agent Skills file with metadata, triggers, and instructions sections. ## Homepage post limit Limit the number of posts shown on the homepage. Configure in `src/config/siteConfig.ts`: ```typescript postsDisplay: { showOnHome: true, homePostsLimit: 5, // Limit to 5 most recent posts (undefined = show all) homePostsReadMore: { enabled: true, text: "Read more blog posts", link: "/blog", }, }, ``` When posts are limited, an optional "read more" link appears below the list. Only shows when there are more posts than the limit. ## Real-time stats The `/stats` page displays real-time analytics: - Active visitors (with per-page breakdown) - Total page views - Unique visitors - Views by page (sorted by count) All stats update automatically via Convex subscriptions. **Configuration:** Enable or disable in `src/config/siteConfig.ts`: ```typescript statsPage: { enabled: true, // Enable /stats route showInNav: false, // Hide from navigation (access via direct URL) }, ``` ## 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 # 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 | | `/api/posts` | JSON post list | | `/api/post?slug=xxx` | Single post (JSON) | | `/api/post?slug=xxx&format=md` | Single post (markdown) | | `/api/export` | All posts with full content | | `/raw/{slug}.md` | Static raw markdown file | | `/.well-known/ai-plugin.json` | AI plugin manifest | | `/openapi.yaml` | OpenAPI 3.0 specification | | `/llms.txt` | AI agent discovery | ## MCP Server The site includes an HTTP-based Model Context Protocol (MCP) server for AI tool integration. It allows AI assistants like Cursor and Claude Desktop to access blog content programmatically. **Endpoint:** `https://www.markdown.fast/mcp` **Features:** - 24/7 availability via Netlify Edge Functions - Public access with rate limiting (50 req/min per IP) - Optional API key for higher limits (1000 req/min) - Read-only access to content **Available tools:** | Tool | Description | | ---------------- | ------------------------------------------------ | | `list_posts` | Get all published blog posts with metadata | | `get_post` | Get a single post by slug with full content | | `list_pages` | Get all published pages | | `get_page` | Get a single page by slug with full content | | `get_homepage` | Get homepage data with featured and recent posts | | `search_content` | Full text search across posts and pages | | `export_all` | Batch export all content | **Cursor configuration:** Add to `~/.cursor/mcp.json`: ```json { "mcpServers": { "markdown-fast": { "url": "https://www.markdown.fast/mcp" } } } ``` **For forks:** The MCP server automatically connects to your Convex deployment. Ensure `VITE_CONVEX_URL` is set in Netlify. Optionally set `MCP_API_KEY` for authenticated access with higher rate limits. See [How to Use the MCP Server](/how-to-use-mcp-server) for full documentation. ## Raw markdown files When you run `npm run sync` (development) or `npm run sync:prod` (production), static `.md` files are generated in `public/raw/` for each published post and page. Use `npm run sync:all` or `npm run sync:all:prod` to sync content and update discovery files together. **Access pattern:** `/raw/{slug}.md` **Examples:** - `/raw/setup-guide.md` - `/raw/about.md` These files include a metadata header with type, date, reading time, and tags. Access via the "View as Markdown" option in the Copy Page dropdown. ## Markdown formatting For complete markdown syntax examples including tables, collapsible sections, code blocks, lists, links, images, and all formatting options, see [Writing Markdown with Code Examples](/markdown-with-code-examples). **Quick reference:** - **Tables:** Render with GitHub-style formatting, clean borders, mobile responsive - **Collapsible sections:** Use HTML `
` and `` tags for expandable content - **Code blocks:** Support syntax highlighting for TypeScript, JavaScript, bash, JSON, and more - **Images:** Place in `public/images/` and reference with absolute paths All markdown features work with all four themes and are styled to match the site design. ## Import external content Use Firecrawl to import articles from external URLs. See [How to Use Firecrawl](/how-to-use-firecrawl) for detailed setup instructions. ```bash npm run import https://example.com/article ``` **Quick setup:** 1. Get an API key from firecrawl.dev 2. Add `FIRECRAWL_API_KEY=fc-xxx` to `.env.local` The import command creates local markdown files only. It does not interact with Convex directly. **After importing:** - `npm run sync` to push to development - `npm run sync:prod` to push to production - Use `npm run sync:all` or `npm run sync:all:prod` to sync content and update discovery files together There is no `npm run import:prod` because import creates local files and sync handles the target environment. Imported posts are drafts (`published: false`). Review, edit, set `published: true`, then sync.