Skip to content

josephbrockw/connexus

Repository files navigation

A conference platform for browsing, registering, and managing tech conferences.

What It Does

ConNexus lets users:

  • Browse and search conferences with real-time filtering
  • Register for conferences with form validation
  • Favorite conferences for later
  • Manage their profile and registrations
  • View upcoming and past events

Admins can:

  • Create and edit conferences
  • Manage attendee registrations
  • Track conference capacity and stats

Tech Stack

  • Framework: Next.js 15.5.5 with App Router
  • Database: PostgreSQL with Prisma ORM
  • Authentication: NextAuth.js v4 with GitHub OAuth
  • Styling: Tailwind CSS v4
  • Language: TypeScript throughout

Getting Started

Prerequisites

  • Node.js 20+
  • PostgreSQL database (or use a hosted option like Supabase/Neon)
  • GitHub OAuth app for authentication

Setup

  1. Clone and install dependencies:
git clone git@github.com:josephbrockw/connexus.git
cd connexus
npm install
  1. Start the local PostgreSQL database:
docker-compose up -d
  1. Set up your environment variables in .env.local:
# Database (matches docker-compose.yml)
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/myapp_dev"
DIRECT_DATABASE_URL="postgresql://postgres:postgres@localhost:5432/myapp_dev"

# NextAuth
NEXTAUTH_URL="http://localhost:3001"
NEXTAUTH_SECRET="your-secret-key-here"

# GitHub OAuth (create at github.com/settings/developers)
GITHUB_ID="your-github-oauth-id"
GITHUB_SECRET="your-github-oauth-secret"

# App
NEXT_PUBLIC_APP_URL="http://localhost:3001"
  1. Set up the database:
npx prisma generate
npx prisma migrate deploy
npm run db:seed  # Optional: adds sample data
  1. Run the dev server:
npm run dev

Open http://localhost:3001 to see it running.

Architecture Decisions

Here are some of the key patterns I implemented and why:

API Client Layer

I extracted all fetch calls into dedicated API clients (/src/lib/api/):

Why: Every component was doing its own error handling, JSON parsing, and header management. This was repetitive and hard to maintain.

What I built:

  • apiClient.ts - Base fetch wrapper with automatic error handling
  • conferenceApi.ts - All conference-related endpoints
  • favoriteApi.ts - Favorite toggle operations
  • adminApi.ts - Admin CRUD operations
  • userApi.ts - User profile management

Benefits:

  • Changed error handling once, fixed it everywhere
  • Type-safe API responses
  • Easy to mock for testing
  • Centralized place to add auth headers or logging

Trade-off: Added about 280 lines of code to save 44 lines in components. Net increase, but the maintenance win is worth it if the codebase grows.

Custom Hooks

I created reusable hooks for common patterns (/src/hooks/):

Why: Components were duplicating state management logic, especially for pagination and debouncing.

What I built:

  • useDebounce - Delays updates (for search inputs)
  • useInfiniteScroll - Generic infinite scroll pagination

Benefits:

  • Infinite scroll is reusable for any future data lists
  • Debouncing prevents excessive API calls
  • Easier to test business logic separately from UI

Trade-off: Added about 150 lines of hook code.

Authentication Pattern

I used NextAuth v4 without middleware:

Why: Middleware can be tricky with Next.js App Router, and with such a small application, it's not worth the complexity.

How it works:

  • Each protected page calls getServerSession(authOptions) server-side
  • If no session, redirect to /api/auth/signin
  • Client components use useSession() for conditional rendering

Benefits:

  • Explicit and predictable
  • No mysterious middleware redirects
  • Easy to debug

Trade-off: Have to remember to add the auth check to every protected page. Middleware would be automatic but less flexible.

Server-Side Filtering

Filtering happens in the API route, not the client:

Why: Started with client-side filtering, but realized I'd eventually load all conferences which doesn't scale.

