Evently β€” Documentation

A complete, production-ready Event Management System and ticketing platform built with Next.js 16, React 19, TypeScript, and MongoDB. This guide walks you through installation, configuration, architecture, and the full REST API.

Next.js 16 Β· App Router React 19 TypeScript MongoDB + Mongoose Tailwind CSS v4 NextAuth v5

What is this?

Evently is a full-stack template that ships two products in one codebase:

🌐 Public Events Website

A polished, SEO-ready marketing site with a dynamic landing page, event catalogue, event detail & registration, speaker and venue directories, a job board, certificate verification, testimonials, newsletter, and contact forms.

πŸ› οΈ Management Dashboards

Role-based dashboards for Super Admins and Organizers β€” events, sessions, tickets, registrations, waitlists, speakers, sponsors, exhibitors, venues, badges, certificates, expenses, CRM, subscriptions, and full site settings β€” plus an attendee area, all backed by a typed REST API.

Tip: The full rendered version of this documentation is also available inside the running app at the /documentation route.

Features

🎫 Events & Ticketing

Create, publish and cancel events with drafts. Multiple ticket tiers per event with pricing, quantity, sale windows, and per-order limits.

πŸ“ Registrations

Attendee registration with unique confirmation codes, quantity, totals, coupon discounts, and a guarded status workflow.

⏳ Waitlists

Automatic waitlisting for sold-out events with a 48-hour notification hold, conversion to registration, and expiry via cron.

πŸ—“οΈ Sessions & Agenda

Multi-track agendas with rooms, time windows, concurrent sessions, and speaker assignments.

🎀 Speakers & Sponsors

Speaker profiles with bios and socials; tiered sponsors (platinum→partner) and exhibitor booth management.

🏟️ Venues

Venue directory with type (indoor / outdoor / virtual / hybrid), capacity, amenities and location.

βœ… Check-in & Badges

QR-based or manual check-in with digital badges (VIP / sponsor flags, custom templates).

πŸ“œ Certificates

Issue post-event certificates (workshop / training / webinar / conference) with a public verification endpoint.

πŸ‘₯ Roles & Dashboards

Three roles β€” Super Admin, Organizer, Attendee β€” each with a dedicated dashboard and middleware-protected routes.

πŸ’³ Subscriptions & Plans

Organizer subscription plans (monthly / yearly / one-time) with feature limits and status (active / trialing / canceled / expired).

πŸ“Š Analytics

Revenue, registrations, occupancy and expense reporting with charts on the Super Admin and Organizer dashboards.

🀝 CRM & Job Board

Lightweight CRM for organizer contacts, plus a public careers page with an application pipeline (new β†’ hired).

🎨 Dynamic Landing Page

Hero, features, testimonials, team, FAQ, newsletter and branding β€” all editable from the admin without touching code.

πŸ€– AI Event Templates

Template-driven event creation with suggested titles, descriptions, ticket tiers, agenda items and SEO keywords.

πŸ›‘οΈ Audit Logging

Every sensitive action recorded with actor, resource, IP and details (auto-expires after 365 days).

Tech Stack

LayerTechnologyNotes
FrameworkNext.js 16.2 (App Router, Turbopack)Server Components, Route Handlers, middleware
UI RuntimeReact 19Latest concurrent React
LanguageTypeScriptStrict, fully typed models & APIs
DatabaseMongoDB + Mongoose 8Schema models in /model
AuthNextAuth v5 + JWT (jsonwebtoken)Session for pages, Bearer JWT for API
StylingTailwind CSS v4CSS variables, dark mode via next-themes
UI ComponentsRadix UI + shadcn-style componentsIn /components/ui
FormsReact Hook Form + ZodShared schemas in lib/validation-schema
TablesTanStack Table + dnd-kitReusable data-table in /components/data-table
ChartsRechartsDashboard & report analytics
AnimationFramer MotionLanding-page motion
MediaCloudinary + react-dropzoneImage hosting & uploads
PDF / QRjsPDF + qrcodeBadges, certificates, exports
EmailNodemailer (SMTP)Transactional mail
EditorTipTap / SunEditorRich-text for legal & content
StateZustandUser, breadcrumb & table stores
Package ManagerpnpmUse pnpm for installs

