Skip to content

Feature/nextjs migration#7

Closed
Stevenjoelrs wants to merge 21 commits into
mainfrom
feature/nextjs-migration
Closed

Feature/nextjs migration#7
Stevenjoelrs wants to merge 21 commits into
mainfrom
feature/nextjs-migration

Conversation

@Stevenjoelrs

Copy link
Copy Markdown
Owner

No description provided.

Steven Joel Ramos Salazar and others added 21 commits May 14, 2026 08:15
- Add packageManager field (pnpm@11.1.1) to package.json
- Add preinstall guard to block npm/yarn usage
- Add .npmrc with strict isolation (hoist=false, ignore-scripts)
- Gitignore package-lock.json and yarn.lock
- Update README dev commands to pnpm
- Migrate from SvelteKit to Next.js 15 (App Router + Turbopack)
- Create Prisma schema with 15 models (PostgreSQL) from orbital-ctf
- Implement macOS-style terminal window shell (TerminalWindow component)
- Add file tree sidebar with challenge categories as directories
- Port CRT effects from orbital-ctf (scanlines, phosphor, flicker, glow)
- Add CRT settings toggles with localStorage persistence
- Set up NextAuth with credentials provider and JWT sessions
- Create status bar footer, landing page with ASCII banner
- Configure admin route protection middleware

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a Next.js (App Router) migration for CTFrbt, including UI pages/components, NextAuth credentials-based authentication, Prisma/Postgres persistence, and a basic admin + gameplay API surface.

Changes:

  • Adds Next.js app structure (layout, pages, global CRT styles) and core UI components (terminal shell, sidebar, challenge view).
  • Implements auth + core gameplay APIs (register/sign-in, challenges, submissions/scoring, hints, teams, file downloads, leaderboard).
  • Adds Prisma schema/migration/seed plus project tooling/config (TypeScript, ESLint, pnpm, Docker).

Reviewed changes

Copilot reviewed 44 out of 48 changed files in this pull request and generated 21 comments.

