Initial fullstack project setup with Next.js 15, Gin, PostgreSQL and Docker Compose

- Frontend: Next.js 15 (App Router), Auth.js v5, shadcn/ui, MagicUI
- Backend: Go + Gin + GORM with layered architecture
- Auth: Local credentials login with optional Keycloak OAuth binding
- Admin: RBAC user management for admin role
- Dev: Docker Compose with hot reload for both frontend and backend
- Docker: 3-service orchestration (frontend, backend, postgres)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 15:11:20 +00:00
commit b0b85f4d3a
62 changed files with 12113 additions and 0 deletions

33
frontend/middleware.ts Normal file
View File

@@ -0,0 +1,33 @@
import { auth } from "@/auth";
import { NextResponse } from "next/server";
export default auth((req) => {
const { nextUrl } = req;
const isLoggedIn = !!req.auth;
const role = (req.auth?.user as any)?.role || "guest";
const isAuthPage = nextUrl.pathname.startsWith("/login") ||
nextUrl.pathname.startsWith("/register") ||
nextUrl.pathname.startsWith("/bind-account");
const isProtected = nextUrl.pathname.startsWith("/dashboard") ||
nextUrl.pathname.startsWith("/admin");
if (isLoggedIn && isAuthPage) {
return NextResponse.redirect(new URL("/dashboard", nextUrl));
}
if (!isLoggedIn && isProtected) {
return NextResponse.redirect(new URL("/login", nextUrl));
}
if (nextUrl.pathname.startsWith("/admin") && role !== "admin") {
return NextResponse.redirect(new URL("/unauthorized", nextUrl));
}
return NextResponse.next();
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};