Requirements

Before installing, make sure you have the following available:

  • Node.js 18.18+ (Node 20 LTS or newer recommended).
  • pnpm β€” install with npm install -g pnpm.
  • MongoDB database β€” a free MongoDB Atlas cluster or a local mongod instance.
  • Cloudinary account (optional, for image uploads) β€” configured later from the admin panel.
  • SMTP credentials (optional, for email) β€” e.g. Gmail App Password, SendGrid, Mailgun.

Note: Cloudinary and SMTP are not required to boot the app. You can configure them later from Super Admin β†’ Settings. The build itself does not require a reachable database.

Quick Start

  1. Unzip & install dependencies

    # from the project root
    pnpm install
  2. Create your environment file

    Copy the example and fill in the values (see Environment Variables).

    cp .env.example .env.local
  3. Run the development server

    pnpm dev

    Open http://localhost:3000 β€” the public site loads. Staff dashboards live at /super-admin and /organizer; attendees use /attendee.

  4. Build for production

    pnpm build
    pnpm start
ScriptCommandPurpose
devnext dev --turbopackLocal development with hot reload
buildnext build --turbopackProduction build
startnext startServe the production build
linteslintLint the codebase
generate-postmannode scripts/generate-postman.jsRegenerate the Postman API collection

Environment Variables

Create .env.local in the project root. Required keys are marked below.

# ── Core ──────────────────────────────────────────────
MONGODB_URI="mongodb+srv://user:pass@cluster.mongodb.net/event-management"
AUTH_SECRET="a-long-random-secret-string"
NEXTAUTH_SECRET="a-long-random-secret-string"
NEXTAUTH_URL="http://localhost:3000"
AUTH_TRUST_HOST="true"
JWT_SECRET="a-long-random-secret-string"

# ── Public URLs ───────────────────────────────────────
NEXT_PUBLIC_SITE_URL="http://localhost:3000"
NEXT_API_URL="http://localhost:3000"

# ── Cron (waitlist expiry authorization) ──────────────
CRON_SECRET="a-random-cron-secret"

# ── SMTP fallback (optional β€” preferably set in admin Settings) ──
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_SECURE="false"
SMTP_USER="you@gmail.com"
SMTP_PASS="your-app-password"
FROM_EMAIL="you@gmail.com"
FROM_NAME="Evently"

# ── Cloudinary (optional β€” preferably set in admin Settings) ──
CLOUDINARY_CLOUD_NAME=""
CLOUDINARY_API_KEY=""
CLOUDINARY_API_SECRET=""
VariableRequiredDescription
MONGODB_URIβœ… YesMongoDB connection string. The app uses the database template-event-management (set in config/database.ts).
AUTH_SECRET / NEXTAUTH_SECRETβœ… YesSecret used to sign sessions. Generate with openssl rand -base64 32.
JWT_SECRETβœ… YesSecret used to sign the API Bearer JWTs.
NEXTAUTH_URL / AUTH_TRUST_HOSTβœ… YesCanonical app URL + trust the deployment host.
NEXT_PUBLIC_SITE_URL / NEXT_API_URLRecommendedAbsolute URLs for metadata, sitemap, and server-side fetches.
CRON_SECRETRecommendedAuthorizes the waitlist-expiry cron endpoint.
SMTP_* / CLOUDINARY_*OptionalFallbacks when the corresponding admin Settings are empty.

Important: SMTP and Cloudinary credentials are read first from the database Settings (set in the admin), and only fall back to env variables. Configuring them in the admin panel is the recommended path.

First-Run Setup

On its first connection to an empty database, the app auto-creates a default Super Admin so you can sign in immediately.

Default admin emailadmin@evently.com
Default passwordChangeMe123!
Login page/staff/login β†’ routes to /super-admin/dashboard
  1. Start the app & sign in

    Run pnpm dev, open /staff/login, and sign in with the default Super Admin credentials above.

  2. Seed demo data (optional)

    Open Super Admin β†’ Seed (or POST /api/events/seed as a Super Admin) to populate demo organizers, attendees, venues, events, tickets, registrations, speakers, sponsors, team members, contacts and newsletter subscribers.

    Warning: Seeding replaces demo content and is intended for a fresh/dev database only. Do not run it against production data.

  3. Secure the account

    Immediately change the default Super Admin password (and email) from Profile / Settings before going live.

