infra(04-00): route /c/ → /client/, Dockerfile, Gitea deploy

- Rename src/app/c/[token] → src/app/client/[token]
- Update proxy.ts, ClientRow, admin client detail with /client/ path
- Add output: "standalone" to next.config.ts for Docker build
- Add Dockerfile (multi-stage, node:20-alpine) and .dockerignore
- Push schema to Coolify Postgres via SSH tunnel (drizzle-kit push ✓)
- Update CLAUDE.md constraint 4 to reflect /client/ route
- Add Phase 4 planning artifacts (04-00, 04-RESEARCH, 04-PATTERNS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 16:12:05 +02:00
parent 49ef45da83
commit 5bf5dfce71
21 changed files with 3164 additions and 63 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ export default async function ClientDetailPage({
</div>
<div className="flex flex-col items-end gap-2">
<a
href={`/c/${client.token}`}
href={`/client/${client.token}`}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-[#1A463C] hover:underline font-mono bg-[#1A463C]/5 px-2 py-1 rounded"
+2 -2
View File
@@ -56,12 +56,12 @@ export function ClientRow({ client }: { client: ClientWithPayments }) {
</td>
<td className="py-3 px-4">
<a
href={`/c/${client.token}`}
href={`/client/${client.token}`}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-[#1A463C] hover:underline font-mono"
>
/c/{client.token.slice(0, 8)}
/client/{client.token.slice(0, 8)}
</a>
</td>
</tr>
+3 -3
View File
@@ -29,8 +29,8 @@ export async function proxy(request: NextRequest) {
}
// ── CLIENT TOKEN GUARD ───────────────────────────────────────────────────
if (pathname.startsWith("/c/")) {
const tokenMatch = pathname.match(/^\/c\/([a-zA-Z0-9_-]+)/);
if (pathname.startsWith("/client/")) {
const tokenMatch = pathname.match(/^\/client\/([a-zA-Z0-9_-]+)/);
if (!tokenMatch) {
return NextResponse.rewrite(new URL("/not-found", request.url));
}
@@ -60,5 +60,5 @@ export async function proxy(request: NextRequest) {
}
export const config = {
matcher: ["/admin/:path*", "/c/:path*"],
matcher: ["/admin/:path*", "/client/:path*"],
};