π¬ποΈπΏ MoviefyHub is a full-stack movie ticket booking application. Browse movies and showtimes, select seats, pay through Stripe Checkout, and manage bookings with a React and Vite frontend and an Express, MongoDB, and Node.js backend.
- Authentication & User Management: Sign-in and session handling through Clerk, with private user metadata used for admin roles and favorites.
- Movie Discovery: Now-playing movies, movie details, cast information, posters, and backdrops fetched from TMDB.
- Showtime & Seat Selection: Browse upcoming shows, select seats, and check occupied seats before creating a booking.
- Stripe Checkout: Create hosted Checkout Sessions and confirm completed payments through a Stripe webhook.
- Booking Management: View bookings, payment status, seat selections, and booking details.
- Admin Dashboard: Regular admins manage their own shows and review bookings and revenue associated with those shows; MainAdmin can view platform-wide shows, bookings, and revenue.
- MainAdmin Theater Requests: Users can request admin access by submitting theater details. A
main-admincan approve or reject requests; approval assigns the regularadminrole. - Background Jobs & Email: Inngest handles Clerk user sync events, payment timeout cleanup, scheduled reminders, booking confirmations, and new-show email notifications.
- Responsive Interface: React, Tailwind CSS, React Router, and React Hot Toast provide the movie browsing and booking experience.
- Frontend: React 19, Vite, React Router DOM, Tailwind CSS v4, Axios, React Hot Toast, Clerk React, Lucide React
- Backend: Node.js, Express.js v5, Mongoose, Clerk Express, Inngest, Stripe SDK, Nodemailer, Axios, CORS, Dotenv, Nodemon
- Database: MongoDB Atlas with Mongoose
- Authentication: Clerk session authentication and private metadata role checks
- Movie Data: TMDB API
- Payments: Stripe Checkout Sessions and Stripe webhooks
- Email: Nodemailer using an SMTP provider
- Version Control: Git and GitHub
- Deployment: Frontend and backend can be deployed independently; configure public backend and Inngest endpoints for production
- ποΈ Full-Stack MERN Architecture β React and Vite client connected to an Express REST API and MongoDB Atlas.
- β‘ Axios API Integration β Shared client requests to the configured backend URL.
- π Clerk Authentication & Access Control β Clerk provides sign-in and bearer tokens; server middleware checks private metadata roles for protected routes.
- π Role-Based Admin Access β
adminandmain-admincan use admin tools. Onlymain-admincan approve or reject theater-admin requests. - ποΈ TMDB Movie Catalog β Backend requests now-playing lists, movie information, and credits; movie data is stored in MongoDB when a show is created.
- π Showtimes & Seat Availability β Browse scheduled shows and verify seat availability before booking.
- π³ Stripe Checkout & Webhooks β The backend creates hosted Checkout Sessions; the webhook marks successful bookings paid and triggers confirmation email work.
- π§ Inngest and Nodemailer Workflows β Background handlers synchronize Clerk users, remove unpaid bookings and release seats, send booking confirmations, prepare show reminders, and announce new shows.
- π Admin Dashboard β Review booking and revenue totals, active shows, bookings, and show management tools.
- ποΈ MongoDB & Mongoose Models β Persist users, movies, shows, bookings, and theater-admin requests.
- π Dynamic Client-Side Routing β React Router powers home, movie details, seat selection, bookings, favorites, and admin pages.
- π¨ Responsive UI β Tailwind CSS v4 and React Hot Toast provide responsive layout and user feedback.
- βοΈ Environment-Based Configuration β Keep client and server configuration in separate
.envfiles. Never commit real credentials. - β‘ Developer Workflow β Vite serves the client and Nodemon restarts the Express server during development.
- Node.js: Use a current LTS version compatible with Vite 8 (Node.js 20.19+ or 22.12+).
- npm package manager
- A MongoDB Atlas cluster or local MongoDB instance
- A Clerk application
- A TMDB API account and API Read Access Token
- A Stripe account (test mode is suitable for local development)
- An Inngest account for deployed background processing
- An SMTP account or SMTP relay for email delivery
This project creates Stripe-hosted Checkout Sessions. Use Stripe test-mode cards while your Stripe account and server use test credentials:
- Card Number:
4242 4242 4242 4242 - Expiry Date (MM / YY): Any future date
- CVC:
123 - Postal / ZIP Code: Any valid test postal code
| Test Scenario | Card Number | Expected Behavior |
|---|---|---|
| Generic Card Decline | 4000 0000 0000 0002 |
Stripe reports a card decline |
| Insufficient Funds | 4000 0000 0000 9995 |
Stripe reports insufficient funds |
| Expired Card | 4000 0000 0000 0069 |
Stripe reports an expired card |
| Incorrect CVC | 4000 0000 0000 0127 |
Stripe reports a CVC check failure |
Use only test card numbers with Stripe test keys. Do not use real payment details for testing.
Generated: 10/11/2026, 11:23:13 AM
Root Path: workspace\Movie_Booking_MERN_App
βββ π client
β βββ π public
β β βββ πΌοΈ HeroImg.png
β β βββ πΌοΈ favicon.svg
β βββ π src
β β βββ π assets
β β β βββ π assets.js
β β β βββ πΌοΈ logo.svg
β β β βββ πΌοΈ marvelLogo.svg
β β β βββ πΌοΈ screenImage.svg
β β βββ π components
β β β βββ π admin
β β β β βββ π AdminNavBar.jsx
β β β β βββ π AdminSideBar.jsx
β β β β βββ π Title.jsx
β β β βββ π BlurCircle.jsx
β β β βββ π DateSelect.jsx
β β β βββ π FeaturedSection.jsx
β β β βββ π Footer.jsx
β β β βββ π Hero.jsx
β β β βββ π Loading.jsx
β β β βββ π MovieCard.jsx
β β β βββ π NavBar.jsx
β β β βββ π TrailerSection.jsx
β β βββ π context
β β β βββ π AppContext.jsx
β β βββ π lib
β β β βββ π dateFormat.js
β β β βββ π isoTimeFormat.js
β β β βββ π kConverter.js
β β β βββ π timeFormat.js
β β βββ π pages
β β β βββ π admin
β β β β βββ π AddShows.jsx
β β β β βββ π Dashboard.jsx
β β β β βββ π Layuot.jsx
β β β β βββ π ListBookings.jsx
β β β β βββ π ListShows.jsx
β β β β βββ π TheaterRequests.jsx
β β β βββ π Favorite.jsx
β β β βββ π Home.jsx
β β β βββ π MovieDetails.jsx
β β β βββ π Movies.jsx
β β β βββ π MyBookings.jsx
β β β βββ π SeatLayout.jsx
β β βββ π App.jsx
β β βββ π¨ index.css
β β βββ π main.jsx
β βββ βοΈ .gitignore
β βββ π README.md
β βββ π eslint.config.js
β βββ π index.html
β βββ βοΈ package-lock.json
β βββ βοΈ package.json
β βββ βοΈ vercel.json
β βββ π vite.config.js
βββ π server
β βββ π config
β β βββ π db.js
β β βββ π nodemailer.js
β βββ π controllers
β β βββ π AdminController.js
β β βββ π BookingController.js
β β βββ π ShowsController.js
β β βββ π StripeWebHook.js
β β βββ π TheaterAdminController.js
β β βββ π UserController.js
β βββ π inngest
β β βββ π index.js
β βββ π middlewares
β β βββ π auth.js
β βββ π models
β β βββ π BookingModel.js
β β βββ π MovieModel.js
β β βββ π ShowsModel.js
β β βββ π TheaterAdminRequestModel.js
β β βββ π UserModel.js
β βββ π routes
β β βββ π AdminRouter.js
β β βββ π BookingRoutes.js
β β βββ π ShowsRoutes.js
β β βββ π TheaterAdminRouter.js
β β βββ π UserRouter.js
β βββ βοΈ package-lock.json
β βββ βοΈ package.json
β βββ π server.js
β βββ βοΈ vercel.json
βββ βοΈ .gitignore
βββ π README.md
- Create or select a MongoDB Atlas project and cluster.
- Create a database user with a strong password and only the permissions the application needs.
- Add the IP addresses of your development machine and backend host to Network Access. Avoid allowing access from anywhere unless you understand and accept the exposure.
- Copy the cluster connection URI into the backend
MONGO_URI. - The current server appends
/moviefyhubtoMONGO_URI; use the cluster URI without an existing database path or query string so the database name is not duplicated.
Set environment variables in each deployment provider's project settings:
- Add
VITE_variables to the frontend project and backend variables to the backend project. - Configure the values for the required environments (Development, Preview, and Production when applicable).
- Keep secret keys private. Do not add them to source control, frontend variables, screenshots, or public build configuration.
VITE_variables are bundled into the browser application and are not secret. Only use them for publishable keys, public URLs, currency, and image URLs.- Redeploy after changing deployment environment variables.
VITE_CLERK_PUBLISHABLE_KEY=pk_test_...____
VITE_CURRENCY=$
VITE_BASE_URL=Backend Live link
VITE_TMDB_IMAGE_BASE_URL=tmdb base img urlPORT=port
MONGO_URI=MongoDB URI
CLERK_PUBLISHABLE_KEY=pk_test_....___
CLERK_SECRET_KEY=sk_test_..___
INNGEST_EVENT_KEY=inngest event key
INNGEST_SIGNIN_KEY=signkey-prod-_______
TMDB_API_KEY=api kay
STRIPE_SECRET_KEY=sk_test_...___
STRIPE_PUBLISHABLE_KEY=pk_test_....___
STRIPE_WEBHOOK_SECRET=whsec_...___
SMTP_HOST=smtp.host.com
SMTP_PORT=587
SMTP_USER=owner_email@host.com
SMTP_PASS=smtp-password
SENDER_EMAIL=owner_email@host.comThe snippets above are the requested templates; replace placeholder values with credentials from the corresponding service. The TMDB_API_KEY setting is used by the backend as a TMDB Bearer token, so provide the TMDB API Read Access Token expected by the current request code. STRIPE_PUBLISHABLE_KEY is included in the template, although the current application creates hosted Checkout Sessions on the backend and does not use that key in the client.
The requested INNGEST_SIGNIN_KEY spelling is retained exactly in the template. Confirm the signing-key variable name expected by your Inngest deployment and SDK configuration before deploying; Inngest commonly refers to its signing key as INNGEST_SIGNING_KEY.
- Push the project to GitHub without committing either
.envfile. - Create a frontend deployment from the repository's
clientdirectory. - Set the frontend build command to
npm run buildand output directory todist(Vite default). - Set the frontend environment variables listed above.
VITE_BASE_URLmust point to the deployed backend origin. - Deploy the Express backend as its own service and set the backend environment variables. The server must be reachable over HTTPS by the client and Stripe.
- Configure the Stripe webhook endpoint to reach the backend's
/api/stripeendpoint. Use the webhook signing secret for that specific endpoint inSTRIPE_WEBHOOK_SECRET. - Configure the Inngest application to reach the backend's
/api/inngestendpoint and synchronize the registered functions. - Configure Clerk's allowed origins and production keys for the deployed frontend and backend.
- Redeploy both services after changing environment variables.
π‘ The repository contains a Vite client and a standalone Express server. Deploy them using providers/settings that support their respective runtimes; do not assume that selecting the repository root will automatically deploy both. Inngest and Stripe require public, correctly configured backend endpoints.
Project_Folder/
βββ client/
βββ server/
This guide covers running the existing MoviefyHub frontend and connecting it to Clerk and the Express API. The frontend is already scaffolded; do not initialize a second Vite project in this repository.
Run the following command in your terminal:
npm init viteProceed? y
Project Name: name
Package Name: name
Select a framework: React
Select a variant: JavaScript
Select oxlintrc? Yes
Install with npm? Yes
From the repository root:
cd client
npm install
npm run devBefore starting Vite, create client/.env and set its values using the frontend environment template above. Point VITE_BASE_URL to the backend, for example http://localhost:5000, and use the TMDB image base URL appropriate for the poster size used by the UI (for example https://image.tmdb.org/t/p/w500).
The frontend dependencies are declared in client/package.json and installed by npm install. The current project uses:
@clerk/react
react-router-dom
@tailwindcss/vite
tailwindcss
react-hot-toast
axios
lucide-react
react
react-dom
No additional package installation is needed for a normal checkout. To inspect the exact installed dependency versions, refer to client/package.json and client/package-lock.json.
It automatically Create package.json if not exists. Like
The existing client/package.json includes scripts for development, build, lint, and preview:
{
"name": "client",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@clerk/react": "^6.17.5",
"@tailwindcss/vite": "^4.3.3",
"axios": "^1.20.0",
"lucide-react": "^1.51.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-hot-toast": "^2.6.1",
"react-player": "^3.4.0",
"react-router-dom": "^7.18.4",
"tailwindcss": "^4.3.3"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.7",
"@vitejs/plugin-react": "^6.1.1",
"eslint": "^10.10.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.6",
"globals": "^17.12.0",
"vite": "^8.3.0"
}
}Note: Use the existing lockfile with npm install; avoid replacing the package manifest with copied dependency versions.
Note: Install packages when needed
npm install tailwindcss @tailwindcss/viteAdd plugin to vite.config.js:
import tailwindcss from "@tailwindcss/vite";
export default {
plugins: [tailwindcss()],
};Add to index.css:
@import "tailwindcss";Installed using the official React Router CLI as per reactrouter.com:
npx create-react-router@latest
cd my-project
npm run devOr add to an existing Vite project:
npm install react-router-dom- Create a Clerk application and configure its sign-in methods and allowed origins.
- Copy the Clerk publishable key into
VITE_CLERK_PUBLISHABLE_KEYinclient/.env. - Copy the matching publishable key and secret key into
CLERK_PUBLISHABLE_KEYandCLERK_SECRET_KEYinserver/.env. - The frontend initializes
ClerkProviderinclient/src/main.jsx; the backend enablesclerkMiddleware()inserver/server.js. - Authenticated requests use Clerk session tokens. Server middleware checks Clerk private metadata for protected admin operations.
- To configure the privileged theater approval account, set that account's private metadata role to
main-admin. Approved applicants receive theadminrole; onlymain-admincan review theater requests. - If using Clerk webhooks for user synchronization, configure the Clerk-to-Inngest event integration so the Inngest functions receive
clerk/user.created,clerk/user.updated, andclerk/user.deletedevents.
Install a current Node.js LTS release compatible with the Vite frontend and backend dependencies from the Node.js Official Site.
Verify installation in your terminal:
node -v
npm -vMoviefyHub can use MongoDB Atlas or a local MongoDB service.
- For Atlas, create a cluster, database user, and network access rule, then place the connection URI in
MONGO_URI. - For a local database, install MongoDB Community Server and MongoDB Shell (
mongosh). - Verify a local shell connection with:
mongoshThe server connects with Mongoose and uses the moviefyhub database name appended to MONGO_URI.
Initialize your Node project inside any project directory:
npm initpackage name: (name)
version: (1.0.0)
description: may add β entry point: (server.js)β
test command: just enterβ
git repository: (https://github.com/username/repo_name.git)
keywords: may add
author: may add
license: (ISC) may be MIT for open source
type: (commonjs) recommended module
Is this OK? (yes)
If you want to pull this project and run it again locally, simply execute these commands:
# Navigate to the project folder
cd Project_dir
# create node_modules folder by running this command
npm i
# Start the local development server
npm startThe existing server/package.json declares "type": "module" and starts server.js; do not replace it with a newly generated package file.
{
"name": "node",
"version": "1.0.0",
"bugs": {
"url": "https://github.com/username/repo/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/username/repo.git"
},
"license": "ISC",
"author": "",
"type": "commonjs",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js" // add manually write "nodemon index.js" if installed
}
}Run this command inside your project directory to install npm pakages in pakages.json file:
npm i express
npm i mongoose
npm i nodemon
npm i cors
npm i dotenv
npm i cloudinary
npm i svix
npm i multer
npm i @clerk/express
npm i stripe
bpm i nodemailerIt automatically Create package.json if not exists. Like
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"keywords": [],
"type": "module",
"dependencies": {
"@clerk/express": "^2.1.76",
"axios": "^1.20.0",
"cloudinary": "^2.11.0",
"cors": "^2.8.6",
"dotenv": "^18.0.6",
"express": "^5.2.1",
"inngest": "^4.22.0",
"mongoose": "^9.11.0",
"nodemailer": "^10.1.0",
"nodemon": "^3.1.14",
"stripe": "^23.0.0",
"svix": "^2.8.0"
}
}Note: npm install uses the versions recorded in server/package-lock.json. Do not install duplicate or unrelated packages just to reproduce this documentation.
- Create a TMDB account and obtain an API Read Access Token.
- Set that token as
TMDB_API_KEYinserver/.env. The backend sends it in the TMDBAuthorization: Bearerheader. - The server requests now-playing data and movie details/credits when an admin adds a show. Movie details, cast, and poster/backdrop paths are stored in MongoDB.
- Set
VITE_TMDB_IMAGE_BASE_URLinclient/.envto the TMDB image base URL and a suitable image size. The client appends the stored poster path to it.
Read the TMDB API documentation and follow its attribution and usage requirements.
- Use Stripe test mode for local development and set the server's
STRIPE_SECRET_KEY. - The booking endpoint creates a hosted Stripe Checkout Session and stores its URL with the booking.
- Configure the Stripe webhook endpoint as
<BACKEND_URL>/api/stripe; webhook events must be sent as raw request bytes so signature verification works. - Set
STRIPE_WEBHOOK_SECRETto the signing secret for that webhook endpoint. Do not use the webhook secret as an API key. - The webhook handles successful payment events, marks the booking as paid, and sends an Inngest booking-confirmation event.
- Stripe Checkout currently uses USD in the backend.
VITE_CURRENCYcontrols the currency label shown in the interface; change backend payment currency logic separately if the actual charged currency needs to change. - The Checkout Session is created with a 30-minute expiration. The current Inngest seat/booking cleanup waits 10 minutes before checking for payment; align these timeouts in code if the intended reservation window should be 30 minutes.
Use Stripe's webhook testing guide and the Stripe CLI to forward test events to the local backend.
The server exposes the Inngest handler at /api/inngest and registers the functions from server/inngest/index.js. Configure the Inngest app to sync against the publicly reachable backend endpoint.
The current functions include:
- Clerk user creation, update, and deletion synchronization events.
- Payment-timeout processing that checks whether a booking was paid and releases held seats/removes an unpaid booking.
- Booking confirmation email handling after the Stripe webhook emits
app/show.booked. - A scheduled show reminder function configured with an eight-hour cron interval.
- New-show announcement emails triggered by
app/show.added.
Configure the Inngest event and signing credentials in the backend deployment environment. Confirm the signing-key variable name against the active Inngest environment. For local development, use the Inngest Dev Server or the currently supported local workflow in the Inngest documentation.
Reminder implementation note: The reminder function currently filters the show model using showTime, while the show schema stores showDateTime. Verify or update that field mapping before relying on scheduled reminders in production.
The shared Nodemailer transporter in server/config/nodemailer.js uses:
SMTP_HOSTandSMTP_PORTfor the SMTP server.SMTP_USERandSMTP_PASSfor SMTP authentication.SENDER_EMAILfor the message sender.
Use a provider-supported secure SMTP configuration, keep credentials only in the backend environment, and ensure the sender address is permitted by the provider. Inngest functions use this transporter for booking confirmations, show reminders, and new-show announcements.
- React Documentation β (React components, state, and hooks)
- Vite Guide β (Frontend development server and production builds)
- React Router Documentation β (Client-side routes and navigation)
- Tailwind CSS Documentation β (Utility-first styling and responsive layouts)
- Clerk Documentation β (React authentication, Express middleware, sessions, and user metadata)
- Express Documentation β (Node.js web framework and HTTP routing)
- Inngest Documentation β (Event-driven background functions, cron jobs, and local development)
- Axios Documentation β (HTTP requests for browser and Node.js applications)
- TMDB API Documentation β (Movie metadata, now-playing lists, credits, and image paths)
- Stripe Documentation β (Checkout Sessions, payments, test mode, and webhooks)
- Nodemailer Documentation β (SMTP-based email transport for Node.js)
- Inngest Documentation β (Reliable background execution and scheduled jobs)
- MongoDB Manual β (MongoDB documents, indexes, and CRUD operations)
- Mongoose Documentation β (MongoDB schemas, models, and queries for Node.js)
- NPM Documentation β (Node package manager and lockfiles)
- MDN Web Docs β (HTML, CSS, JavaScript, browser APIs, and HTTP)
MehmoodCoder
- π GitHub: https://github.com/MehmoodCoder
- π Portfolio: https://mh56-portfolio.vercel.app
No LICENSE file is currently included in this repository. Add a license file before redistributing the project.
Contributions are welcome. Please keep changes focused and do not commit API keys, .env files, or other credentials.
- Fork the repository.
- Create a feature branch (
git checkout -b feature/your-change). - Make and test your changes.
- Commit the changes (
git commit -m "Describe your change"). - Push the branch and open a Pull Request.
- β¨ Full-Stack Movie Booking: Connected a React 19/Vite client to an Express 5 API and MongoDB Atlas.
- π Clerk Authentication: Integrated Clerk sign-in, session tokens, and private metadata role checks.
- ποΈ TMDB Integration: Added now-playing discovery and TMDB movie details, cast, poster, and backdrop data.
- ποΈ Showtime and Seat Booking: Implemented show scheduling, seat availability, booking records, and user booking views.
- π³ Stripe Checkout: Added hosted Checkout Sessions and webhook-driven payment confirmation.
- β‘ Inngest Background Processing: Added Clerk sync, payment timeout cleanup, scheduled reminders, and booking/new-show email workflows.
- π§ SMTP Email: Integrated Nodemailer for HTML booking confirmations, reminders, and new-show announcements.
- π Admin Workflows: Added dashboard metrics, show management, booking management, and MainAdmin-only theater request approvals.
- π¨ Responsive Frontend: Built movie, showtime, favorites, booking, and admin experiences with React Router and Tailwind CSS v4.