This is a Next.js project bootstrapped with create-next-app.
GatherU is a campus and community events platform for discovering, creating, and booking local events in one place. It is designed to help students browse upcoming meetups, workshops, hackathons, and social events, while also giving organizers a simple way to publish new events with images and structured details.
The app includes:
- a homepage with featured events
- an events listing page
- an event detail page with booking support
- a create-event flow with image upload
This project uses the App Router and modern Next.js 16 caching features.
cacheComponents: trueis enabled in next.config.ts.- This turns on the current Cache Components model used by
use cache.
The project caches database reads at the function level in lib/actions/event.actions.ts:
getEvents()getEventBySlug(slug)
Each of these uses:
'use cache'to cache the async function resultcacheLife('hours')to define the cache profilecacheTag(...)to tag cached event data
This follows the current Next.js 16 recommendation of caching the data function itself instead of having Server Components fetch the app's own API routes.
This project uses tag-based invalidation so cached event data can refresh after writes:
- lib/actions/booking.actions.ts uses
updateTag(...)inside a Server Action after a booking is created - app/api/events/route.ts uses
revalidateTag(..., 'max')inside the Route Handler after an event is created
The difference is intentional:
updateTag()is the modern choice for immediate read-your-own-writes behavior in Server ActionsrevalidateTag(..., 'max')is the recommended Route Handler pattern and uses stale-while-revalidate semantics
The project also uses several current App Router conventions:
- dynamic routing with app/events/[slug]/page.tsx
- route-level loading UI with app/events/[slug]/loading.tsx
- route-level not-found UI with app/events/[slug]/not-found.tsx
- metadata-based app icons via app/icon.png and app/favicon.ico
When the app reads event data:
- MongoDB is queried through cached server functions
- repeated requests can reuse cached results
- tags let related pages share the same cached data
When the app writes event data:
- creating an event revalidates
eventsandevent:${slug} - creating a booking updates
eventsandevent:${slug}
That means event lists and event detail pages refresh using the current Next.js 16 cache model instead of older unstable_cache-based patterns.
- Next.js 16.2.1 App Router
- React 19
- TypeScript
- Tailwind CSS 4
next/imageandnext/link- client components for interactive forms like booking and event creation
- Next.js Route Handlers for API endpoints
- Server Actions for booking mutations
- MongoDB with Mongoose
- hybrid image uploads:
local fallback to
public/imagesduring development and Vercel Blob whenBLOB_READ_WRITE_TOKENis available
/Home page with featured events/eventsEvent listing page/events/createCreate event page with local image upload/events/[slug]Event detail page
- app/page.tsx
- app/events/page.tsx
- app/events/create/page.tsx
- app/events/[slug]/page.tsx
- app/events/[slug]/loading.tsx
- app/events/[slug]/not-found.tsx
GET /api/eventsReturns all eventsGET /api/events/[slug]Returns a single event by slugPOST /api/eventsCreates a new event and uploads its image either to local storage or Vercel Blob
Booking is handled through a Server Action instead of a public /api/bookings route.
When a user submits the booking form on an event detail page, the client component calls the createBooking(...) Server Action, which writes the booking into MongoDB and updates related cache tags.
- Open an event detail page at
/events/[slug] - Enter an email address in the booking form
- Click
Submit - The app creates a booking record for that event
- The booking count on the page updates after the mutation
This project supports a hybrid upload flow for event images.
Behavior:
- if
BLOB_READ_WRITE_TOKENis available, uploads are stored in Vercel Blob - otherwise, uploads fall back to the local filesystem under
public/images
In practice:
- local development works without Vercel Blob because files can still be written to
public/images - production on Vercel should use Vercel Blob so uploaded images persist reliably
This means the app can keep working locally while also being ready for deployment on Vercel once BLOB_READ_WRITE_TOKEN is configured.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.