mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 04:09:14 +00:00
feature: new dashboard workos auth for dashboard login, dashboard optional in site config, sync server for dashboard, workos and dashboard docs updated
This commit is contained in:
315
content/blog/how-to-setup-workos.md
Normal file
315
content/blog/how-to-setup-workos.md
Normal file
@@ -0,0 +1,315 @@
|
||||
---
|
||||
title: "How to setup WorkOS"
|
||||
description: "Step-by-step guide to configure WorkOS AuthKit authentication for your markdown blog dashboard. WorkOS is optional and can be enabled in siteConfig.ts."
|
||||
date: "2025-12-29"
|
||||
slug: "how-to-setup-workos"
|
||||
published: true
|
||||
tags: ["workos", "authentication", "tutorial", "dashboard"]
|
||||
readTime: "10 min read"
|
||||
featured: true
|
||||
featuredOrder: 3
|
||||
excerpt: "Complete guide to setting up WorkOS AuthKit authentication for your dashboard. WorkOS is optional and can be configured in siteConfig.ts."
|
||||
---
|
||||
|
||||
# How to setup WorkOS
|
||||
|
||||
WorkOS AuthKit adds authentication to your markdown blog dashboard. It's optional—you can use the dashboard without WorkOS, or enable authentication for production sites.
|
||||
|
||||
## Overview
|
||||
|
||||
WorkOS AuthKit provides:
|
||||
|
||||
- Password authentication
|
||||
- Social login (Google, GitHub, etc.)
|
||||
- SSO support
|
||||
- User management
|
||||
- Session handling
|
||||
|
||||
The dashboard at `/dashboard` can work with or without WorkOS. Configure it in `siteConfig.ts`:
|
||||
|
||||
```typescript
|
||||
dashboard: {
|
||||
enabled: true,
|
||||
requireAuth: false, // Set to true to require WorkOS authentication
|
||||
},
|
||||
```
|
||||
|
||||
When `requireAuth` is `false`, the dashboard is open access. When `requireAuth` is `true` and WorkOS is configured, users must log in to access the dashboard.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, make sure you have:
|
||||
|
||||
- Node.js 18 or higher
|
||||
- A working markdown blog project
|
||||
- A Convex account and project set up
|
||||
- Your Convex development server running (`npx convex dev`)
|
||||
|
||||
## Step 1: Create a WorkOS account
|
||||
|
||||
### Sign up
|
||||
|
||||
1. Go to [workos.com/sign-up](https://signin.workos.com/sign-up)
|
||||
2. Create a free account with your email
|
||||
3. Verify your email address
|
||||
|
||||
### Set up AuthKit
|
||||
|
||||
1. Log into the [WorkOS Dashboard](https://dashboard.workos.com)
|
||||
2. Navigate to **Authentication** → **AuthKit**
|
||||
3. Click the **Set up AuthKit** button
|
||||
4. Select **"Use AuthKit's customizable hosted UI"**
|
||||
5. Click **Begin setup**
|
||||
|
||||
### Configure redirect URI
|
||||
|
||||
During the AuthKit setup wizard, you'll reach step 4: **"Add default redirect endpoint URI"**
|
||||
|
||||
Enter this for local development:
|
||||
```
|
||||
http://localhost:5173/callback
|
||||
```
|
||||
|
||||
After a user logs in, WorkOS redirects them back to this URL with an authorization code. Your app exchanges this code for user information.
|
||||
|
||||
### Copy your credentials
|
||||
|
||||
1. Go to [dashboard.workos.com/get-started](https://dashboard.workos.com/get-started)
|
||||
2. Under **Quick start**, find and copy:
|
||||
- **Client ID** (looks like `client_01XXXXXXXXXXXXXXXXX`)
|
||||
|
||||
Save this somewhere safe—you'll need it shortly.
|
||||
|
||||
## Step 2: Configure WorkOS dashboard
|
||||
|
||||
### Enable CORS
|
||||
|
||||
For the React SDK to work, you need to allow your app's domain:
|
||||
|
||||
1. Go to **Authentication** → **Sessions** in the WorkOS Dashboard
|
||||
2. Find **Cross-Origin Resource Sharing (CORS)**
|
||||
3. Click **Manage**
|
||||
4. Add your development URL: `http://localhost:5173`
|
||||
5. Click **Save**
|
||||
|
||||
When you deploy to production (e.g., Netlify), add your production domain here too (e.g., `https://yoursite.netlify.app`).
|
||||
|
||||
### Verify redirect URI
|
||||
|
||||
1. Go to **Redirects** in the WorkOS Dashboard
|
||||
2. Confirm `http://localhost:5173/callback` is listed
|
||||
3. If not, add it by clicking **Add redirect**
|
||||
|
||||
## Step 3: Install dependencies
|
||||
|
||||
Open your terminal in the project folder and install the required packages:
|
||||
|
||||
```bash
|
||||
npm install @workos-inc/authkit-react @convex-dev/workos
|
||||
```
|
||||
|
||||
**What these packages do:**
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| `@workos-inc/authkit-react` | WorkOS React SDK for handling login/logout |
|
||||
| `@convex-dev/workos` | Bridges WorkOS auth with Convex backend |
|
||||
|
||||
## Step 4: Add environment variables
|
||||
|
||||
### Update `.env.local`
|
||||
|
||||
Open your `.env.local` file (in the project root) and add these lines:
|
||||
|
||||
```env
|
||||
# Existing Convex URL (should already be here)
|
||||
VITE_CONVEX_URL=https://your-deployment.convex.cloud
|
||||
|
||||
# WorkOS AuthKit Configuration (add these)
|
||||
VITE_WORKOS_CLIENT_ID=client_01XXXXXXXXXXXXXXXXX
|
||||
VITE_WORKOS_REDIRECT_URI=http://localhost:5173/callback
|
||||
```
|
||||
|
||||
Replace `client_01XXXXXXXXXXXXXXXXX` with your actual Client ID from the WorkOS Dashboard.
|
||||
|
||||
Vite only exposes environment variables that start with `VITE_` to the browser.
|
||||
|
||||
### Add to `.gitignore`
|
||||
|
||||
Make sure `.env.local` is in your `.gitignore` to avoid committing secrets:
|
||||
|
||||
```
|
||||
.env.local
|
||||
.env.production.local
|
||||
```
|
||||
|
||||
## Step 5: Configure Convex auth
|
||||
|
||||
Create a new file to tell Convex how to validate WorkOS tokens.
|
||||
|
||||
### Create `convex/auth.config.ts`
|
||||
|
||||
Create a new file at `convex/auth.config.ts`:
|
||||
|
||||
```typescript
|
||||
// convex/auth.config.ts
|
||||
const clientId = process.env.WORKOS_CLIENT_ID;
|
||||
|
||||
const authConfig = {
|
||||
providers: [
|
||||
{
|
||||
type: "customJwt",
|
||||
issuer: "https://api.workos.com/",
|
||||
algorithm: "RS256",
|
||||
applicationID: clientId,
|
||||
jwks: `https://api.workos.com/sso/jwks/${clientId}`,
|
||||
},
|
||||
{
|
||||
type: "customJwt",
|
||||
issuer: `https://api.workos.com/user_management/${clientId}`,
|
||||
algorithm: "RS256",
|
||||
jwks: `https://api.workos.com/sso/jwks/${clientId}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default authConfig;
|
||||
```
|
||||
|
||||
### Add environment variable to Convex
|
||||
|
||||
The Convex backend needs the Client ID too:
|
||||
|
||||
1. Run `npx convex dev` if not already running
|
||||
2. You'll see an error with a link—click it
|
||||
3. It takes you to the Convex Dashboard environment variables page
|
||||
4. Add a new variable:
|
||||
- **Name**: `WORKOS_CLIENT_ID`
|
||||
- **Value**: Your WorkOS Client ID (e.g., `client_01XXXXXXXXXXXXXXXXX`)
|
||||
5. Save
|
||||
|
||||
After saving, `npx convex dev` should show "Convex functions ready."
|
||||
|
||||
## Step 6: Update site configuration
|
||||
|
||||
Enable authentication in your site config:
|
||||
|
||||
```typescript
|
||||
// src/config/siteConfig.ts
|
||||
dashboard: {
|
||||
enabled: true,
|
||||
requireAuth: true, // Set to true to require WorkOS authentication
|
||||
},
|
||||
```
|
||||
|
||||
When `requireAuth` is `true` and WorkOS is configured, the dashboard requires login. When `requireAuth` is `false`, the dashboard is open access.
|
||||
|
||||
## Step 7: Test locally
|
||||
|
||||
1. Start your development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
2. Navigate to `http://localhost:5173/dashboard`
|
||||
|
||||
3. You should see a login prompt (if `requireAuth: true`) or the dashboard (if `requireAuth: false`)
|
||||
|
||||
4. If authentication is enabled, click "Sign in" to test the WorkOS login flow
|
||||
|
||||
5. After logging in, you should be redirected back to the dashboard
|
||||
|
||||
## Step 8: Deploy to production
|
||||
|
||||
### Add production environment variables
|
||||
|
||||
In your Netlify dashboard (or hosting provider), add these environment variables:
|
||||
|
||||
- `VITE_WORKOS_CLIENT_ID` - Your WorkOS Client ID
|
||||
- `VITE_WORKOS_REDIRECT_URI` - Your production callback URL (e.g., `https://yoursite.netlify.app/callback`)
|
||||
|
||||
### Update WorkOS redirect URI
|
||||
|
||||
1. Go to **Redirects** in the WorkOS Dashboard
|
||||
2. Add your production callback URL: `https://yoursite.netlify.app/callback`
|
||||
3. Click **Save**
|
||||
|
||||
### Update CORS settings
|
||||
|
||||
1. Go to **Authentication** → **Sessions** in the WorkOS Dashboard
|
||||
2. Find **Cross-Origin Resource Sharing (CORS)**
|
||||
3. Click **Manage**
|
||||
4. Add your production domain: `https://yoursite.netlify.app`
|
||||
5. Click **Save**
|
||||
|
||||
### Add Convex environment variable
|
||||
|
||||
In your Convex Dashboard, add the `WORKOS_CLIENT_ID` environment variable for your production deployment:
|
||||
|
||||
1. Go to [dashboard.convex.dev](https://dashboard.convex.dev)
|
||||
2. Select your production project
|
||||
3. Navigate to Settings → Environment Variables
|
||||
4. Add `WORKOS_CLIENT_ID` with your Client ID value
|
||||
5. Save
|
||||
|
||||
## How it works
|
||||
|
||||
When WorkOS is configured and `requireAuth: true`:
|
||||
|
||||
1. User navigates to `/dashboard`
|
||||
2. Dashboard checks authentication status
|
||||
3. If not authenticated, shows login prompt
|
||||
4. User clicks "Sign in" and is redirected to WorkOS
|
||||
5. User logs in with WorkOS (password, social, or SSO)
|
||||
6. WorkOS redirects back to `/callback` with authorization code
|
||||
7. App exchanges code for user information
|
||||
8. User is redirected to `/dashboard` as authenticated user
|
||||
|
||||
When WorkOS is not configured or `requireAuth: false`:
|
||||
|
||||
1. User navigates to `/dashboard`
|
||||
2. Dashboard shows content directly (no authentication required)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Dashboard shows "Authentication Required" message:**
|
||||
- Verify `VITE_WORKOS_CLIENT_ID` and `VITE_WORKOS_REDIRECT_URI` are set in `.env.local`
|
||||
- Check that `WORKOS_CLIENT_ID` is set in Convex environment variables
|
||||
- Ensure `requireAuth: true` in `siteConfig.ts`
|
||||
|
||||
**Login redirect not working:**
|
||||
- Verify redirect URI matches exactly in WorkOS Dashboard
|
||||
- Check CORS settings include your domain
|
||||
- Ensure callback route is configured in `App.tsx`
|
||||
|
||||
**"WorkOS is not configured" message:**
|
||||
- Check that both `VITE_WORKOS_CLIENT_ID` and `VITE_WORKOS_REDIRECT_URI` are set
|
||||
- Verify environment variables are loaded (check browser console)
|
||||
- Restart development server after adding environment variables
|
||||
|
||||
**Convex auth errors:**
|
||||
- Verify `WORKOS_CLIENT_ID` is set in Convex environment variables
|
||||
- Check that `convex/auth.config.ts` exists and is correct
|
||||
- Ensure Convex functions are deployed (`npx convex deploy`)
|
||||
|
||||
## Optional configuration
|
||||
|
||||
WorkOS is optional. You can:
|
||||
|
||||
- Use the dashboard without WorkOS (`requireAuth: false`)
|
||||
- Enable WorkOS later when you need authentication
|
||||
- Configure WorkOS for production only
|
||||
|
||||
The dashboard works with or without WorkOS. Configure it based on your needs.
|
||||
|
||||
## Next steps
|
||||
|
||||
After setting up WorkOS:
|
||||
|
||||
1. Test the authentication flow locally
|
||||
2. Deploy to production with production environment variables
|
||||
3. Add additional redirect URIs if needed
|
||||
4. Configure social login providers in WorkOS Dashboard
|
||||
5. Set up SSO if needed for your organization
|
||||
|
||||
See [How to use the Markdown sync dashboard](https://www.markdown.fast/how-to-use-the-markdown-sync-dashboard) for dashboard usage.
|
||||
269
content/blog/how-to-use-the-markdown-sync-dashboard.md
Normal file
269
content/blog/how-to-use-the-markdown-sync-dashboard.md
Normal file
@@ -0,0 +1,269 @@
|
||||
---
|
||||
title: "How to use the Markdown sync dashboard"
|
||||
description: "Learn how to use the dashboard at /dashboard to manage content, configure your site, and sync markdown files without leaving your browser."
|
||||
date: "2025-12-29"
|
||||
slug: "how-to-use-the-markdown-sync-dashboard"
|
||||
published: true
|
||||
tags: ["dashboard", "tutorial", "content-management"]
|
||||
readTime: "8 min read"
|
||||
featured: true
|
||||
featuredOrder: 2
|
||||
excerpt: "A complete guide to using the dashboard for managing your markdown blog without leaving your browser."
|
||||
---
|
||||
|
||||
# How to use the Markdown sync dashboard
|
||||
|
||||
The dashboard at `/dashboard` gives you a centralized interface for managing your markdown blog. You can edit posts, sync content, configure settings, and more without switching between your editor and terminal.
|
||||
|
||||
## Accessing the dashboard
|
||||
|
||||
Navigate to `/dashboard` in your browser. The dashboard isn't linked in the navigation by default, so you'll access it directly via URL.
|
||||
|
||||
### Authentication
|
||||
|
||||
The dashboard supports optional WorkOS authentication. Configure it in `siteConfig.ts`:
|
||||
|
||||
```typescript
|
||||
dashboard: {
|
||||
enabled: true,
|
||||
requireAuth: false, // Set to true to require WorkOS authentication
|
||||
},
|
||||
```
|
||||
|
||||
When `requireAuth` is `false`, the dashboard is open to anyone who knows the URL. For production sites, set `requireAuth: true` and configure WorkOS authentication. See [How to setup WorkOS](https://www.markdown.fast/how-to-setup-workos) for authentication setup.
|
||||
|
||||
If WorkOS isn't configured and `requireAuth` is `true`, the dashboard shows setup instructions instead of the login prompt.
|
||||
|
||||
## Content management
|
||||
|
||||
### Posts and pages list
|
||||
|
||||
View all your posts and pages in one place. Each list includes:
|
||||
|
||||
- Filter by status: All, Published, Drafts
|
||||
- Search by title or content
|
||||
- Pagination with "First" and "Next" buttons
|
||||
- Items per page selector (15, 25, 50, 100)
|
||||
- Quick actions: Edit, View, Publish/Unpublish
|
||||
|
||||
Posts and pages display with their titles, publication status, and last modified dates. Click any item to open the editor.
|
||||
|
||||
### Post and page editor
|
||||
|
||||
Edit markdown content with a live preview. The editor includes:
|
||||
|
||||
- Markdown editor on the left
|
||||
- Live preview on the right showing how content appears on your site
|
||||
- Draggable frontmatter sidebar (200px-600px width)
|
||||
- Independent scrolling for editor and preview sections
|
||||
- Download markdown button to save changes locally
|
||||
- Copy to clipboard for quick sharing
|
||||
|
||||
The frontmatter sidebar shows all available fields with descriptions. Edit values directly, and changes appear in the preview immediately.
|
||||
|
||||
### Write post and write page
|
||||
|
||||
Create new content without leaving the dashboard. The write interface includes:
|
||||
|
||||
- Full-screen markdown editor
|
||||
- Frontmatter reference panel with copy buttons
|
||||
- Word, line, and character counts
|
||||
- Download markdown button
|
||||
- Content persists in localStorage
|
||||
|
||||
Write your content, fill in frontmatter fields, then download the markdown file. Save it to `content/blog/` or `content/pages/`, then sync to Convex.
|
||||
|
||||
## AI Agent
|
||||
|
||||
The dashboard includes a dedicated AI chat section separate from the Write page. Use it for:
|
||||
|
||||
- Writing assistance
|
||||
- Content suggestions
|
||||
- Editing help
|
||||
- Answering questions about your content
|
||||
|
||||
The AI Agent uses Anthropic Claude API and requires `ANTHROPIC_API_KEY` in your Convex environment variables. Chat history is stored per-session in Convex.
|
||||
|
||||
## Newsletter management
|
||||
|
||||
All Newsletter Admin features are integrated into the dashboard:
|
||||
|
||||
- Subscribers: View, search, filter, and delete subscribers
|
||||
- Send newsletter: Select a blog post to send to all active subscribers
|
||||
- Write email: Compose custom emails with markdown support
|
||||
- Recent sends: View the last 10 newsletter sends (posts and custom emails)
|
||||
- Email stats: Dashboard with total emails sent, newsletters sent, active subscribers, and retention rate
|
||||
|
||||
Newsletter features require AgentMail configuration. Set `AGENTMAIL_API_KEY` and `AGENTMAIL_INBOX` in your Convex environment variables.
|
||||
|
||||
## Content import
|
||||
|
||||
Import articles from external URLs using Firecrawl:
|
||||
|
||||
1. Enter the URL you want to import
|
||||
2. Click "Import"
|
||||
3. Review the imported markdown draft
|
||||
4. Edit if needed, then sync to Convex
|
||||
|
||||
Imported posts are created as drafts (`published: false`) by default. Review, edit, set `published: true`, then sync.
|
||||
|
||||
Firecrawl import requires `FIRECRAWL_API_KEY` in your `.env.local` file.
|
||||
|
||||
## Site configuration
|
||||
|
||||
The Config Generator UI lets you configure all `siteConfig.ts` settings from the dashboard:
|
||||
|
||||
- Site name, title, logo, bio
|
||||
- Blog page settings
|
||||
- Featured section configuration
|
||||
- Logo gallery settings
|
||||
- GitHub contributions
|
||||
- Footer and social footer
|
||||
- Newsletter settings
|
||||
- Contact form settings
|
||||
- Stats page settings
|
||||
- Dashboard settings
|
||||
|
||||
Make changes in the UI, then download the generated `siteConfig.ts` file. Replace your existing config file with the downloaded version.
|
||||
|
||||
## Index HTML editor
|
||||
|
||||
View and edit `index.html` content directly:
|
||||
|
||||
- Meta tags
|
||||
- Open Graph tags
|
||||
- Twitter Cards
|
||||
- JSON-LD structured data
|
||||
|
||||
Edit values in the UI, then download the updated HTML file. Replace your existing `index.html` with the downloaded version.
|
||||
|
||||
## Analytics
|
||||
|
||||
The dashboard includes a real-time stats section (clone of `/stats` page):
|
||||
|
||||
- Active visitors with per-page breakdown
|
||||
- Total page views
|
||||
- Unique visitors
|
||||
- Views by page sorted by popularity
|
||||
|
||||
Stats update automatically via Convex subscriptions. No page refresh needed.
|
||||
|
||||
## Sync commands
|
||||
|
||||
Run sync operations from the dashboard without opening a terminal:
|
||||
|
||||
**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
|
||||
|
||||
### Sync server
|
||||
|
||||
For the best experience, start the sync server to execute commands directly from the dashboard:
|
||||
|
||||
```bash
|
||||
npm run sync-server
|
||||
```
|
||||
|
||||
This starts a local HTTP server on `localhost:3001` that allows the dashboard to execute sync commands and stream output in real-time.
|
||||
|
||||
**When sync server is running:**
|
||||
|
||||
- Server status shows "Online" in the sync section
|
||||
- "Execute" buttons appear for each sync command
|
||||
- Clicking Execute runs the command and streams output to the terminal view
|
||||
- Real-time output appears as the command runs
|
||||
- No need to copy commands to your terminal
|
||||
|
||||
**When sync server is offline:**
|
||||
|
||||
- Server status shows "Offline" in the sync section
|
||||
- Only "Copy" buttons appear for each sync command
|
||||
- Clicking Copy shows the command in a modal for copying to your terminal
|
||||
- Copy icon appears next to `npm run sync-server` command to help you start the server
|
||||
|
||||
**Security:**
|
||||
|
||||
- Server binds to localhost only (not accessible from network)
|
||||
- Optional token authentication via `SYNC_TOKEN` environment variable
|
||||
- Only whitelisted commands can be executed
|
||||
- CORS enabled for localhost:5173 (dev server)
|
||||
|
||||
### Header sync buttons
|
||||
|
||||
Quick sync buttons in the dashboard header let you run `npm run sync:all` (dev and prod) with one click. These buttons automatically use the sync server when available, or show the command in a modal when the server is offline.
|
||||
|
||||
## Dashboard features
|
||||
|
||||
### Search
|
||||
|
||||
The search bar in the dashboard header searches:
|
||||
|
||||
- Dashboard features and sections
|
||||
- Page titles
|
||||
- Post content
|
||||
|
||||
Results appear as you type. Click any result to navigate to that section or content.
|
||||
|
||||
### Theme and font
|
||||
|
||||
Toggle between themes (dark, light, tan, cloud) and switch fonts (serif, sans, monospace) from the dashboard. Preferences persist across sessions.
|
||||
|
||||
### Toast notifications
|
||||
|
||||
Success, error, info, and warning notifications appear in the top-right corner. They auto-dismiss after 4 seconds and are theme-aware.
|
||||
|
||||
### Command modal
|
||||
|
||||
When you run sync commands, output appears in a modal. You can:
|
||||
|
||||
- View full command output
|
||||
- Copy command to clipboard
|
||||
- Close the modal
|
||||
|
||||
### Mobile responsive
|
||||
|
||||
The dashboard works on mobile devices with:
|
||||
|
||||
- Collapsible sidebar
|
||||
- Touch-friendly controls
|
||||
- Responsive tables and forms
|
||||
- Mobile-optimized layout
|
||||
|
||||
## Best practices
|
||||
|
||||
1. Use the editor for quick edits and previews
|
||||
2. Download markdown files for version control
|
||||
3. Sync regularly to keep content up to date
|
||||
4. Use the AI Agent for writing assistance
|
||||
5. Check analytics to see what content performs well
|
||||
6. Configure WorkOS authentication for production sites
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Dashboard not loading:**
|
||||
|
||||
- Check that `dashboard.enabled: true` in `siteConfig.ts`
|
||||
- Verify Convex is running (`npx convex dev`)
|
||||
- Check browser console for errors
|
||||
|
||||
**Sync commands failing:**
|
||||
|
||||
- Ensure you're in the project root directory
|
||||
- Check that Convex environment variables are set
|
||||
- Verify `.env.local` or `.env.production.local` exists
|
||||
|
||||
**Authentication not working:**
|
||||
|
||||
- Verify WorkOS environment variables are set
|
||||
- Check that `requireAuth: true` in `siteConfig.ts`
|
||||
- See [How to setup WorkOS](https://www.markdown.fast/how-to-setup-workos) for setup instructions
|
||||
|
||||
The dashboard makes managing your markdown blog easier. You can edit content, sync files, and configure settings all from one place.
|
||||
@@ -16,7 +16,9 @@ image: "/images/markdown.png"
|
||||
|
||||
# Writing Markdown with Code Examples
|
||||
|
||||
This post demonstrates how to write markdown content with code blocks, tables, and formatting. Use it as a reference when creating your own posts.
|
||||
This post is the complete reference for all markdown syntax used in this framework. It includes copy-paste examples for code blocks, tables, lists, links, images, collapsible sections, and all formatting options.
|
||||
|
||||
**Use this post as your reference** when writing blog posts or pages. All examples are ready to copy and paste directly into your markdown files.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
|
||||
@@ -1589,6 +1589,67 @@ Agent requires the following Convex environment variables:
|
||||
|
||||
If `ANTHROPIC_API_KEY` is not configured in Convex environment variables, Agent displays a user-friendly error message: "API key is not set". This helps identify when the API key is missing in production deployments.
|
||||
|
||||
## Dashboard
|
||||
|
||||
The Dashboard at `/dashboard` provides a centralized UI for managing content, configuring the site, and performing sync operations. It's designed for developers who fork the repository to set up and manage their markdown blog.
|
||||
|
||||
**Access:** Navigate to `/dashboard` in your browser. The dashboard is not linked in the navigation by default.
|
||||
|
||||
**Authentication:** WorkOS authentication is optional. Configure it in `siteConfig.ts`:
|
||||
|
||||
```typescript
|
||||
dashboard: {
|
||||
enabled: true,
|
||||
requireAuth: false, // Set to true to require WorkOS authentication
|
||||
},
|
||||
```
|
||||
|
||||
When `requireAuth` is `false`, the dashboard is open access. When `requireAuth` is `true` and WorkOS is configured, users must log in to access the dashboard. See [How to setup WorkOS](https://www.markdown.fast/how-to-setup-workos) for authentication setup.
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- **Content Management:** Posts and Pages list views with filtering, search, pagination, and items per page selector
|
||||
- **Post/Page Editor:** Markdown editor with live preview, draggable/resizable frontmatter sidebar, download markdown
|
||||
- **Write Post/Page:** Full-screen writing interface with markdown editor and frontmatter reference
|
||||
- **AI Agent:** Dedicated AI chat section separate from Write page
|
||||
- **Newsletter Management:** All Newsletter Admin features integrated (subscribers, send newsletter, write email, recent sends, email stats)
|
||||
- **Content Import:** Firecrawl import UI for importing external URLs as markdown drafts
|
||||
- **Site Configuration:** Config Generator UI for all `siteConfig.ts` settings
|
||||
- **Index HTML Editor:** View and edit `index.html` content
|
||||
- **Analytics:** Real-time stats dashboard (always accessible in dashboard)
|
||||
- **Sync Commands:** UI with buttons for all sync operations (sync, sync:discovery, sync:all for dev and prod)
|
||||
- **Sync Server:** Execute sync commands directly from dashboard with real-time output
|
||||
- **Header Sync Buttons:** Quick sync buttons in dashboard header for `npm run sync:all` (dev and prod)
|
||||
|
||||
**Sync Commands Available:**
|
||||
|
||||
- `npm run sync` - Sync markdown content (development)
|
||||
- `npm run sync:prod` - Sync markdown content (production)
|
||||
- `npm run sync:discovery` - Update discovery files (development)
|
||||
- `npm run sync:discovery:prod` - Update discovery files (production)
|
||||
- `npm run sync:all` - Sync content + discovery files (development)
|
||||
- `npm run sync:all:prod` - Sync content + discovery files (production)
|
||||
- `npm run sync-server` - Start local HTTP server for executing commands from dashboard
|
||||
|
||||
**Sync Server:**
|
||||
|
||||
The dashboard can execute sync commands directly without opening a terminal. Start the sync server:
|
||||
|
||||
```bash
|
||||
npm run sync-server
|
||||
```
|
||||
|
||||
This starts a local HTTP server on `localhost:3001` that:
|
||||
- Executes sync commands when requested from the dashboard
|
||||
- Streams output in real-time to the dashboard terminal view
|
||||
- Shows server status (online/offline) in the dashboard
|
||||
- Supports optional token authentication via `SYNC_TOKEN` environment variable
|
||||
- Only executes whitelisted commands for security
|
||||
|
||||
When the sync server is running, the dashboard shows "Execute" buttons that run commands directly. When offline, buttons show commands in a modal for copying to your terminal.
|
||||
|
||||
The dashboard provides a UI for these commands, but you can also run them directly from the terminal. See the [Dashboard documentation](/docs#dashboard) for complete details.
|
||||
|
||||
## Next Steps
|
||||
|
||||
After deploying:
|
||||
|
||||
@@ -9,6 +9,108 @@ layout: "sidebar"
|
||||
All notable changes to this project.
|
||||

|
||||
|
||||
## v1.46.0
|
||||
|
||||
Released December 29, 2025
|
||||
|
||||
**Dashboard sync server for executing sync commands from UI**
|
||||
|
||||
- Local HTTP server for executing sync commands directly from dashboard
|
||||
- Run `npm run sync-server` to start the local server on localhost:3001
|
||||
- Execute sync commands without opening a terminal
|
||||
- Real-time output streaming in dashboard terminal view
|
||||
- Server status indicator shows online/offline status
|
||||
- Copy and Execute buttons for each sync command
|
||||
- Optional token authentication via `SYNC_TOKEN` environment variable
|
||||
- Whitelisted commands only for security
|
||||
- Health check endpoint for server availability detection
|
||||
- Header sync buttons automatically use sync server when available
|
||||
- Copy icons for `npm run sync-server` command throughout dashboard
|
||||
|
||||
**Technical details:**
|
||||
|
||||
- New `scripts/sync-server.ts` file implements local HTTP server
|
||||
- Uses Node.js `child_process.spawn` to execute npm commands
|
||||
- Streams output in real-time to dashboard UI
|
||||
- CORS enabled for localhost:5173 development server
|
||||
- Server binds to localhost only (not accessible from network)
|
||||
|
||||
Updated files: `scripts/sync-server.ts`, `src/pages/Dashboard.tsx`, `src/styles/global.css`, `package.json`
|
||||
|
||||
## v1.45.0
|
||||
|
||||
Released December 29, 2025
|
||||
|
||||
**Dashboard and WorkOS authentication integration**
|
||||
|
||||
- Dashboard supports optional WorkOS authentication via `siteConfig.dashboard.requireAuth`
|
||||
- WorkOS is optional - dashboard works with or without WorkOS configured
|
||||
- When `requireAuth` is `false`, dashboard is open access
|
||||
- When `requireAuth` is `true` and WorkOS is configured, dashboard requires login
|
||||
- Shows setup instructions if `requireAuth` is `true` but WorkOS is not configured
|
||||
- Warning banner displayed when authentication is not enabled
|
||||
- Blog posts added: "How to use the Markdown sync dashboard" and "How to setup WorkOS"
|
||||
|
||||
Updated files: `src/pages/Dashboard.tsx`, `src/main.tsx`, `src/App.tsx`, `src/pages/Callback.tsx`, `src/utils/workos.ts`, `convex/auth.config.ts`, `src/config/siteConfig.ts`, `README.md`, `content/pages/docs.md`, `content/blog/setup-guide.md`, `FORK_CONFIG.md`, `fork-config.json.example`, `files.md`, `TASK.md`, `changelog.md`, `content/pages/changelog-page.md`
|
||||
|
||||
## v1.44.0
|
||||
|
||||
Released December 29, 2025
|
||||
|
||||
**Dashboard for centralized content management and site configuration**
|
||||
|
||||
- Dashboard at `/dashboard` provides a centralized UI for managing content, configuring the site, and performing sync operations
|
||||
- Content management: Posts and Pages list views with filtering, search, pagination, and items per page selector (15, 25, 50, 100)
|
||||
- Post and Page editor: Markdown editor with live preview, draggable/resizable frontmatter sidebar (200px-600px), independent scrolling, download markdown, copy to clipboard
|
||||
- Write Post and Write Page: Full-screen writing interface with markdown editor, frontmatter reference, download markdown, localStorage persistence
|
||||
- AI Agent section: Dedicated AI chat separate from Write page, uses Anthropic Claude API, per-session chat history, markdown rendering
|
||||
- Newsletter management: All Newsletter Admin features integrated (subscribers, send newsletter, write email, recent sends, email stats)
|
||||
- Content import: Firecrawl import UI for importing external URLs as markdown drafts
|
||||
- Site configuration: Config Generator UI for all `siteConfig.ts` settings, generates downloadable config file
|
||||
- Index HTML editor: View and edit `index.html` content with meta tags, Open Graph, Twitter Cards, JSON-LD
|
||||
- Analytics: Real-time stats dashboard (clone of `/stats` page, always accessible in dashboard)
|
||||
- Sync commands: UI with buttons for all sync operations (sync, sync:discovery, sync:all for dev and prod)
|
||||
- Header sync buttons: Quick sync buttons in dashboard header for `npm run sync:all` (dev and prod)
|
||||
- Dashboard search: Search bar in header to search dashboard features, page titles, and post content
|
||||
- Toast notifications: Success, error, info, and warning notifications with auto-dismiss
|
||||
- Command modal: Shows sync command output with copy to clipboard functionality
|
||||
- Mobile responsive: Fully responsive design with mobile-optimized layout
|
||||
- Theme and font: Theme toggle and font switcher with persistent preferences
|
||||
|
||||
Updated files: `src/pages/Dashboard.tsx`, `src/styles/global.css`, `src/App.tsx`
|
||||
|
||||
## v1.43.0
|
||||
|
||||
Released December 29, 2025
|
||||
|
||||
**Stats page configuration option for public/private access**
|
||||
|
||||
- New `StatsPageConfig` interface in `siteConfig.ts` with `enabled` and `showInNav` options
|
||||
- Stats page can be made private by setting `enabled: false` (similar to NewsletterAdmin pattern)
|
||||
- When disabled, route shows "Stats page is disabled" message instead of analytics
|
||||
- Navigation item automatically hidden when stats page is disabled
|
||||
- Default configuration: `enabled: true` (public), `showInNav: true` (visible in nav)
|
||||
|
||||
Updated files: `src/config/siteConfig.ts`, `src/App.tsx`, `src/pages/Stats.tsx`, `src/components/Layout.tsx`
|
||||
|
||||
## v1.42.0
|
||||
|
||||
Released December 29, 2025
|
||||
|
||||
**Honeypot bot protection for contact and newsletter forms**
|
||||
|
||||
- Hidden honeypot fields invisible to humans but visible to bots
|
||||
- Contact form uses hidden "Website" field for bot detection
|
||||
- Newsletter signup uses hidden "Fax" field for bot detection
|
||||
- Bots that fill hidden fields receive fake success message (no data submitted)
|
||||
- No external dependencies required (client-side only protection)
|
||||
- Works with all four themes (dark, light, tan, cloud)
|
||||
|
||||
Updated files: `src/components/ContactForm.tsx`, `src/components/NewsletterSignup.tsx`
|
||||
- Honeypot fields use CSS positioning (position: absolute, left: -9999px) to hide from users
|
||||
- Fields include aria-hidden="true" and tabIndex={-1} for accessibility
|
||||
- Different field names per form (website/fax) to avoid pattern detection
|
||||
|
||||
## v1.41.0
|
||||
|
||||
Released December 28, 2025
|
||||
|
||||
@@ -83,6 +83,8 @@ markdown-site/
|
||||
|
||||
## Content
|
||||
|
||||
**Markdown examples:** For complete markdown syntax examples including code blocks, tables, lists, links, images, collapsible sections, and all formatting options, see [Writing Markdown with Code Examples](/markdown-with-code-examples). That post includes copy-paste examples for every markdown feature.
|
||||
|
||||
### Blog posts
|
||||
|
||||
Create files in `content/blog/` with frontmatter:
|
||||
@@ -1003,6 +1005,206 @@ 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.
|
||||
|
||||
## Dashboard
|
||||
|
||||
The Dashboard at `/dashboard` provides a centralized UI for managing content, configuring the site, and performing sync operations. It's designed for developers who fork the repository to set up and manage their markdown blog.
|
||||
|
||||
**Access:** Navigate to `/dashboard` in your browser. The dashboard is not linked in the navigation by default (similar to Newsletter Admin pattern).
|
||||
|
||||
**Authentication:** WorkOS authentication is optional. Configure it in `siteConfig.ts`:
|
||||
|
||||
```typescript
|
||||
dashboard: {
|
||||
enabled: true,
|
||||
requireAuth: false, // Set to true to require WorkOS authentication
|
||||
},
|
||||
```
|
||||
|
||||
When `requireAuth` is `false`, the dashboard is open access. When `requireAuth` is `true` and WorkOS is configured, users must log in to access the dashboard. See [How to setup WorkOS](https://www.markdown.fast/how-to-setup-workos) for authentication setup.
|
||||
|
||||
### Content Management
|
||||
|
||||
**Posts and Pages List Views:**
|
||||
- View all posts and pages (published and unpublished)
|
||||
- Filter by status: All, Published, Drafts
|
||||
- Search by title or content
|
||||
- Pagination with "First" and "Next" buttons
|
||||
- Items per page selector (15, 25, 50, 100) - default: 15
|
||||
- Edit, view, and publish/unpublish options
|
||||
- WordPress-style UI with date, edit, view, and publish controls
|
||||
|
||||
**Post and Page Editor:**
|
||||
- Markdown editor with live preview
|
||||
- Frontmatter sidebar on the right with all available fields
|
||||
- Draggable/resizable frontmatter sidebar (200px-600px width)
|
||||
- Independent scrolling for frontmatter sidebar
|
||||
- Preview mode shows content as it appears on the live site
|
||||
- Download markdown button to generate `.md` files
|
||||
- Copy markdown to clipboard
|
||||
- All frontmatter fields editable in sidebar
|
||||
- Preview uses ReactMarkdown with proper styling
|
||||
|
||||
**Write Post and Write Page:**
|
||||
- Full-screen writing interface
|
||||
- Markdown editor with word/line/character counts
|
||||
- Frontmatter reference panel
|
||||
- Download markdown button for new content
|
||||
- Content persists in localStorage
|
||||
- Separate storage for post and page content
|
||||
|
||||
### AI Agent
|
||||
|
||||
- Dedicated AI chat section separate from the Write page
|
||||
- Uses Anthropic Claude API (requires `ANTHROPIC_API_KEY` in Convex environment)
|
||||
- Per-session chat history stored in Convex
|
||||
- Markdown rendering for AI responses
|
||||
- Copy functionality for AI responses
|
||||
|
||||
### Newsletter Management
|
||||
|
||||
All Newsletter Admin features integrated into the Dashboard:
|
||||
|
||||
- **Subscribers:** View, search, filter, and delete subscribers
|
||||
- **Send Newsletter:** Select a blog post to send as newsletter
|
||||
- **Write Email:** Compose custom emails with markdown support
|
||||
- **Recent Sends:** View last 10 newsletter sends (posts and custom emails)
|
||||
- **Email Stats:** Dashboard with total emails, newsletters sent, active subscribers, retention rate
|
||||
|
||||
All newsletter sections are full-width in the dashboard content area.
|
||||
|
||||
### Content Import
|
||||
|
||||
**Firecrawl Import:**
|
||||
- Import articles from external URLs using Firecrawl API
|
||||
- Requires `FIRECRAWL_API_KEY` in `.env.local`
|
||||
- Creates local markdown drafts in `content/blog/`
|
||||
- Imported posts are drafts (`published: false`) by default
|
||||
- Review, edit, set `published: true`, then sync
|
||||
|
||||
### Site Configuration
|
||||
|
||||
**Config Generator:**
|
||||
- UI to configure all settings in `src/config/siteConfig.ts`
|
||||
- Generates downloadable `siteConfig.ts` file
|
||||
- Hybrid approach: dashboard generates config, file-based config continues to work
|
||||
- Includes all site configuration options:
|
||||
- Site name, title, logo, bio, intro
|
||||
- Blog page settings
|
||||
- Featured section configuration
|
||||
- Logo gallery settings
|
||||
- GitHub contributions
|
||||
- Footer and social footer
|
||||
- Newsletter settings
|
||||
- Contact form settings
|
||||
- Stats page settings
|
||||
- And more
|
||||
|
||||
**Index HTML Editor:**
|
||||
- View and edit `index.html` content
|
||||
- Meta tags, Open Graph, Twitter Cards, JSON-LD
|
||||
- Download updated HTML file
|
||||
|
||||
### Analytics
|
||||
|
||||
- Real-time stats dashboard (clone of `/stats` page)
|
||||
- Active visitors with per-page breakdown
|
||||
- Total page views and unique visitors
|
||||
- Views by page sorted by popularity
|
||||
- Does not follow `siteConfig.statsPage` settings (always accessible in dashboard)
|
||||
|
||||
### Sync Commands
|
||||
|
||||
**Sync Content Section:**
|
||||
- UI with buttons for all sync operations
|
||||
- Development sync commands:
|
||||
- `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 sync commands:
|
||||
- `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
|
||||
- Server status indicator shows if sync server is online
|
||||
- Copy and Execute buttons for each command
|
||||
- Real-time terminal output when sync server is running
|
||||
- Command modal shows full command output when sync server is offline
|
||||
- Toast notifications for success/error feedback
|
||||
|
||||
**Sync Server:**
|
||||
- Local HTTP server for executing commands from dashboard
|
||||
- Start with `npm run sync-server` (runs on localhost:3001)
|
||||
- Execute commands directly from dashboard with real-time output streaming
|
||||
- Optional token authentication via `SYNC_TOKEN` environment variable
|
||||
- Whitelisted commands only for security
|
||||
- Health check endpoint for server availability detection
|
||||
- Copy icons for `npm run sync-server` command in dashboard
|
||||
|
||||
**Header Sync Buttons:**
|
||||
- Quick sync buttons in dashboard header (right side)
|
||||
- `npm run sync:all` (dev) button
|
||||
- `npm run sync:all:prod` (prod) button
|
||||
- One-click sync for all content and discovery files
|
||||
- Automatically use sync server when available, fallback to command modal
|
||||
|
||||
### Dashboard Features
|
||||
|
||||
**Search:**
|
||||
- Search bar in header
|
||||
- Search dashboard features, page titles, and post content
|
||||
- Real-time results as you type
|
||||
|
||||
**Theme and Font:**
|
||||
- Theme toggle (dark, light, tan, cloud)
|
||||
- Font switcher (serif, sans, monospace)
|
||||
- Preferences persist across sessions
|
||||
|
||||
**Mobile Responsive:**
|
||||
- Fully responsive design
|
||||
- Mobile-optimized layout
|
||||
- Touch-friendly controls
|
||||
- Collapsible sidebar on mobile
|
||||
|
||||
**Toast Notifications:**
|
||||
- Success, error, info, and warning notifications
|
||||
- Auto-dismiss after 4 seconds
|
||||
- Theme-aware styling
|
||||
- No browser default alerts
|
||||
|
||||
**Command Modal:**
|
||||
- Shows sync command output
|
||||
- Copy command to clipboard
|
||||
- Close button to dismiss
|
||||
- Theme-aware styling
|
||||
|
||||
### Technical Details
|
||||
|
||||
- Uses Convex queries for real-time data
|
||||
- All mutations follow Convex best practices (idempotent, indexed queries)
|
||||
- Frontmatter sidebar width persisted in localStorage
|
||||
- Editor content persisted in localStorage
|
||||
- Independent scrolling for editor and sidebar sections
|
||||
- Preview uses ReactMarkdown with remark-gfm, remark-breaks, rehype-raw, rehype-sanitize
|
||||
|
||||
### Sync Commands Reference
|
||||
|
||||
**Development:**
|
||||
- `npm run sync` - Sync markdown content to development Convex
|
||||
- `npm run sync:discovery` - Update discovery files (AGENTS.md, llms.txt) with development data
|
||||
- `npm run sync:all` - Run both content sync and discovery sync (development)
|
||||
|
||||
**Production:**
|
||||
- `npm run sync:prod` - Sync markdown content to production Convex
|
||||
- `npm run sync:discovery:prod` - Update discovery files with production data
|
||||
- `npm run sync:all:prod` - Run both content sync and discovery sync (production)
|
||||
|
||||
**Sync Server:**
|
||||
- `npm run sync-server` - Start local HTTP server for executing sync commands from dashboard UI
|
||||
|
||||
**Content Import:**
|
||||
- `npm run import <url>` - Import external URL as markdown post (requires FIRECRAWL_API_KEY)
|
||||
|
||||
**Note:** The dashboard provides a UI for these commands. When the sync server is running (`npm run sync-server`), you can execute commands directly from the dashboard with real-time output. Otherwise, the dashboard shows commands in a modal for copying to your terminal.
|
||||
|
||||
## API endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
@@ -1077,49 +1279,18 @@ When you run `npm run sync` (development) or `npm run sync:prod` (production), s
|
||||
|
||||
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 tables
|
||||
## Markdown formatting
|
||||
|
||||
Tables render with GitHub-style 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).
|
||||
|
||||
- Clean borders across all themes
|
||||
- Mobile responsive with horizontal scroll
|
||||
- Theme-aware alternating row colors
|
||||
- Hover states for readability
|
||||
**Quick reference:**
|
||||
|
||||
Example:
|
||||
- **Tables:** Render with GitHub-style formatting, clean borders, mobile responsive
|
||||
- **Collapsible sections:** Use HTML `<details>` and `<summary>` 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
|
||||
|
||||
| Feature | Status |
|
||||
| ------- | ------ |
|
||||
| Borders | Clean |
|
||||
| Mobile | Scroll |
|
||||
| Themes | All |
|
||||
|
||||
## Collapsible sections
|
||||
|
||||
Create expandable/collapsible content using HTML `<details>` and `<summary>` tags:
|
||||
|
||||
```html
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
|
||||
Hidden content here. Supports markdown: - Lists - **Bold** and _italic_ - Code
|
||||
blocks
|
||||
</details>
|
||||
```
|
||||
|
||||
**Expanded by default:** Add the `open` attribute:
|
||||
|
||||
```html
|
||||
<details open>
|
||||
<summary>Already expanded</summary>
|
||||
|
||||
This section starts open.
|
||||
</details>
|
||||
```
|
||||
|
||||
**Nested sections:** You can nest `<details>` inside other `<details>` for multi-level collapsible content.
|
||||
|
||||
Collapsible sections work with all four themes and are styled to match the site design.
|
||||
All markdown features work with all four themes and are styled to match the site design.
|
||||
|
||||
## Import external content
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ order: -1
|
||||
textAlign: "left"
|
||||
---
|
||||
|
||||
An open-source publishing framework built for AI agents and developers to ship websites, docs, or blogs.
|
||||
An open-source publishing framework built for AI agents and developers to ship **websites**, **docs**, or **blogs**.
|
||||
|
||||
Write markdown, sync from the terminal. [Fork it](https://github.com/waynesutton/markdown-site), customize it, ship it.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user