diff --git a/app/content/[...path]/route.ts b/app/content/[...path]/route.ts new file mode 100644 index 0000000..d76a148 --- /dev/null +++ b/app/content/[...path]/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; +import { readFileSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; + +const CONTENT_DIR = join(process.cwd(), 'content'); + +const MIME_TYPES: Record = { + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png': 'image/png', + '.gif': 'image/gif', + '.webp': 'image/webp', + '.svg': 'image/svg+xml', + '.pdf': 'application/pdf', + '.txt': 'text/plain', + '.md': 'text/plain', + '.mdx': 'text/plain', +}; + +export async function GET( + _request: Request, + { params }: { params: Promise<{ path: string[] }> }, +) { + const { path } = await params; + const decodedPath = decodeURIComponent(path.join('/')); + const fullPath = join(CONTENT_DIR, decodedPath); + + if (!fullPath.startsWith(CONTENT_DIR) || !existsSync(fullPath)) { + return new NextResponse('Not found', { status: 404 }); + } + + const ext = '.' + fullPath.split('.').pop()!; + const contentType = MIME_TYPES[ext] ?? 'application/octet-stream'; + const data = readFileSync(fullPath); + + return new NextResponse(data, { + headers: { + 'Content-Type': contentType, + 'Cache-Control': 'public, max-age=31536000, immutable', + }, + }); +} diff --git a/content/posts/euler-identity.mdx b/content/posts/euler-identity.mdx index 9a01f72..7ff881f 100644 --- a/content/posts/euler-identity.mdx +++ b/content/posts/euler-identity.mdx @@ -7,7 +7,7 @@ tags: - mathematics - euler - complex-numbers -coverImage: /images/euler-cover.jpg +coverImage: /content/posts/euler-identity/euler-cover.jpg --- Euler's identity is widely regarded as the most beautiful equation in all of mathematics: diff --git a/content/posts/hello-world.mdx b/content/posts/hello-world.mdx index cca53d3..d9748c7 100644 --- a/content/posts/hello-world.mdx +++ b/content/posts/hello-world.mdx @@ -7,7 +7,7 @@ tags: - typescript - programming - tutorial -coverImage: /images/typescript-cover.jpg +coverImage: /content/posts/hello-world/typescript-cover.jpg --- Welcome to this comprehensive TypeScript tutorial! Whether you are migrating a JavaScript project or starting fresh, this guide will walk you through TypeScript's type system from fundamentals to advanced patterns used in production codebases. diff --git a/content/posts/hybrid-post.mdx b/content/posts/hybrid-post.mdx index 8f58f44..42fe178 100644 --- a/content/posts/hybrid-post.mdx +++ b/content/posts/hybrid-post.mdx @@ -8,7 +8,7 @@ tags: - signal-processing - tutorial author: James Liu -coverImage: /images/fourier-cover.jpg +coverImage: /content/posts/hybrid-post/fourier-cover.jpg --- ## Fourier Analysis: From Mathematical Theory to Python Practice diff --git a/next.config.ts b/next.config.ts index 36721af..a758e9c 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,9 +1,7 @@ import type { NextConfig } from 'next' const nextConfig: NextConfig = { - // Static export — generates out/ directory with plain HTML - output: 'export', - // Trailing slash for clean static URLs + // Trailing slash for clean URLs trailingSlash: true, // Images: unoptimized required for static export images: {