Demo Accounts

The default Super Admin is created automatically on first run. Additional demo organizer and attendee accounts are created by the seeder β€” the exact emails and shared password are listed on the Super Admin β†’ Seed page after seeding.

RoleEmailLogin PagePassword
Super Adminadmin@evently.com/staff/loginChangeMe123!
Organizersee Seed page/staff/loginsee Seed page
Attendeesee Seed page/loginsee Seed page

Before going live: change the default Super Admin credentials and never run the seeder against production data.

Project Structure

The project follows the Next.js App Router convention with route groups for clean separation between public, auth, and dashboard areas.

template-event-management/ β”œβ”€ app/ # Next.js App Router β”‚ β”œβ”€ (public)/ # Marketing site: home, events, speakers, venues, jobs, legal β”‚ β”‚ β”œβ”€ events/[slug]/ # Dynamic event detail + registration β”‚ β”‚ └─ ... β”‚ β”œβ”€ (auth)/ # login, register, staff/login, forgot/reset password β”‚ β”œβ”€ (dashboard)/ # Role dashboards (route-group, no URL segment) β”‚ β”‚ β”œβ”€ super-admin/ # Full management panel β”‚ β”‚ β”œβ”€ organizer/ # Organizer's own events & analytics β”‚ β”‚ └─ attendee/ # Attendee registrations & profile β”‚ β”œβ”€ api/ # Route handlers (REST API) β”‚ β”‚ β”œβ”€ auth/[...nextauth]/ # NextAuth handler β”‚ β”‚ └─ events/ # Main API (auth, public, attendee, organizer, super-admin, cron) β”‚ β”œβ”€ documentation/ # This documentation, served at /documentation β”‚ β”œβ”€ layout.tsx # Root layout + dynamic metadata β”‚ β”œβ”€ globals.css # Tailwind v4 + theme tokens β”‚ └─ sitemap.ts / robots.ts / manifest.ts / opengraph-image.tsx β”œβ”€ components/ # Reusable UI β”‚ β”œβ”€ ui/ # shadcn/Radix primitives β”‚ β”œβ”€ data-table/ # TanStack data-table + row-action-button β”‚ β”œβ”€ landing-page/ # Landing-page sections β”‚ └─ dashboard/ Β· seo/ Β· shared/ β”œβ”€ model/ # Mongoose schemas (28) β”‚ β”œβ”€ Event Β· Session Β· Ticket Β· Registration Β· Waitlist β”‚ β”œβ”€ Speaker Β· Sponsor Β· Exhibitor Β· Venue Β· Badge Β· Certificate β”‚ β”œβ”€ Plan Β· OrganizerSubscription Β· Coupon Β· CRM Β· Volunteer β”‚ └─ User Β· Team Β· Expense Β· Contact Β· Newsletter Β· Testimonial Β· … β”œβ”€ lib/ # Server & shared helpers β”‚ β”œβ”€ async-handler.ts # API wrapper: db + auth + zod validation β”‚ β”œβ”€ actions/ # Server actions + seeder (lib/actions/seed.ts) β”‚ β”œβ”€ validation-schema Β· email Β· audit Β· brand-colors β”‚ └─ landing-page-defaults Β· routes Β· types β”œβ”€ services/ # Cached data-access (settings, …) β”œβ”€ config/ # database.ts Β· cloudinary.ts Β· constant.ts (enums) β”œβ”€ public/ # Static assets, fonts, images, this documentation β”œβ”€ proxy.ts # Middleware (route protection) β€” Next.js 16 naming β”œβ”€ next.config.ts Β· tailwind.config.ts Β· tsconfig.json └─ package.json

Note: In Next.js 16 the middleware file is named proxy.ts (with a default export), not middleware.ts. Route protection logic lives there.