Show a summary per file
File Description
tsconfig.json Adds TypeScript config suitable for Next.js App Router.
src/types/next-auth.d.ts Adds NextAuth type augmentation for custom user/session/JWT fields.
src/middleware.ts Adds middleware to protect /api/admin/* routes.
src/lib/prisma.ts Adds Prisma client singleton wiring for Next.js runtime.
src/lib/auth.ts Adds NextAuth credentials provider + callbacks.
src/components/TerminalWindow.tsx Implements terminal-style app shell container.
src/components/StatusBar.tsx Adds bottom status bar UI.
src/components/Sidebar.tsx Adds explorer-style sidebar navigation tree.
src/components/Providers.tsx Adds NextAuth SessionProvider wrapper.
src/components/CRTSettings.tsx Adds client-side CRT effect toggle UI + persistence.
src/components/ChallengeView.tsx Adds challenge details, file downloads, flag submission, hints UI.
src/app/scoreboard/page.tsx Adds client scoreboard page fetching /api/leaderboard.
src/app/rules/page.tsx Adds rules page fetching /api/rules.
src/app/profile/page.tsx Adds profile/team management page backed by /api/teams.
src/app/page.tsx Adds landing page with links to auth/rules.
src/app/layout.tsx Adds root layout with fonts, session bootstrap, toaster, app shell.
src/app/globals.css Adds global CRT/terminal UI styling.
src/app/dashboard/page.tsx Adds dashboard page fetching challenges and rendering ChallengeView.
src/app/auth/signup/page.tsx Adds registration UI backed by /api/auth/register.
src/app/auth/signin/page.tsx Adds credentials sign-in UI via NextAuth signIn.
src/app/api/teams/route.ts Adds API to create/join teams and fetch team info.
src/app/api/submissions/route.ts Adds flag submission API with scoring + rate limiting.
src/app/api/rules/route.ts Adds API to fetch rules from site config.
src/app/api/leaderboard/route.ts Adds API to compute team rankings.
src/app/api/hints/route.ts Adds APIs for listing/purchasing hints.
src/app/api/files/[fileId]/route.ts Adds API to download challenge files by ID.
src/app/api/challenges/route.ts Adds API to list challenges grouped by category + solved/unlocked enrichment.
src/app/api/auth/register/route.ts Adds registration endpoint (bcrypt hash + alias uniqueness).
src/app/api/auth/[...nextauth]/route.ts Adds NextAuth route handler exports.
src/app/api/announcements/route.ts Adds announcements listing endpoint.
src/app/api/admin/game/route.ts Adds admin game config read/write endpoint.
src/app/api/admin/challenges/route.ts Adds admin challenge list/create endpoint.
src/app/api/admin/challenges/[id]/route.ts Adds admin challenge update/delete endpoint.
src/app/api/admin/announcements/route.ts Adds admin announcement creation endpoint.
src/app/admin/page.tsx Adds admin panel UI for challenges/game config/announcements.
README.md Adds project overview + dev workflow commands.
prisma/seed.ts Adds seed data for users/teams/challenges/rules/game config.
prisma/schema.prisma Adds Prisma data model for platform entities.
prisma/migrations/migration_lock.toml Adds Prisma migration lock file.
prisma/migrations/20260611062951_ctfrbt/migration.sql Adds initial DB migration SQL for schema.
pnpm-workspace.yaml Adds pnpm workspace config for allowed builds.
package.json Adds scripts and dependencies for Next.js/Prisma/NextAuth stack.
next.config.ts Adds Next.js config scaffold.
eslint.config.mjs Adds ESLint flat config for Next.js.
docker-compose.yml Adds local Postgres service for development.
.gitignore Adds ignores for Next.js/Node/Prisma artifacts and env files.
.env.example Adds environment variable template for DB + NextAuth.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +30
try {
const filePath = path.join(process.cwd(), "public", file.path);
const fileBuffer = await readFile(filePath);

return new NextResponse(fileBuffer, {
headers: {
"Content-Type": "application/octet-stream",
"Content-Disposition": `attachment; filename="${file.name}"`,
"Content-Length": String(fileBuffer.length),
},
});
Comment on lines +82 to +84
// Generate a random invite code
const code = Math.random().toString(36).substring(2, 10).toUpperCase();

Comment on lines +64 to +88
if (!teamName || teamName.length > 32) {
return NextResponse.json(
{ error: "Team name is required (max 32 chars)" },
{ status: 400 }
);
}

const existingTeam = await prisma.team.findUnique({
where: { name: teamName },
});

if (existingTeam) {
return NextResponse.json(
{ error: "Team name is already taken" },
{ status: 409 }
);
}

// Generate a random invite code
const code = Math.random().toString(36).substring(2, 10).toUpperCase();

const team = await prisma.team.create({
data: {
name: teamName,
code,
hints,
} = body;

if (!title || !description || !points || !category || !difficulty) {
Comment on lines +24 to +33
// Rate limiting
const now = Date.now();
const lastTime = lastSubmission.get(session.user.id);
if (lastTime && now - lastTime < RATE_LIMIT_MS) {
const waitSec = Math.ceil((RATE_LIMIT_MS - (now - lastTime)) / 1000);
return NextResponse.json(
{ error: `Rate limited. Wait ${waitSec}s before submitting again.` },
{ status: 429 }
);
}
Comment thread .env.example
Comment on lines +1 to +2
# Database — PostgreSQL connection string
DATABASE_URL="postgresql://ctfrbt:ctfrbt@localhost:5432/ctfrbt"
Comment on lines +114 to +118
if (hint.cost > 0) {
const updatedTeam = await prisma.team.update({
where: { id: session.user.teamId },
data: { score: { decrement: hint.cost } },
});
Comment on lines +12 to +18
const file = await prisma.challengeFile.findUnique({
where: { id: fileId },
});

if (!file) {
return NextResponse.json({ error: "File not found" }, { status: 404 });
}
Comment on lines +79 to +82
isLocked,
isSolved: solvedChallengeIds.includes(challenge.id),
solveCount: challenge._count.submissions,
multipleFlags: challenge.multipleFlags,
Comment on lines +20 to +27
children: [
{ label: "web", icon: "folder", href: "/categories/web" },
{ label: "crypto", icon: "folder", href: "/categories/crypto" },
{ label: "pwn", icon: "folder", href: "/categories/pwn" },
{ label: "forensics", icon: "folder", href: "/categories/forensics" },
{ label: "reverse", icon: "folder", href: "/categories/reverse" },
{ label: "misc", icon: "folder", href: "/categories/misc" },
],
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants