Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ DATABASE_URL="mongodb://localhost:27017/test-db"
AUTH_SECRET=

# Google OAuth (create at https://console.cloud.google.com/apis/credentials)
# Redirect URI: http://localhost:3000/api/auth/callback/google
# Local redirect URI: http://localhost:3000/api/auth/callback/google
# Production redirect URI: https://<your-vercel-domain>/api/auth/callback/google
AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
AUTH_GOOGLE_SECRET=

# Resend transactional email (https://resend.com/api-keys)
RESEND_API_KEY=

# Comma-separated super-admin emails granted elevated access on deploy.
# Keep real production emails out of version control (set in Vercel only).
BSL_ADMIN_EMAIL=
10 changes: 10 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": ["next/core-web-vitals", "prettier"],
"ignorePatterns": [
"node_modules/",
".next/",
"generated/",
"playwright-report/",
"next-env.d.ts"
]
}
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: CI

# Runs on every pull request targeting main. Configure branch protection on
# `main` to require the "Lint & Build" check below so failing lint/build blocks
# merges. (That is the job's `name:`, which is what GitHub shows as the check.)
on:
pull_request:
branches: [main]

# Cancel in-progress runs for the same PR when new commits are pushed.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Lint & Build
runs-on: ubuntu-latest

# The gallery pages (/startups, /organizations, /teams) are server
# components that query MongoDB during `next build`'s static prerender
# step, so the build needs a reachable database. An ephemeral standalone
# Mongo is enough — the queries just return empty result sets in CI.
services:
mongodb:
image: mongo:7
ports:
- 27017:27017

env:
# Build-time placeholders. Real secrets live in Vercel, never in CI.
DATABASE_URL: mongodb://localhost:27017/bsl-ci
AUTH_SECRET: ci-build-placeholder-secret

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

# react-simple-maps@3 still pins React 18 as a peer, which conflicts with
# the project's React 19. --legacy-peer-deps mirrors the local install.
- name: Install dependencies
run: npm ci --legacy-peer-deps

# The generated Prisma client is gitignored, so it must be generated
# before type-checking and building.
- name: Generate Prisma client
run: npx prisma generate

- name: Lint
run: npm run lint

- name: Build
run: npm run build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ next-env.d.ts
*.tsbuildinfo
tsconfig.tsbuildinfo
playwright-report/.last-run.json
.DS_Store
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ import { Button } from "@/components/ui/button";

### Prisma Client Import

The generated Prisma client lives in `generated/prisma/client`. When importing types directly:
The generated Prisma client is exported from `@prisma/client`. When importing types directly:
```typescript
import { Prisma } from "@/generated/prisma/client";
import { Prisma } from "@prisma/client";
```

## Environment Variables
Expand Down
2 changes: 1 addition & 1 deletion app/admin/(authenticated)/access-denied/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default function AccessDeniedPage() {
<div className="w-full max-w-sm space-y-8 p-8 text-center">
<h1 className="text-2xl font-bold text-gray-900">Access Denied</h1>
<p className="mt-2 text-sm text-gray-500">
You don't have permission to view this page.
You don&apos;t have permission to view this page.
</p>
<button
onClick={() => signOut({ callbackUrl: "/admin/login" })}
Expand Down
2 changes: 1 addition & 1 deletion app/api/admin/applications/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from "next/server";
import { Prisma } from "@/generated/prisma/client";
import { Prisma } from "@prisma/client";
import { prisma } from "@/lib/prisma";
import { auth } from "@/auth";
import { hasRole } from "@/lib/rbac";
Expand Down
Loading