From 6e8d1b11388c74ed11c8c7dbdf0934af871aed2a Mon Sep 17 00:00:00 2001 From: Wayne Sutton Date: Sun, 14 Dec 2025 10:27:27 -0800 Subject: [PATCH] first commit --- README.md | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..20bcc95 --- /dev/null +++ b/README.md @@ -0,0 +1,273 @@ +# Markdown Site + +A minimalist markdown site built with React, Convex, and Vite. Optimized for SEO, AI agents, and LLM discovery. + +## Features + +- Markdown-based blog posts with frontmatter +- Syntax highlighting for code blocks +- Four theme options: Dark, Light, Tan (default), Cloud +- Real-time data with Convex +- Fully responsive design + +### SEO and Discovery + +- RSS feeds at `/rss.xml` and `/rss-full.xml` (with full content) +- Dynamic sitemap at `/sitemap.xml` +- JSON-LD structured data for Google rich results +- Open Graph and Twitter Card meta tags +- `robots.txt` with AI crawler rules +- `llms.txt` for AI agent discovery + +### AI and LLM Access + +- `/api/posts` - JSON list of all posts for agents +- `/api/post?slug=xxx` - Single post JSON or markdown +- `/rss-full.xml` - Full content RSS for LLM ingestion +- Copy Page dropdown for sharing to ChatGPT, Claude, Cursor, VS Code + +## Getting Started + +### Prerequisites + +- Node.js 18 or higher +- A Convex account + +### Setup + +1. Install dependencies: + +```bash +npm install +``` + +2. Initialize Convex: + +```bash +npx convex dev +``` + +This will create your Convex project and generate the `.env.local` file. + +3. Start the development server: + +```bash +npm run dev +``` + +4. Open http://localhost:5173 + +## Writing Blog Posts + +Create markdown files in `content/blog/` with frontmatter: + +## Static Pages (Optional) + +Create optional pages like About, Projects, or Contact in `content/pages/`: + +```markdown +--- +title: "About" +slug: "about" +published: true +order: 1 +--- + +Your page content here... +``` + +Pages appear as navigation links in the top right, next to the theme toggle. The `order` field controls display order (lower numbers first). + +```markdown +--- +title: "Your Post Title" +description: "A brief description" +date: "2025-01-15" +slug: "your-post-slug" +published: true +tags: ["tag1", "tag2"] +readTime: "5 min read" +image: "/images/my-header.png" +--- + +Your markdown content here... +``` + +## Images + +### Open Graph Images + +Add an `image` field to frontmatter for social media previews: + +```yaml +image: "/images/my-header.png" +``` + +Recommended dimensions: 1200x630 pixels. Images can be local (`/images/...`) or external URLs. + +### Inline Images + +Add images in markdown content: + +```markdown +![Alt text description](/images/screenshot.png) +``` + +Place image files in `public/images/`. The alt text displays as a caption. + +### Site Logo + +Edit `src/pages/Home.tsx` to set your site logo: + +```typescript +const siteConfig = { + logo: "/images/logo.svg", // Set to null to hide + // ... +}; +``` + +Replace `public/images/logo.svg` with your own logo file. + +### Favicon + +Replace `public/favicon.svg` with your own icon. The default is a rounded square with the letter "m". Edit the SVG to change the letter or style. + +### Default Open Graph Image + +The default OG image is used when posts do not have an `image` field. Replace `public/images/og-default.svg` with your own image (1200x630 recommended). + +Update the reference in `src/pages/Post.tsx`: + +```typescript +const DEFAULT_OG_IMAGE = "/images/og-default.svg"; +``` + +## Syncing Posts + +Posts are synced to Convex at build time. To manually sync: + +```bash +npm run sync +``` + +## Deployment + +### Netlify + +1. Connect your repository to Netlify +2. Set environment variables: + - `VITE_CONVEX_URL` - Your Convex deployment URL +3. Update `netlify.toml` with your Convex HTTP URL (replace `YOUR_CONVEX_DEPLOYMENT`) +4. Deploy with: + +```bash +npm run deploy +``` + +## Project Structure + +``` +personal-blog/ +├── content/blog/ # Markdown blog posts +├── convex/ # Convex backend +│ ├── http.ts # HTTP endpoints (sitemap, API, RSS) +│ ├── posts.ts # Post queries and mutations +│ ├── rss.ts # RSS feed generation +│ └── schema.ts # Database schema +├── netlify/ # Netlify edge functions +├── public/ # Static assets +│ ├── images/ # Blog images and OG images +│ ├── robots.txt # Crawler rules +│ └── llms.txt # AI agent discovery +├── scripts/ # Build scripts +└── src/ + ├── components/ # React components + ├── context/ # Theme context + ├── pages/ # Page components + └── styles/ # Global CSS +``` + +## Tech Stack + +- React 18 +- TypeScript +- Vite +- Convex +- react-markdown +- react-syntax-highlighter +- date-fns +- lucide-react +- Netlify + +## API Endpoints + +| Endpoint | Description | +| ------------------------------ | ------------------------------- | +| `/rss.xml` | RSS feed with post descriptions | +| `/rss-full.xml` | RSS feed with full post content | +| `/sitemap.xml` | Dynamic XML sitemap | +| `/api/posts` | JSON list of all posts | +| `/api/post?slug=xxx` | Single post as JSON | +| `/api/post?slug=xxx&format=md` | Single post as markdown | +| `/meta/post?slug=xxx` | Open Graph HTML for crawlers | + +## How Blog Post Slugs Work + +Slugs are defined in the frontmatter of each markdown file: + +```markdown +--- +slug: "my-post-slug" +--- +``` + +The slug becomes the URL path: `yourdomain.com/my-post-slug` + +Rules: + +- Slugs must be unique across all posts +- Use lowercase letters, numbers, and hyphens +- The sync script reads the `slug` field from frontmatter +- Posts are queried by slug using a Convex index + +## Theme Configuration + +The default theme is Tan. Users can cycle through themes using the toggle: + +- Dark (Moon icon) +- Light (Sun icon) +- Tan (Half icon) - default +- Cloud (Cloud icon) + +To change the default theme, edit `src/context/ThemeContext.tsx`: + +```typescript +const DEFAULT_THEME: Theme = "tan"; // Change to "dark", "light", or "cloud" +``` + +## Font Configuration + +The blog uses a serif font (New York) by default. To switch fonts, edit `src/styles/global.css`: + +```css +body { + /* Sans-serif option */ + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, sans-serif; + + /* Serif option (default) */ + font-family: + "New York", + -apple-system-ui-serif, + ui-serif, + Georgia, + Cambria, + "Times New Roman", + Times, + serif; +} +``` + +Replace the `font-family` property with your preferred font stack. +# markdown-site