docs: add npm run sync:prod notes for production

Clarify when to use development vs production sync commands
in setup-guide, about-this-blog, and markdown-with-code-examples
This commit is contained in:
Wayne Sutton
2025-12-15 09:25:42 -08:00
parent 6c10829b1c
commit b280cb4605
8 changed files with 60 additions and 16 deletions

View File

@@ -1,4 +1,4 @@
# Markdown Site
# markdown "sync" site
A minimalist markdown site built with React, Convex, and Vite. Optimized for SEO, AI agents, and LLM discovery.

View File

@@ -72,9 +72,11 @@ The setup takes about 10 minutes:
1. Fork the repo
2. Run `npx convex dev` to set up your backend
3. Run `npm run sync` to upload posts
3. Run `npm run sync` to upload posts (development) or `npm run sync:prod` (production)
4. Deploy to Netlify
**Development vs Production:** Use `npm run sync` when testing locally against your dev Convex deployment. Use `npm run sync:prod` when deploying content to your live production site.
Read the [setup guide](/setup-guide) for detailed steps.
## Customization

View File

@@ -85,9 +85,12 @@ npm install
# Start development server
npm run dev
# Sync posts to Convex
# Sync posts to Convex (development)
npm run sync
# Sync posts to Convex (production)
npm run sync:prod
# Deploy to production
npm run deploy
```
@@ -114,12 +117,13 @@ Reference files with inline code: `convex/schema.ts`, `src/pages/Home.tsx`.
## Tables
| Command | Description |
| ---------------- | ------------------------ |
| `npm run dev` | Start development server |
| `npm run build` | Build for production |
| `npm run sync` | Sync markdown to Convex |
| `npx convex dev` | Start Convex dev server |
| Command | Description |
| -------------------- | ------------------------------ |
| `npm run dev` | Start development server |
| `npm run build` | Build for production |
| `npm run sync` | Sync markdown to Convex (dev) |
| `npm run sync:prod` | Sync markdown to Convex (prod) |
| `npx convex dev` | Start Convex dev server |
## Lists
@@ -177,5 +181,5 @@ content/blog/
1. Keep slugs URL-friendly (lowercase, hyphens)
2. Set `published: false` for drafts
3. Run `npm run sync` after adding posts
3. Run `npm run sync` after adding posts (or `npm run sync:prod` for production)
4. Use descriptive titles for SEO

View File

@@ -12,7 +12,7 @@ readTime: "8 min read"
This guide walks you through forking [this markdown site](https://github.com/waynesutton/markdown-site), setting up your Convex backend, and deploying to Netlify. The entire process takes about 10 minutes.
**How publishing works:** Once deployed, you write posts in markdown, run `npm run sync`, and they appear on your live site immediately. No rebuild or redeploy needed. Convex handles real-time data sync, so all connected browsers update automatically.
**How publishing works:** Once deployed, you 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 all connected browsers update automatically.
## Table of Contents
@@ -47,6 +47,7 @@ This guide walks you through forking [this markdown site](https://github.com/way
- [Add Static Pages (Optional)](#add-static-pages-optional)
- [Update SEO Meta Tags](#update-seo-meta-tags)
- [Update llms.txt and robots.txt](#update-llmstxt-and-robotstxt)
- [Real-time Stats](#real-time-stats)
- [API Endpoints](#api-endpoints)
- [Troubleshooting](#troubleshooting)
- [Posts not appearing](#posts-not-appearing)

View File

@@ -104,6 +104,7 @@ export const getStats = query({
uniqueVisitors: v.number(),
publishedPosts: v.number(),
publishedPages: v.number(),
trackingSince: v.union(v.number(), v.null()),
pageStats: v.array(
v.object({
path: v.string(),
@@ -133,8 +134,15 @@ export const getStats = query({
.map(([path, count]) => ({ path, count }))
.sort((a, b) => b.count - a.count);
// Get all page views
const allViews = await ctx.db.query("pageViews").collect();
// Get all page views ordered by timestamp to find earliest
const allViews = await ctx.db
.query("pageViews")
.withIndex("by_timestamp")
.order("asc")
.collect();
// Get tracking start date (earliest view timestamp)
const trackingSince = allViews.length > 0 ? allViews[0].timestamp : null;
// Aggregate views by path and count unique sessions
const viewsByPath: Record<string, number> = {};
@@ -197,6 +205,7 @@ export const getStats = query({
uniqueVisitors: uniqueSessions.size,
publishedPosts: posts.length,
publishedPages: pages.length,
trackingSince,
pageStats,
};
},

View File

@@ -4,7 +4,7 @@ import PostList from "../components/PostList";
// Site configuration - customize this for your site
const siteConfig = {
name: "Markdown Site",
name: 'markdown "sync" site',
title: "Real-time Site with Convex",
// Optional logo/header image (place in public/images/, set to null to hide)
logo: "/images/logo.svg" as string | null,

View File

@@ -10,6 +10,25 @@ import {
Activity,
} from "lucide-react";
// Site launched Dec 14, 2025 at 1:00 PM (v1.0.0), stats added same day (v1.2.0)
const SITE_LAUNCH_DATE = "Dec 14, 2025 at 1:00 PM";
// Format tracking start date with time
function formatTrackingDate(timestamp: number | null): string {
if (!timestamp) return "No data yet";
const date = new Date(timestamp);
const dateStr = date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
});
const timeStr = date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});
return `${dateStr} at ${timeStr}`;
}
export default function Stats() {
const navigate = useNavigate();
const stats = useQuery(api.stats.getStats);
@@ -56,7 +75,10 @@ export default function Stats() {
<span className="stat-card-label">Total Views</span>
</div>
<div className="stat-card-value">{stats.totalPageViews}</div>
<div className="stat-card-desc">All-time page views</div>
<div className="stat-card-desc">
Since {formatTrackingDate(stats.trackingSince)}
</div>
<div className="stat-card-note">Site launched {SITE_LAUNCH_DATE}</div>
</div>
{/* Unique visitors card */}
@@ -131,4 +153,3 @@ export default function Stats() {
</div>
);
}

View File

@@ -1025,6 +1025,13 @@ body {
color: var(--text-secondary);
}
.stat-card-note {
font-size: 11px;
color: var(--text-secondary);
opacity: 0.7;
margin-top: 4px;
}
/* Stats sections */
.stats-section {
margin-bottom: 40px;