The all-in-one academic companion for college students.
Track attendance, monitor submissions, and sync your Google Classroom — all in one place.
UniBuddy pulls your courses and assignments straight from Google Classroom and gives you a clean dashboard to manage everything that actually matters in college — without juggling five different apps.
| Dashboard | Today's classes, pending submissions, and attendance percentages at a glance |
| Timetable | Build your weekly schedule with multi-day class slots |
| Attendance | Log and track attendance per subject with percentage summaries |
| Subjects | Set up subjects with credits, codes, and link them to Classroom courses |
| Submissions | See all pending and submitted coursework with due dates |
| Settings | Manage your account and trigger a Classroom sync |
| Layer | Technology |
|---|---|
| Framework | Next.js 15 — App Router, React Server Components, Server Actions |
| Language | TypeScript 5 |
| Auth | NextAuth v5 — Google OAuth, database-backed sessions |
| Database | PostgreSQL via Supabase, managed with Prisma ORM |
| Styling | Tailwind CSS v4 |
| Deployment | Vercel (Edge + Serverless) |
| External API | Google Classroom API (read-only) |
Browser
│
├─► middleware.ts Lightweight session-cookie check before protected routes
│
├─► /app/* React Server Components — fetch data server-side
│ └─► lib/data.ts userId-scoped Prisma queries
│ └─► lib/actions.ts Server Actions, all guarded by requireUserId()
│
├─► /api/auth/* NextAuth v5 — Google OAuth callback, session management
│
└─► lib/classroom.ts Google Classroom API — syncs courses & assignments
│
Supabase PostgreSQL (ap-south-1)
- Node.js 18+
- A Google Cloud project with Google Classroom API enabled
- A Supabase project (free tier works)
git clone https://github.com/itej13/UniBuddy.git
cd UniBuddy/web
npm installcp .env.example .env.localFill in .env.local — see the Environment Variables section below.
npm run devOpen http://localhost:3000.
Create web/.env.local with the following:
| Variable | Description |
|---|---|
AUTH_GOOGLE_ID |
OAuth 2.0 Web Application client ID from Google Cloud Console |
AUTH_GOOGLE_SECRET |
OAuth 2.0 client secret |
AUTH_SECRET |
Random 32-byte secret — generate with openssl rand -base64 32 |
AUTH_URL |
App base URL — http://localhost:3000 for local dev |
DATABASE_URL |
Supabase transaction pooler URL (port 6543) |
DIRECT_URL |
Supabase direct connection URL (port 5432) — used for migrations only |
Never commit
.env.local. It is gitignored by default.
- Go to APIs & Services → Credentials
- Enable the Google Classroom API
- Create an OAuth 2.0 credential — type: Web application
- Add to Authorized redirect URIs:
http://localhost:3000/api/auth/callback/google https://your-app.vercel.app/api/auth/callback/google - Add to Authorized JavaScript origins:
http://localhost:3000 https://your-app.vercel.app
- Create a project at supabase.com
- Go to Settings → Database → Connection string
- Copy the Transaction URL (port 6543) →
DATABASE_URL - Copy the Direct connection URL (port 5432) →
DIRECT_URL - Apply the schema:
npm run db:push
UniBuddy/
└── web/ Next.js application
├── prisma/
│ ├── schema.prisma Database schema (PostgreSQL)
│ └── migrations/ SQL migration history
├── src/
│ ├── app/ Routes (App Router)
│ │ ├── dashboard/
│ │ ├── subjects/
│ │ ├── timetable/
│ │ ├── attendance/
│ │ ├── submissions/
│ │ ├── settings/
│ │ └── api/auth/ NextAuth route handler
│ ├── components/
│ │ ├── app-shell.tsx Navigation layout
│ │ ├── auth-gate.tsx Sign-in screen
│ │ ├── views.tsx Page-level view components
│ │ └── ui.tsx Shared UI primitives
│ ├── lib/
│ │ ├── actions.ts Server Actions (CRUD + Classroom sync)
│ │ ├── data.ts Data fetching (userId-scoped)
│ │ ├── classroom.ts Google Classroom API client
│ │ ├── domain.ts Business logic utilities
│ │ └── prisma.ts Prisma client singleton
│ ├── auth.ts NextAuth v5 configuration
│ └── middleware.ts Route-level auth middleware
├── .env.example Environment variable template
└── next.config.ts Security headers + Next.js config
npm run db:migrate # Create and apply a new migration (development)
npm run db:migrate:prod # Apply pending migrations (production / CI)
npm run db:push # Push schema changes without migration files
npm run db:studio # Open Prisma Studio (visual DB browser)GitHub Actions runs the same checks used before release on every push and pull request:
cd web
npm ci
npm run lint
npm run buildStudent data privacy is a first-class concern. Here's how it's enforced:
- Database-backed sessions — session tokens are opaque references stored in PostgreSQL; no user data is embedded in cookies or JWTs
- Server-side token storage — Google OAuth access and refresh tokens never leave the server or appear in client-side state
- Row-level data isolation — every Prisma query includes
where: { userId }, making cross-user data access impossible at the application layer - Route protection —
middleware.tschecks for a valid session cookie on every protected request;requireUserId()in Server Actions enforces auth a second time - Read-only Classroom scopes — the app requests
classroom.courses.readonly,classroom.coursework.me.readonly, andclassroom.student-submissions.me.readonly; it cannot modify any Classroom data - HTTP security headers — Content-Security-Policy, HSTS (2-year max-age), X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy
The app deploys automatically on every push to main via Vercel.
To deploy manually:
npm exec --package=vercel -- vercel deploy --prodSet all environment variables listed above in your Vercel project settings (Settings → Environment Variables).
- Fork the repo
- Create a branch:
git checkout -b feature/your-feature - Make your changes and commit
- Open a pull request against
main
Built by Tejas Das