Add asset sync script
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -34,5 +34,8 @@ pnpm-debug.log*
|
|||||||
# Vercel
|
# Vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
# Generated assets mirror
|
||||||
|
/public/assets
|
||||||
|
|
||||||
# TypeScript
|
# TypeScript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -39,7 +39,7 @@ Recent iterations focused on migrating every image to `next/image`, refreshing t
|
|||||||
- `posts/` – Blog posts (`.md`)
|
- `posts/` – Blog posts (`.md`)
|
||||||
- `pages/` – Static pages (`.md`)
|
- `pages/` – Static pages (`.md`)
|
||||||
- `assets/` – Images referenced from markdown
|
- `assets/` – Images referenced from markdown
|
||||||
- `public/assets` – Symlink to `content/assets` for serving images at `/assets/...`
|
- `public/assets` – Copy of `content/assets` that is refreshed via `npm run sync-assets` (and automatically before `npm run build`) so Next.js can serve `/assets/...` without relying on symlinks.
|
||||||
- `contentlayer.config.ts` – Contentlayer document types and markdown pipeline
|
- `contentlayer.config.ts` – Contentlayer document types and markdown pipeline
|
||||||
|
|
||||||
## UI Overview
|
## UI Overview
|
||||||
@@ -199,9 +199,17 @@ Recent iterations focused on migrating every image to `next/image`, refreshing t
|
|||||||
echo -n 'your-email@example.com' | md5 # macOS
|
echo -n 'your-email@example.com' | md5 # macOS
|
||||||
# or
|
# or
|
||||||
echo -n 'your-email@example.com' | md5sum | cut -d' ' -f1 # Linux
|
echo -n 'your-email@example.com' | md5sum | cut -d' ' -f1 # Linux
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Run the development server**
|
5. **Mirror markdown assets**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run sync-assets
|
||||||
|
```
|
||||||
|
|
||||||
|
This copies `content/assets` into `public/assets` so `/assets/...` continues to work; the build script already runs it before `next build`, but running it locally keeps your previews in sync.
|
||||||
|
|
||||||
|
6. **Run the development server**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run dev
|
||||||
@@ -242,7 +250,7 @@ Contentlayer is configured in `contentlayer.config.ts` to read from the `content
|
|||||||
```
|
```
|
||||||
|
|
||||||
- At build time, a rehype plugin rewrites these to `/assets/my-image.jpg`.
|
- At build time, a rehype plugin rewrites these to `/assets/my-image.jpg`.
|
||||||
- `public/assets` is a symlink to `content/assets`, so Next.js serves them as static files.
|
- `public/assets` is populated from `content/assets` before each build (and via `npm run sync-assets`) so `/assets/...` stays available without symlinks.
|
||||||
- `feature_image` fields are also mapped from `../assets/...` → `/assets/...` and rendered above the article content via `next/image`.
|
- `feature_image` fields are also mapped from `../assets/...` → `/assets/...` and rendered above the article content via `next/image`.
|
||||||
- All component-level imagery (list thumbnails, related posts, sidebar avatar, about page hero, etc.) now uses `next/image` for responsive sizing, blur placeholders, and better LCP.
|
- All component-level imagery (list thumbnails, related posts, sidebar avatar, about page hero, etc.) now uses `next/image` for responsive sizing, blur placeholders, and better LCP.
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"sync-assets": "node scripts/sync-assets.mjs",
|
||||||
|
"build": "npm run sync-assets && next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"contentlayer": "contentlayer build"
|
"contentlayer": "contentlayer build"
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
"@fortawesome/react-fontawesome": "^3.1.0",
|
"@fortawesome/react-fontawesome": "^3.1.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"contentlayer": "^0.3.4",
|
"contentlayer": "^0.3.4",
|
||||||
|
"framer-motion": "^12.23.24",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"markdown-wasm": "^1.2.0",
|
"markdown-wasm": "^1.2.0",
|
||||||
"next": "^13.5.11",
|
"next": "^13.5.11",
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
"rehype-autolink-headings": "^7.1.0",
|
"rehype-autolink-headings": "^7.1.0",
|
||||||
"rehype-slug": "^6.0.0",
|
"rehype-slug": "^6.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
|
"tailwind-merge": "^3.4.0",
|
||||||
"unist-util-visit": "^5.0.0"
|
"unist-util-visit": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../content/assets
|
|
||||||
27
scripts/sync-assets.mjs
Normal file
27
scripts/sync-assets.mjs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { cp, mkdir, rm, stat } from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
async function syncAssets() {
|
||||||
|
const root = process.cwd();
|
||||||
|
const sourceDir = path.join(root, 'content', 'assets');
|
||||||
|
const targetDir = path.join(root, 'public', 'assets');
|
||||||
|
|
||||||
|
await rm(targetDir, { recursive: true, force: true });
|
||||||
|
await mkdir(targetDir, { recursive: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
await stat(sourceDir);
|
||||||
|
} catch {
|
||||||
|
// Nothing to copy yet; leave the empty directory in place.
|
||||||
|
console.info('sync-assets: no content/assets directory found yet.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await cp(sourceDir, targetDir, { recursive: true, force: true });
|
||||||
|
console.info('sync-assets: copied content/assets → public/assets.');
|
||||||
|
}
|
||||||
|
|
||||||
|
syncAssets().catch((error) => {
|
||||||
|
console.error('sync-assets: failed to mirror assets.', error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user