User Roles & Access

Three roles drive access control. Staff (Super Admin, Organizer) sign in at /staff/login; attendees sign in at /login.

πŸ‘‘
Super Admin
Full control of every module & settings
πŸŽͺ
Organizer
Own events, tickets, registrations & analytics
πŸ™‹
Attendee
Registrations, tickets, badges & profile
CapabilitySuper AdminOrganizerAttendee
Dashboardβœ… Platform-wideβœ… Own eventsβœ… Own activity
Events / Sessions / Ticketsβœ… Allβœ… Ownbrowse / register
Registrations & Check-inβœ… Allβœ… Own eventsown only
Speakers / Sponsors / Venuesβœ…βœ… Ownbrowse
Waitlist / Badges / Certificatesβœ…βœ… Ownown only
Users / Team / Plans / CRMβœ…β€”β€”
Expenses / Subscriptionsβœ… Allβœ… Ownβ€”
Settings / Seed / Audit Logsβœ…β€”β€”

Routing & Pages

Page URLs are centralised in lib/routes.ts via the ROUTES helper. Middleware (proxy.ts) guards dashboard routes and redirects users to the correct area based on their role.

Public routes

/Landing page (dynamic, admin-editable)
/events Β· /events/[slug]Event catalogue & detail with registration
/speakers Β· /venuesSpeaker & venue directories
/jobs Β· /jobs/applyCareers board & application form
/testimonials/submitSubmit a platform testimonial
/badge/[id] Β· /certificates/verifyPublic badge view & certificate verification
/about-us Β· /contact-usContent & contact pages
/privacy-policy Β· /terms-and-conditionsLegal pages (rich-text from settings)

Auth routes

/login Β· /registerAttendee auth
/staff/loginStaff (super admin / organizer) auth
/forgot-password Β· /reset-passwordPassword recovery

Dashboard roots

/super-admin/*dashboard, events, sessions, tickets, registrations, waitlist, venues, speakers, sponsors, exhibitors, badges, certificates, volunteers, users, team, expenses, coupons, crm, plans, subscriptions, jobs, newsletter, contact, audit-logs, settings, seed
/organizer/*dashboard, events, sessions, tickets, registrations, venues, speakers, sponsors, expenses, subscription, profile
/attendee/*dashboard, registrations, waitlist, badges, certificates, agenda, profile

Authentication

The template uses a hybrid auth model:

  • NextAuth v5 session protects pages via the proxy.ts middleware and stores the access token in the session.
  • Bearer JWT protects the REST API. Tokens are signed with JWT_SECRET and verified by the API auth helper.

Login flow

POST /auth/login→ verify password (bcrypt)→ sign JWT→ return { token, role }→ client stores token

Calling a protected endpoint

fetch("/api/events/attendee/registrations", {
  headers: { "Authorization": `Bearer ${token}` }
})

Every protected handler is wrapped with asyncHandler, which connects to the database, verifies the Bearer token, enforces an optional allowed-roles list, and validates the request body against a Zod schema before your handler runs. Passwords are hashed with bcrypt; email verification uses a time-limited OTP and password reset uses a signed token delivered by email.

Admin Settings

Almost everything is configurable from Super Admin β†’ Settings β€” no code edits needed. Settings are stored as a single document and cached (revalidated when saved).

SectionWhat it controls
GeneralSite name, tagline, email, phone, address, social links, favicon, currency, maintenance mode.
CloudinaryCloud name, API key/secret, upload folder β€” powers all image uploads.
SMTPHost, port, security, user/pass, from-name/email. Includes a Send test email action.
MetadataSEO title, application name, description, keywords, Open Graph image.
Legal & AboutRich-text About Us, Privacy Policy, Terms & Conditions and Testimonials content.
Landing PageThe full dynamic homepage builder + brand colors (see below).

Tip: Turn on Maintenance Mode in General settings to show a maintenance screen to public visitors while you make changes.

Theming & Branding

The design system is driven by CSS variables in app/globals.css and Tailwind v4 tokens. Light and dark modes are handled by next-themes. The template ships a green & white theme by default.

Brand colors

Primary, secondary and accent brand colors are exposed as CSS variables. The public site and dashboards read the admin-configured colors from the landingPage branding settings, applied through a scoped wrapper (brandVars() in the layouts) so the UI restyles without touching component classes. Defaults live in lib/landing-page-defaults.ts.

// lib/landing-page-defaults.ts
BRAND_DEFAULTS = {
  primaryColor: "#16a34a",   /* green-600 */
  secondaryColor: "#22c55e", /* green-500 */
  accentColor: "#06b6d4",    /* cyan-500 */
}

Change the brand colors

Set them from Super Admin β†’ Settings β†’ Landing Page (branding). The public site and admin dashboards pick them up automatically.

Logo & favicon

Upload your logo and favicon under Settings β†’ General; they are wired into the header and document <head> automatically.

Landing Page Builder

The homepage is fully data-driven from Settings β†’ Landing Page. Each section can be edited and populated with images without touching code.

SectionEditable Content
HeroBadge, title, description, background image, CTA labels, and stat counters.
FeaturesSection heading + feature items (icon, title, description).
TestimonialsUser-submitted testimonials (rating, content) with approval & feature toggles, shown in a carousel.
TeamPublic team members (name, role, bio, avatar, socials).
FAQ & NewsletterFrequently asked questions and the newsletter signup block.
BrandingPrimary, secondary & accent brand colors for the site.

Sensible defaults ship in lib/landing-page-defaults.ts, so the homepage looks complete before you customise anything.

Database Models

All Mongoose schemas live in /model (28 total). Every model includes timestamps and a softDelete flag (records are flagged, not physically removed).

ModelPurpose
EventCore event β€” title, dates, venue, category, status, speakers, sponsors, capacity, featured.
SessionAgenda session β€” time window, track, room, speaker(s), concurrent flag.
TicketTicket tier β€” name, price, quantity, sold, sale window, max per order.
RegistrationAttendee registration β€” quantity, total, status, confirmation code, check-in state.
WaitlistSold-out queue β€” status, 48-hour notification window, conversion.
Speaker Β· Sponsor Β· ExhibitorSpeaker profiles; tiered sponsors; exhibition booth holders.
VenueVenue β€” type (indoor/outdoor/virtual/hybrid), capacity, amenities.
Badge Β· CertificateCheck-in badges (QR, VIP flags); post-event certificates + verification.
Plan Β· OrganizerSubscriptionOrganizer plans (pricing/interval); subscription assignment & status.
Coupon Β· CRMDiscount codes; organizer contact/relationship records.
Volunteer Β· AgendaVolunteer registrations; event schedule/itinerary.
JobApplicationCareer applications β€” resume, cover letter, status pipeline.
AIEventTemplateAI-suggested event templates (titles, agenda, tickets, SEO).
User Β· TeamPlatform users (role/auth); public About-page team members.
ExpenseCategorised business expenses linked to events.
Contact Β· Newsletter Β· TestimonialContact submissions; subscribers; user testimonials.
Notification Β· AuditLog Β· SettingsIn-app notifications; audit trail (365-day TTL); singleton settings.

Lifecycles & Status Enums

Event

draft→ published→ completed· cancelled

Registration & Ticket

Registration: confirmed Β· pending Β· cancelled Β· waitlisted. Ticket: active Β· sold_out Β· cancelled. When a ticket sells out, new registrations are added to the Waitlist.

Waitlist

waiting→ notified (48h hold)→ converted· expired· cancelled

When a spot opens, the next person is notified and holds it for 48 hours. If they don't convert, a cron job marks them expired and notifies the next in line.

Other enums

Venue typeindoor Β· outdoor Β· virtual Β· hybrid
Sponsor tierplatinum Β· gold Β· silver Β· bronze Β· partner
Subscriptionactive Β· trialing Β· canceled Β· expired
Couponpercentage Β· fixed
Volunteerregistered Β· confirmed Β· checked_in Β· completed Β· cancelled
Job applicationnew Β· reviewed Β· shortlisted Β· interviewed Β· rejected Β· hired
Contactnew Β· in_progress Β· resolved Β· closed
Expense categoryvenue Β· catering Β· marketing Β· equipment Β· speakers Β· staff Β· travel Β· other

Cron Jobs

A single scheduled job keeps the waitlist moving. It releases expired 48-hour holds, promotes the next person in the queue, and sends the relevant emails.

POST/api/events/cron/waitlist-expiryCron

Authorized with the CRON_SECRET (Bearer header). Recommended cadence: every 15 minutes.

Schedule it with a Vercel Cron entry or an external scheduler (e.g. cron-job.org) hitting the endpoint with Authorization: Bearer <CRON_SECRET>.

API Conventions

All endpoints live under /api. The main API is namespaced under /api/events. NextAuth's handler lives at /api/auth/[...nextauth].

Standard response envelope

{
  "status": true,
  "message": "Operation successful!",
  "data": { /* payload or null */ },
  "pagination": { /* present on list endpoints */ }
}

Authentication header

Authorization: Bearer <jwt-token>
CodeMeaning
200 / 201Success
400Validation failed
401Missing / invalid / expired token
403Authenticated but not permitted (wrong role)
404Resource not found
409Conflict (e.g. email in use, already registered, sold out)
500Server error

Public = no token required  Β·  Auth = Bearer token + role required

Tip: A ready-to-import postman_collection.json ships in the project root (regenerate with pnpm generate-postman).

Auth API

Base path: /api/events/auth

POST/loginPublic

Authenticate a user. Body: { email, password }. Returns { token, role }.

POST/registerPublic

Create an attendee account. Body: { name, email, password, phone? }.

GET/meAuth

Return the current authenticated user's profile.

POST/forgot-passwordPublic

Email a password-reset token. Body: { email }.

POST/reset-passwordPublic

Set a new password using the emailed token. Body: { token, password }.

POST/change-passwordAuth

Change password. Body: { currentPassword, newPassword }.

Public API

Base path: /api/events/public β€” no authentication required.

GET/eventsList published events (search / filter / paginate)
GET/events/[slug]Event detail with tickets, speakers, sponsors
GET/speakersList active speakers
GET/venuesList venues
GET/sponsors Β· /exhibitors Β· /sessionsPublic event-related listings
GET/plansOrganizer subscription plans
POST/registerRegister for an event (checks capacity, coupons)
POST/waitlistJoin a sold-out event's waitlist
POST/coupons/validateValidate a discount code
GET/certificates/verifyVerify a certificate by code
GET/jobsList open job postings
POST/contact Β· /newsletter Β· /volunteersContact form, newsletter signup, volunteer registration

Attendee API

Base path: /api/events/attendee β€” requires an attendee Bearer token.

GET/profileGet / update the attendee profile
GET/registrationsList the attendee's registrations
GET/registrations/[id]Registration detail + confirmation code
PATCH/registrations/[id]/checkinSelf check-in at the event
GET/waitlist Β· /waitlist/[id]View / manage waitlist entries
GET/badges Β· /certificates Β· /agendaAttendee badges, certificates and personal agenda

Organizer API

Base path: /api/events/organizer β€” requires an organizer Bearer token. Scoped to the organizer's own resources.

GET/dashboardRevenue, registrations & expense analytics
GET/events POSTList / create the organizer's events
PUT/events/[slug] PATCH/events/[slug]/publishUpdate / publish an event
GET/tickets Β· /sessions Β· /speakers Β· /sponsors Β· /venuesCRUD for event building blocks
GET/registrations PATCH/registrations/[id]/checkinManage attendees & check-in
GET/expenses GET/subscriptionEvent expenses & the organizer's subscription

Super Admin API

Base path: /api/events/super-admin β€” requires a Super Admin Bearer token. Full CRUD across every module. Each resource below supports the standard set (GET list & [id], POST, PUT, DELETE) unless noted.

Dashboard & Platform

GET/dashboardPlatform KPIs & charts
GET/audit-logsActivity trail
POST/uploadCloudinary image upload

Events & Content

GET/events Β· /sessions Β· /ticketsEvents, agenda sessions, ticket tiers (CRUD)
GET/registrations PATCH/registrations/[id]/checkinAll registrations + check-in
GET/waitlistWaitlist entries β€” notify / convert / cancel
GET/speakers Β· /sponsors Β· /exhibitors Β· /venuesEvent participants & locations (CRUD)
GET/badges Β· /certificatesBadges & certificates (CRUD)

People & Growth

GET/users Β· /team Β· /volunteersPlatform users, public team, volunteers
GET/plans Β· /subscriptionsOrganizer plans & subscriptions
GET/coupons Β· /crm Β· /expensesDiscounts, CRM, business expenses (CRUD)
GET/jobsJob applications β€” list + update status
GET/contact Β· /newsletterContact inbox (reply) & subscribers
GET/ai-templatesAI event templates (CRUD)

Settings

GET/settings PUT/settingsRead / update settings by key
POST/smtp/testSend a test email

Notifications & Seed

Base path: /api/events/notifications

GET/notificationsAuth

List the current user's notifications with unread count.

PATCH/notifications/[id]/readAuth

Mark a single notification as read.

POST/api/events/seedSuper Admin

Populate the database with demo data. Use only in development.

Deployment

The app deploys anywhere that runs Node.js. Vercel is the simplest path.

Vercel

  1. Push to Git

    Push the project to a GitHub/GitLab repo.

  2. Import to Vercel

    Create a new project and import the repo.

  3. Add environment variables

    Copy every key from your .env.local into the Vercel project settings. Set NEXTAUTH_URL and the public URLs to your production domain.

  4. Add the waitlist cron

    Configure a Vercel Cron (or external scheduler) to POST /api/events/cron/waitlist-expiry every ~15 min with the CRON_SECRET.

  5. Deploy

    Vercel builds with pnpm build automatically.

Self-hosted / VPS

pnpm install
pnpm build
pnpm start   # serves on port 3000 β€” put Nginx/PM2 in front

Production checklist: set strong AUTH_SECRET/JWT_SECRET/CRON_SECRET, point all URLs to your domain, configure SMTP & Cloudinary in admin Settings, change the default Super Admin credentials, and never run the seeder against production data.

Troubleshooting & FAQ

Which login page do I use?

Staff (Super Admin, Organizer) sign in at /staff/login; attendees at /login. New registrations are created with the attendee role.

The build fails trying to reach the database

The template is designed to build without a live DB β€” settings are skipped during the build phase and DB-backed pages are dynamic. Make sure you're on the latest code and that config/database.ts only reads MONGODB_URI lazily (inside dbConnect).

Database connection fails at runtime

Verify MONGODB_URI and that your IP is whitelisted in MongoDB Atlas (Network Access). The app uses the database name template-event-management.

Emails aren't sending

Configure SMTP in Settings β†’ SMTP and use the Send test email button. For Gmail, use an App Password, not your account password.

Image uploads fail

Fill in Cloudinary credentials under Settings β†’ Cloudinary. Without them, image upload features are disabled.

Waitlist holds never expire

The /api/events/cron/waitlist-expiry job must run on a schedule with the correct CRON_SECRET. Check your Vercel Cron / external scheduler.

Build error: middleware not found

This project uses Next.js 16, where middleware is proxy.ts with a default export β€” do not rename it to middleware.ts.

Public site shows a maintenance screen

Maintenance Mode is enabled in Settings β†’ General. Turn it off to restore the public site.

Support & Credits

Thank you for choosing Evently β€” Event Management System. We hope it accelerates your project.

πŸ“š Documentation

This guide is bundled as documentation.html / documentation.pdf and is also served live at /documentation.

πŸ›Ÿ Support

For help, use the support channel listed on the item's download page. Please include your environment details and any error messages.

Built with

Next.js Β· React Β· TypeScript Β· MongoDB Β· Mongoose Β· Tailwind CSS Β· Radix UI Β· NextAuth Β· Zod Β· React Hook Form Β· TanStack Table Β· Recharts Β· Framer Motion Β· Cloudinary Β· Nodemailer Β· jsPDF Β· qrcode Β· TipTap Β· Zustand.

Enjoying the template? A rating and review are hugely appreciated and help us keep improving it.