Prepend basePath to stored media URLs so assets load under /hp-prod-tracker

upload-service.ts and annotation-service.ts were storing URLs like
/api/uploads/revisions/... in the database. When the app is served at
/hp-prod-tracker, the browser needs /hp-prod-tracker/api/uploads/...
to hit the correct route.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
DJP 2026-04-08 07:47:08 -04:00
parent 5785f142fd
commit 277ad85073
2 changed files with 12 additions and 7 deletions

View file

@ -6,6 +6,8 @@ import type { CreateAnnotationInput, UpdateAnnotationInput } from "@/lib/validat
import { createFeedbackFromAnnotation } from "@/lib/services/feedback-service";
import { extractThumbnail, isFFmpegAvailable } from "@/lib/services/video-service";
const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
const VIDEO_UPLOADS_DIR =
process.env.VIDEO_UPLOADS_DIR ||
(process.env.NODE_ENV === "production"
@ -140,7 +142,7 @@ async function extractAnnotationFrameThumbnail(
const created = await extractThumbnail(videoPath, thumbPath, timestampSeconds);
if (created) {
const thumbUrl = `/api/uploads/revisions/${revisionId}/annotation_frames/${thumbFilename}`;
const thumbUrl = `${BASE_PATH}/api/uploads/revisions/${revisionId}/annotation_frames/${thumbFilename}`;
await prisma.annotation.update({
where: { id: annotationId },
data: { frameThumbnailUrl: thumbUrl },

View file

@ -11,6 +11,9 @@ import {
transcodeToHLS,
} from "@/lib/services/video-service";
/** Base path prefix so stored URLs work when the app is mounted at a sub-path */
const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
/** Images stored alongside videos in the mounted volume, served via /api/uploads */
const UPLOADS_DIR =
process.env.VIDEO_UPLOADS_DIR
@ -92,7 +95,7 @@ export async function processAndStoreImage(
const ext = file.type === "image/tiff" ? "tiff" : "png";
const filename = `${imageType}_${timestamp}.${ext}`;
const filePath = path.join(revisionDir, filename);
const url = `/api/uploads/revisions/${revisionId}/${filename}`;
const url = `${BASE_PATH}/api/uploads/revisions/${revisionId}/${filename}`;
let originalUrl: string | undefined;
@ -102,7 +105,7 @@ export async function processAndStoreImage(
const originalFilename = `${imageType}_${timestamp}_original.png`;
const originalPath = path.join(revisionDir, originalFilename);
await writeFile(originalPath, buffer);
originalUrl = `/api/uploads/revisions/${revisionId}/${originalFilename}`;
originalUrl = `${BASE_PATH}/api/uploads/revisions/${revisionId}/${originalFilename}`;
// Flatten onto white background
const flattened = await sharp(buffer)
@ -115,7 +118,7 @@ export async function processAndStoreImage(
const originalFilename = `${imageType}_${timestamp}_original.tiff`;
const originalPath = path.join(revisionDir, originalFilename);
await writeFile(originalPath, buffer);
originalUrl = `/api/uploads/revisions/${revisionId}/${originalFilename}`;
originalUrl = `${BASE_PATH}/api/uploads/revisions/${revisionId}/${originalFilename}`;
const converted = await sharp(buffer).png().toBuffer();
const pngFilename = `${imageType}_${timestamp}.png`;
@ -225,7 +228,7 @@ export async function processAndStoreVideo(
const timestamp = Date.now();
const videoFilename = `${videoType}_${timestamp}.mp4`;
const videoPath = path.join(revisionDir, videoFilename);
const videoUrl = `/api/uploads/revisions/${revisionId}/${videoFilename}`;
const videoUrl = `${BASE_PATH}/api/uploads/revisions/${revisionId}/${videoFilename}`;
// Stream-write the file to disk
const arrayBuffer = await file.arrayBuffer();
@ -241,12 +244,12 @@ export async function processAndStoreVideo(
const thumbTime = Math.min(1, metadata.duration * 0.1 || 1);
const thumbCreated = await extractThumbnail(videoPath, thumbPath, thumbTime);
const thumbnailUrl = thumbCreated
? `/api/uploads/revisions/${revisionId}/${thumbFilename}`
? `${BASE_PATH}/api/uploads/revisions/${revisionId}/${thumbFilename}`
: null;
// HLS output paths
const hlsDir = path.join(revisionDir, `${videoType}_${timestamp}_hls`);
const hlsUrl = `/api/uploads/revisions/${revisionId}/${videoType}_${timestamp}_hls/index.m3u8`;
const hlsUrl = `${BASE_PATH}/api/uploads/revisions/${revisionId}/${videoType}_${timestamp}_hls/index.m3u8`;
const uploaded: UploadedVideo = {
url: videoUrl,