Skip to content

Commit 27e1653

Browse files
mxkaskeclaude
andauthored
fix: restore registry json on vercel cache hit (#74)
The registry JSON files were missing from production deployments (fixes #73) because turbo's registry:build cache only restores files inside packages/registry/public/r/, while copy-to-web.mjs also wrote to apps/web/public/r/ — an output path outside the task's package scope. When Vercel hit the remote cache, the copy script didn't re-run and apps/web/public/r/ was left empty, so /r/*.json returned 404. Move the cross-package copy into web:build and declare public/r/** as a web:build output so the files are cached and restored alongside .next/. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ec6ab8a commit 27e1653

4 files changed

Lines changed: 50 additions & 11 deletions

File tree

apps/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"dev": "next dev",
7-
"build": "next build",
7+
"build": "node scripts/copy-registry.mjs && next build",
88
"start": "next start",
99
"lint": "eslint .",
1010
"typecheck": "tsc --noEmit",

apps/web/scripts/copy-registry.mjs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Copies the built registry JSON from packages/registry/public/r/ into
5+
* apps/web/public/r/ so Next.js can serve them at /r/*.json.
6+
*
7+
* Running this as part of web:build (instead of registry:build) means the
8+
* files land in web:build's turbo cache outputs and get restored on cache
9+
* hit — otherwise apps/web/public/r/ is empty on Vercel when registry:build
10+
* hits the remote cache and its script doesn't re-execute.
11+
*/
12+
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
13+
import { dirname, join } from "node:path";
14+
import { fileURLToPath } from "node:url";
15+
16+
const __dirname = dirname(fileURLToPath(import.meta.url));
17+
const WEB_DIR = join(__dirname, "..");
18+
const REGISTRY_R = join(
19+
WEB_DIR,
20+
"..",
21+
"..",
22+
"packages",
23+
"registry",
24+
"public",
25+
"r",
26+
);
27+
const WEB_R = join(WEB_DIR, "public", "r");
28+
29+
if (!existsSync(REGISTRY_R)) {
30+
console.error(
31+
"No packages/registry/public/r/ found. Did registry:build run?",
32+
);
33+
process.exit(1);
34+
}
35+
36+
rmSync(WEB_R, { recursive: true, force: true });
37+
mkdirSync(WEB_R, { recursive: true });
38+
cpSync(REGISTRY_R, WEB_R, { recursive: true });
39+
40+
console.log("Registry output copied to apps/web/public/r/");
Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#!/usr/bin/env node
22

33
/**
4-
* Copies the shadcn build output from dist/public/r/ to:
5-
* - packages/registry/public/r/ (canonical location)
6-
* - apps/web/public/r/ (served by Next.js)
4+
* Copies the shadcn build output from dist/public/r/ to
5+
* packages/registry/public/r/ (the canonical registry output location).
6+
*
7+
* apps/web copies from here during its own build so the JSON files become
8+
* part of web:build's turbo cache — see apps/web/scripts/copy-registry.mjs.
79
*/
810
import { cpSync, existsSync, mkdirSync } from "node:fs";
911
import { dirname, join } from "node:path";
@@ -13,16 +15,13 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
1315
const ROOT_DIR = join(__dirname, "..");
1416
const DIST_R = join(ROOT_DIR, "dist", "public", "r");
1517
const LOCAL_R = join(ROOT_DIR, "public", "r");
16-
const WEB_R = join(ROOT_DIR, "..", "..", "apps", "web", "public", "r");
1718

1819
if (!existsSync(DIST_R)) {
1920
console.error("No dist/public/r/ found. Did shadcn build run?");
2021
process.exit(1);
2122
}
2223

23-
for (const dest of [LOCAL_R, WEB_R]) {
24-
mkdirSync(dest, { recursive: true });
25-
cpSync(DIST_R, dest, { recursive: true });
26-
}
24+
mkdirSync(LOCAL_R, { recursive: true });
25+
cpSync(DIST_R, LOCAL_R, { recursive: true });
2726

28-
console.log("Registry output copied to public/r/ and apps/web/public/r/");
27+
console.log("Registry output copied to public/r/");

turbo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"tasks": {
44
"build": {
55
"dependsOn": ["^build", "^registry:build"],
6-
"outputs": [".next/**", "!.next/cache/**"]
6+
"outputs": [".next/**", "!.next/cache/**", "public/r/**"]
77
},
88
"registry:build": {
99
"outputs": ["public/r/**"]

0 commit comments

Comments
 (0)