mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-11 20:08:57 +00:00
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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user