How it works:

  • Client sends filter params to /api/conferences/search
  • Server filters in the database query
  • Returns paginated results using limit and offset pattern

Benefits:

  • Can handle thousands of conferences
  • Faster initial page load
  • Reduces bandwith (only sends data for visible items)
  • Consistent number of items rendered initially

Type Safety

I used TypeScript strictly with shared types (/src/types/):

Why: Wanted to catch bugs at compile time, not runtime.

Patterns:

  • Shared interfaces for Conference, User, Registration
  • API response types
  • Form data types
  • Validation schemas

Benefits:

  • Autocomplete everywhere
  • Refactoring is safer
  • Bugs caught before deployment

Trade-off: More verbose code. Have to update types when schema changes.

Error Handling

I implemented root-level error boundaries using Next.js App Router conventions:

What I built:

  • error.tsx - Catches runtime errors with a "Try Again" button that resets the error boundary
  • not-found.tsx - Handles 404 pages with a "Go Home" link

Benefits:

  • Users see branded error pages instead of white screens
  • Error boundary allows recovery without full page refresh
  • Both pages use the theme system (light/dark mode support)
  • Development mode shows error messages for debugging

Trade-off: Only root-level boundaries. Errors crash the whole app instead of isolated sections.

Database Schema

I used Prisma with PostgreSQL. Main models:

  • User - User accounts with GitHub OAuth
  • Conference - Events with dates, pricing, capacity
  • Registration - User registrations with contact info
  • Favorite - Saved conferences per user
  • Account/Session - NextAuth tables

Key relationships:

  • User has many Registrations and Favorites
  • Conference has many Registrations and Favorites
  • Cascading deletes when conferences are removed

Check prisma/schema.prisma for the full schema.

Project Structure

src/
├── app/                    # Next.js App Router pages
│   ├── api/               # API routes
│   ├── admin/             # Admin dashboard
│   ├── auth/              # Auth pages
│   └── dashboard/         # User dashboard
├── components/
│   ├── conference/        # Conference-specific components
│   ├── dashboard/         # Dashboard components
│   ├── admin/            # Admin components
│   ├── forms/            # Reusable form inputs
│   ├── ui/               # Generic UI components
│   └── providers/        # React context providers
├── lib/
│   ├── api/              # API client layer
│   ├── filterConferences.ts
│   ├── validation.ts     # Form validators
│   └── admin.ts          # Admin utilities
├── hooks/                # Custom React hooks
├── types/                # TypeScript definitions
├── config/               # App configuration
└── db/                   # Prisma client

Scripts

npm run dev               # Start dev server (localhost:3001)
npm run build             # Production build
npm start                 # Run production server
npm run lint              # Run ESLint
npm run db:seed           # Seed database with sample data
npm run db:seed:large     # Seed database with large sample data
npx prisma studio         # Open database GUI
npx prisma migrate dev    # Create new migration

What I'd Improve Next

If I kept working on this, here's what I'd tackle:

Better error handling:

  • Toast notifications instead of alert()
  • Add route-specific error boundaries (e.g. /dashboard/error.tsx, /admin/error.tsx) to isolate failures
  • Retry logic for failed API calls
  • Error logging service integration

Testing:

  • Unit tests for API clients and hooks
  • Integration tests for critical flows (registration, favorites)
  • E2E tests for happy paths

Performance:

  • Add data caching and background refetch
  • Optimize images with proper sizing and lazy loading
  • Consider virtual scrolling for long conference lists

Better validation:

  • Replace custom validators with Zod
  • Share validation schema between client and server
  • More specific error messages

Search improvements:

  • Full-text search in PostgreSQL
  • Search by location/date range
  • "No results" suggestions

Admin features:

  • Bulk operations (delete multiple, export data)
  • Conference analytics dashboard
  • Email attendees functionality

Accessibility:

  • Keyboard navigation audit
  • Screen reader testing
  • Better focus management in modals

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors