Grand Hotel — Documentation

A complete, production-ready Hotel Management System and booking website 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?

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

🌐 Public Booking Website

A polished, SEO-ready marketing site with a dynamic landing page, room catalogue, room detail pages, availability checking, online booking, guest reviews, newsletter, and contact forms.

🛠️ Management Dashboard

A role-based admin panel for rooms, room types, bookings, guests, employees, salaries, expenses, reviews, reports, audit logs, and full site settings — 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

🏨 Room & Room-Type Management

Group rooms by type with base pricing, per-day service charge, amenities and image galleries. Per-room overrides for floor, view, bed type, size, policies and accessibility.

📅 Bookings Engine

Date-range availability with conflict detection, automatic billing (room cost, service charge, VAT, misc), nights calculation, and a guarded status workflow.

💳 Payments & Billing

Partial/paid/refunded tracking, multiple payment methods, payment recording and booking extension endpoints.

👥 Role-Based Access

Four roles — Super Admin, Admin, Manager, Customer — each with a dedicated dashboard and middleware-protected routes.

👔 HR: Employees & Salaries

Staff records by job role, monthly salary sheets with bonus/deductions, and a one-click "mark paid" action.

💸 Expense Tracking

Categorised operating expenses with receipts, feeding into the financial reports.

⭐ Guest Reviews

Verified-stay reviews with moderation (pending / approved / rejected) and optional public hotel replies.

📊 Reports & Dashboards

Revenue, occupancy and expense reporting plus role-specific dashboard summaries.

🎨 Dynamic Landing Page

Hero, facilities, experiences, nearby attractions, offers and gallery — all editable from the admin without touching code.

📧 Transactional Email

SMTP with welcome, booking confirmation, email verification (OTP) and password-reset mails. DB-configured with env fallback.

🖼️ Cloudinary Uploads

Image uploads for rooms, room types, gallery and branding, configured from the admin Settings.

🛡️ Audit Logging

Every sensitive action (logins, CRUD, status changes) is recorded with actor, resource, IP and details.

🔔 Notifications

In-app notifications for booking requests, approvals, expenses and salary events.

📱 Mobile-Ready v1 API

Versioned, mobile-friendly endpoints for listing rooms and creating guest bookings.

🔍 SEO Built-In

Dynamic metadata, Open Graph image route, sitemap.ts, robots.ts and a PWA manifest.ts.

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.ts
TablesTanStack TableReusable data-table in /components/data-table
AnimationFramer MotionLanding-page motion
MediaCloudinaryImage hosting & delivery
EmailNodemailer (SMTP)Transactional mail
EditorTipTapRich-text for legal pages
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.

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. The dashboard lives at /super-admin, /admin, /manager and /customer.

  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

Environment Variables

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

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

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

# ── 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"

# ── SEO (optional) ────────────────────────────────────
NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION=""
VariableRequiredDescription
MONGODB_URI✅ YesMongoDB connection string. Use template-hotel as the database name.
NEXTAUTH_SECRET✅ YesSecret used to sign sessions and JWTs. Generate with openssl rand -base64 32.
NEXTAUTH_URL✅ YesCanonical app URL used by NextAuth.
AUTH_TRUST_HOST✅ YesSet to true so NextAuth trusts the deployment host.
NEXT_PUBLIC_SITE_URLRecommendedAbsolute site URL for metadata, sitemap and Open Graph.
NEXT_API_URLRecommendedBase URL used for server-side fetches.
SMTP_* / FROM_EMAILOptionalFallback email transport when admin SMTP settings are empty.
NEXT_PUBLIC_GOOGLE_SITE_VERIFICATIONOptionalGoogle Search Console verification token.

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

The app needs a first Super Admin account before you can access the dashboard and seed demo data. Follow these steps once:

  1. Register a normal account

    Start the app and register at /register. New accounts are created with the customer role.

  2. Promote it to Super Admin

    In your MongoDB database, open the users collection, find your account by email, and change its role field to super_admin:

    // mongosh
    db.users.updateOne(
      { email: "you@example.com" },
      { $set: { role: "super_admin", status: true } }
    )
  3. Log in as staff

    Go to /staff/login and sign in. You will be routed to /super-admin/dashboard.

  4. Seed demo data (optional)

    Open Super Admin → Seed and run the seeder to populate room types, rooms, employees, customers, bookings, expenses, salaries, notifications and audit logs.

    Warning: Seeding deletes all existing data except your Super Admin account and replaces it with demo content. Use only on a fresh/dev database.

Demo Accounts

After running the seeder, the following accounts are available. All seeded users share the password Password123!.

RoleEmailLogin PagePassword
Super Adminyour promoted account/staff/loginyour password
Adminsarah@grandhaven.com/staff/loginPassword123!
Managerdavid@grandhaven.com/staff/loginPassword123!
Customerjames.harper@email.com/loginPassword123!

Before going live: delete or change all demo accounts and re-seed nothing on production.

Project Structure

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

template-hotel/ ├─ app/ # Next.js App Router │ ├─ (public)/ # Marketing site: home, rooms, about, menu, outlets, legal │ │ ├─ rooms/[id]/ # Dynamic room detail page │ │ └─ ... │ ├─ (auth)/ # login, register, staff/login, forgot/reset password │ ├─ (dashboard)/ # Role dashboards (route-group, no URL segment) │ │ ├─ super-admin/ # Full management panel │ │ ├─ admin/ # Admin dashboard │ │ ├─ manager/ # Manager dashboard │ │ └─ customer/ # Customer bookings & profile │ ├─ api/ # Route handlers (REST API) │ │ ├─ auth/[...nextauth]/ # NextAuth handler │ │ ├─ hotel/ # Main API (auth, public, customer, staff, super-admin) │ │ └─ v1/ # Versioned mobile-ready API │ ├─ documentation/ # This documentation, served at /documentation │ ├─ layout.tsx # Root layout + dynamic metadata │ ├─ providers.tsx # Theme / session / toast providers │ ├─ globals.css # Tailwind v4 + theme tokens │ ├─ sitemap.ts / robots.ts # SEO routes │ └─ manifest.ts / opengraph-image.tsx ├─ components/ # Reusable UI │ ├─ ui/ # shadcn/Radix primitives │ ├─ data-table/ # TanStack data-table │ ├─ form/ # Form fields & wrappers │ ├─ landing-page/ # Landing-page sections │ ├─ dashboard/ · rooms/ · seo/ · shared/ · custom/ ├─ model/ # Mongoose schemas │ ├─ User · Room · RoomType · Booking · Review │ ├─ Expense · Salary · Contact · Newsletter │ └─ Notification · AuditLog · Settings · index.ts ├─ lib/ # Server & shared helpers │ ├─ async-handler.ts # API wrapper: db + auth + zod validation │ ├─ authenticate.ts # Bearer JWT verification │ ├─ validation-schema.ts # Zod schemas │ ├─ email.ts · payment.ts · audit.ts · notify.ts │ ├─ utils.ts · fetcher.ts · routes.ts · types.ts │ └─ landing-page-defaults.ts · file-validator.ts ├─ services/ # Cached data-access (settings, rooms, bookings, auth) ├─ config/ # database.ts · cloudinary.ts · constant.ts (enums) ├─ store/ # Zustand stores (user, breadcrumb, table) ├─ hooks/ # use-user, use-mobile ├─ types/ # next-auth.d.ts, next.d.ts type augmentation ├─ 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

Four primary roles drive access control. Staff roles (Super Admin, Admin, Manager) log in at /staff/login; customers log in at /login.

👑
Super Admin
Full control of every module & settings
🛡️
Admin
Operational dashboard & bookings
📋
Manager
Day-to-day bookings & dashboard
🙋
Customer
Own bookings & profile

Additional employee job roles (cleaner, plumber, electrician, carpenter, cook, waiter, guard, assistant manager, etc.) are stored on staff records for HR/salary purposes but do not grant dashboard access.

CapabilitySuper AdminAdminManagerCustomer
Dashboard✅ Full✅ Own
Rooms & Room Types
Bookings (all)viewviewown only
Employees / Salaries
Expenses / Reports
Reviews / Contact / Newsletter
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)
/rooms · /rooms/[id]Room catalogue & detail with availability
/about-us · /menu · /outletsContent pages
/privacy-policy · /terms-and-conditionsLegal pages (rich-text from settings)
/documentationThis documentation

Auth routes

/login · /registerCustomer auth
/staff/loginStaff (super admin / admin / manager) auth
/forgot-password · /reset-passwordPassword recovery

Dashboard roots

/super-admin/*dashboard, rooms, room-types, bookings, employees, guests, contact, newsletter, reviews, expenses, salaries, reports, audit-logs, settings, seed
/admin/*dashboard, bookings, rooms, guests, profile
/manager/*dashboard, bookings, profile
/customer/*dashboard, bookings, profile, verify-email

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 NEXTAUTH_SECRET and verified by lib/authenticate.ts.

Login flow

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

Calling a protected endpoint

fetch("/api/hotel/customer/bookings", {
  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.

// Example: super-admin-only route with body validation
export const POST = asyncHandler(roomSchema, handler, true, ["super_admin"]);
//                              schema   fn   auth   allowedRoles

Passwords are hashed with bcrypt. Email verification uses a time-limited OTP stored on the user record, 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
GeneralHotel name, address, phone, logo, favicon, owner & support contact, social links, check-in/out times, currency, maintenance mode.
CloudinaryCloud name, API key/secret, upload folder, secure URL base — 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 PagesRich-text About Us, Privacy Policy and Terms & Conditions content.
Landing PageThe full dynamic homepage builder (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.

Brand colors

Primary and accent (amber) colours are exposed as CSS variables. The public site reads the admin-configured brand colours from the landingPage.branding settings, applied through a scoped wrapper so the admin UI stays neutral.

/* app/globals.css — core tokens */
:root{
  --primary: oklch(0.205 0 0);        /* stone-900 */
  --primary-foreground: oklch(0.985 0 0);
}

Fonts

The UI font is Lato (loaded via next/font/google in the root layout). Swap it by editing the font import in app/layout.tsx.

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, reordered (where applicable) and populated with images without touching code.

SectionEditable Content
HeroBadge, tag, title, description, background image, CTA labels, and stat counters.
FacilitiesSection heading + list of facility items (icon, title, description).
Guest ExperiencesHeading, rating text, and testimonial items (name, country, rating, stay, text).
Nearby AttractionsHeading + items (icon, label, description, distance).
OffersPromotional cards (title, image, badge, discount, CTA, valid-until, active flag).
GalleryImage grid (image + alt text).
BrandingPrimary & secondary brand colours for the public 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. Every model includes timestamps and a softDelete flag (records are flagged, not physically removed).

ModelCollectionKey Fields
Userusersname, email (unique), password, role, phone, status, emailVerified, emailOtp
RoomTyperoom_typesname, slug (unique), basePrice, serviceChargePerDay, capacity, amenities, images, position
RoomroomsroomNumber (unique), type→RoomType, floor, status, priceOverride, maxGuests, bedType, view, policies, features
BookingbookingsbookingNumber, room, guest, guestInfo, checkIn/Out, nights, status, paymentStatus, billing breakdown, statusHistory
Reviewreviewsroom, rating (1–5), comment, status, verified, response
Expenseexpensestitle, category, amount, date, receipt, paidBy
Salarysalariesemployee, amount, bonus, deductions, netAmount, month, year, isPaid
Contactcontactsname, email, subject, message, status, adminNote
Newsletternewslettersemail (unique), status, source
Notificationnotificationsrecipient, type, title, message, isRead
AuditLogaudit_logsactor, action, resource, resourceId, details, IP
Settingssettingsgeneral, smtp, cloudinary, metadata, termsPolicy, landingPage

Status enums (config/constant.ts)

Bookingpending · approved · rejected · reserved · checked_in · checked_out · cleaning · completed · cancelled
Roomavailable · reserved · occupied · cleaning · maintenance · out_of_service
Paymentpending · partial · paid · refunded
Reviewpending · approved · rejected
Payment methodscash · card · mobile_banking · online

Booking Lifecycle

Booking status changes are guarded by an explicit transition map (BOOKING_STATUS_TRANSITIONS). Only allowed next-states are accepted by the status endpoint, and each change is appended to the booking's statusHistory.

pending approved reserved checked_in checked_out cleaning

At any early stage a booking may be cancelled; a pending booking may be rejected.

Date-blocking logic

Dates are considered blocked by any booking except those in non-blocking states (cancelled, rejected, checked_out, cleaning). This is what the availability endpoint checks before accepting a new booking.

Automatic billing

On creation, the system computes roomCost (nightly rate × nights), serviceCharge, vatAmount from vatPercent, any miscCharges, and the final totalAmount. Payments update paidAmount and roll paymentStatus through partial → paid.

API Conventions

All endpoints live under /api. The main API is namespaced under /api/hotel, with a versioned mobile API under /api/v1.

Standard response envelope

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

Authentication header

Authorization: Bearer <jwt-token>

Validation errors (HTTP 400)

{
  "status": false,
  "message": "Request validation failed!",
  "data": { "email": "Valid email is required!" }
}
CodeMeaning
200 / 201Success
400Validation failed
401Missing / invalid / expired token
403Authenticated but not permitted (wrong role / deactivated)
404Resource not found
409Conflict (e.g. email in use, date clash)
500Server error

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

Auth API

Base path: /api/hotel/auth

POST/loginPublic

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

POST/registerPublic

Create a customer account. Body: { name, email, password, phone? }. Sends a welcome email.

GET/meAuth

Return the current authenticated user's profile.

PUT/meAuth

Update the current user's profile (name, phone, image).

PUT/passwordAuth

Change password. Body: { currentPassword, newPassword }.

POST/forgot-passwordPublic

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

POST/reset-passwordPublic

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

POST/verify-email/sendAuth

Send an email-verification OTP to the current user.

POST/verify-email/confirmAuth

Confirm the OTP and mark the email verified. Body: { otp }.

Public API

Base path: /api/hotel/public — no authentication required.

GET/rooms

List published rooms with pricing & room-type info. Supports filtering/pagination query params.

GET/rooms/[id]

Fetch a single room with full details, amenities and images.

GET/rooms/[id]/availability

Check availability for a date range. Query: ?checkIn=&checkOut=.

POST/bookings

Create a guest booking. Validates availability, computes billing, notifies admins, emails confirmation.

GET/reviews

List approved reviews (optionally by room).

POST/reviews

Submit a guest review (enters moderation as pending).

POST/contact

Submit a contact-form message.

POST/newsletter

Subscribe an email to the newsletter.

Customer API

Base path: /api/hotel/customer — requires a customer Bearer token.

GET/bookingsAuth

List the authenticated customer's bookings.

PATCH/bookings/[id]/cancelAuth

Cancel one of the customer's own bookings (if its current status allows it).

Manager & Admin API

Role-scoped dashboard data.

GET/api/hotel/admin/dashboardAdmin

Admin dashboard summary (bookings, occupancy, revenue snapshots).

GET/api/hotel/manager/dashboardManager

Manager dashboard summary.

Super Admin API

Base path: /api/hotel/super-admin — requires a Super Admin Bearer token. Full CRUD across every module.

Dashboard & Reports

GET/dashboardKPIs, revenue, occupancy
GET/reportsFinancial & occupancy reports
GET/audit-logsActivity trail

Rooms & Room Types

GET/roomsList rooms
POST/roomsCreate room
GET/rooms/[id]Get room
PUT/rooms/[id]Update room
DELETE/rooms/[id]Soft-delete room
GET/room-typesList room types
POST/room-typesCreate room type
GET/room-types/[slug]Get room type
PUT/room-types/[slug]Update room type
DELETE/room-types/[slug]Soft-delete

Bookings

GET/bookingsList all bookings
POST/bookingsCreate booking (walk-in)
GET/bookings/[id]Booking detail
DELETE/bookings/[id]Soft-delete booking
PATCH/bookings/[id]/statusTransition status (guarded)
PATCH/bookings/[id]/paymentRecord a payment
PATCH/bookings/[id]/extendExtend the stay

Guests & Employees

GET/guestsList customers
GET/employeesList employees
POST/employeesCreate employee
GET/employees/[id]Get employee
PUT/employees/[id]Update employee
DELETE/employees/[id]Soft-delete employee

Salaries & Expenses

GET/salariesList salary records
POST/salariesCreate salary record
PUT/salaries/[id]Update salary
DELETE/salaries/[id]Delete salary
PATCH/salaries/[id]/payMark salary paid
GET/expensesList expenses
POST/expensesCreate expense
PUT/expenses/[id]Update expense
DELETE/expenses/[id]Delete expense

Reviews, Contact & Newsletter

GET/reviewsList reviews
PATCH/reviews/[id]Moderate / reply
DELETE/reviews/[id]Delete review
GET/contactList messages
GET/contact/[id]Get message
PATCH/contact/[id]Update status / note
DELETE/contact/[id]Delete message
GET/newsletterList subscribers

Settings

GET/settingsRead all settings
PUT/settingsUpdate settings
POST/settings/smtp/testSend a test email

Notifications & Seed

Base path: /api/hotel/notifications

GET/notificationsAuth

List the current user's notifications.

PATCH/notificationsAuth

Mark all notifications as read.

PATCH/notifications/[id]/readAuth

Mark a single notification as read.

POST/api/hotel/seedSuper Admin

Wipe (except Super Admin) and re-seed the database with demo data. Use only in development.

Mobile API (v1)

Base path: /api/v1 — a versioned, mobile-friendly surface for native/3rd-party clients.

GET/v1/roomsPublic

List available rooms, slimmed for mobile consumption.

POST/v1/bookingsPublic

Create a guest booking with availability checks and email confirmation. Body: { room, checkIn, checkOut, adults, children?, guestInfo:{ name, email, phone, nationality? }, specialRequests? }.

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. 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 a strong NEXTAUTH_SECRET, point all URLs to your domain, configure SMTP & Cloudinary in admin Settings, remove demo accounts, and never run the seeder against production data.

Troubleshooting & FAQ

I can't reach the dashboard after registering

New accounts are customer by default. Promote your account to super_admin in MongoDB (see First-Run Setup), then log in at /staff/login.

Database connection fails

Verify MONGODB_URI and that your IP is whitelisted in MongoDB Atlas (Network Access). The database name should be template-hotel.

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. SMTP env vars act only as a fallback.

Image uploads fail

Fill in Cloudinary credentials under Settings → Cloudinary. Without them, image upload features are disabled.

Auth redirect loop

Make sure NEXTAUTH_URL matches the URL you're visiting and AUTH_TRUST_HOST=true is set.

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 Grand Hotel — Hotel 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 · Framer Motion · Cloudinary · Nodemailer · TipTap · Zustand.

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