Overview
Yoga Studio is a production-ready, full-stack website template designed for yoga studios, fitness centers, and wellness businesses. Built with Next.js 16, React 19, MongoDB, and Tailwind CSS 4, it provides a stunning public-facing landing page and a powerful admin dashboard for complete content management.
Every element of the public website — from hero banners to team members, gallery images, class schedules, and more — is fully manageable through the admin panel without writing a single line of code.
Tech Stack
| Layer | Technology |
| Framework | Next.js 16.2.3 (App Router) |
| Frontend | React 19.2.5, Tailwind CSS 4.1.13 |
| UI Components | Radix UI, shadcn/ui patterns (40+ components) |
| State Management | Zustand 5.0.8 |
| Forms & Validation | React Hook Form + Zod |
| Backend | Next.js API Routes (Node.js) |
| Database | MongoDB with Mongoose ODM |
| Authentication | NextAuth 5 + JWT (jsonwebtoken) + bcrypt |
| File Storage | Cloudinary CDN |
| Rich Text Editor | SunEditor |
| Data Tables | TanStack React Table |
| Charts | Recharts |
| Drag & Drop | DnD Kit |
| Icons | Lucide React, React Icons |
| Carousels | Splide, Embla Carousel |
| Video | React Player |
Features
Public Website
- Responsive landing page with 15+ configurable sections
- Hero banner with dynamic content
- About Us & Founder sections
- Types of Yoga showcase with icons
- Classes & Programs display
- Yoga at Home section
- Image & Video galleries
- Why Choose Us section with stats
- Pricing plans
- Testimonials & FAQ sections
- Contact form with submissions management
- Newsletter subscription
- Team member directory
- SEO metadata management
- Dark/Light theme support
Admin Dashboard
- Secure JWT-based authentication
- Dashboard with real-time statistics
- Full CRUD for all content types
- Drag-and-drop reordering
- Active/Inactive status toggle
- Rich text editor (SunEditor)
- Image upload with Cloudinary integration
- Contact & subscription management
- Business hours configuration
- General settings (logo, favicon, social links)
- SEO metadata editor
- Terms & Privacy policy editor
- Page banner management
Requirements
| Requirement | Version / Details |
| Node.js | 18.x or higher |
| Package Manager | pnpm (recommended), npm, or yarn |
| MongoDB | Atlas (cloud) or local instance |
| Cloudinary | Free or paid account for media storage |
Installation
Step 1: Clone the Repository
git clone <repository-url>
cd template-yoga
Step 2: Install Dependencies
pnpm install
Step 3: Configure Environment Variables
Create a .env file in the root directory (see Environment Variables section below).
Step 4: Run the Development Server
pnpm dev
The application will start at http://localhost:3000.
Step 5: Build for Production
pnpm build
pnpm start
Note: On first run, the application automatically creates a default admin account. See
Default Credentials.
Environment Variables
Create a .env file in the project root with the following variables:
| Variable | Description | Example |
AUTH_TRUST_HOST | Trust the host header for authentication | true |
NEXTAUTH_SECRET | Secret key for JWT signing (generate a secure random string) | your-secret-key-here |
NEXTAUTH_URL | Base URL for NextAuth callbacks | http://localhost:3000 |
NEXT_PUBLIC_BASE_URL | Public-facing base URL | http://localhost:3000 |
MONGODB_URI | MongoDB connection string | mongodb+srv://user:pass@host/dbname |
Note: Cloudinary credentials are configured through the Admin Dashboard > Settings page, not via environment variables.
Default Admin Credentials
On first startup, the application seeds a default admin account:
| Field | Value |
| Email | admin@example.com |
| Password | ChangeMe123! |
Important: Change these credentials immediately after your first login through Admin Dashboard > Profile settings.
Available Scripts
| Command | Description |
pnpm dev | Start development server on port 3000 (with hot reload) |
pnpm build | Create optimized production build |
pnpm start | Start production server |
pnpm lint | Run ESLint for code quality checks |
Project Structure
template-yoga/
├── app/ # Next.js App Router
│ ├── (admin)/ # Admin login route group
│ │ └── admin/login/ # Login page & components
│ ├── (private)/ # Protected admin routes
│ │ └── admin/dashboard/ # Dashboard & management pages
│ │ ├── intro/ # Hero section editor
│ │ ├── about-us/ # About section editor
│ │ ├── why-choose-us/ # Why Choose Us editor
│ │ ├── types-of-yoga/ # Yoga types CRUD
│ │ ├── classes-and-programs/ # Classes section editor
│ │ ├── yoga-at-home/ # Yoga at Home editor
│ │ ├── team/ # Team members CRUD
│ │ ├── gallery/ # Image gallery CRUD
│ │ ├── contact/ # Contact submissions
│ │ ├── subscriptions/ # Newsletter subscribers
│ │ └── settings/ # Site settings
│ ├── (public)/ # Public-facing routes
│ │ ├── page.tsx # Landing page
│ │ └── team/ # Team directory
│ ├── api/ # API endpoints
│ │ ├── admin/ # Protected admin APIs
│ │ │ ├── auth/ # Login, profile, password
│ │ │ ├── yoga/ # Yoga CRUD + sort + status
│ │ │ ├── team/ # Team CRUD + sort + status
│ │ │ ├── gallery/ # Gallery CRUD + sort + status
│ │ │ ├── video-gallery/ # Video CRUD + sort + status
│ │ │ ├── yoga-schedule/ # Schedule CRUD + sort
│ │ │ ├── banner/ # Banner management
│ │ │ ├── home-section/ # Dynamic home sections
│ │ │ ├── contact-us/ # Contact submissions
│ │ │ ├── subscribe/ # Subscriber list
│ │ │ ├── file/ # File upload & delete
│ │ │ ├── dashboard/ # Statistics endpoint
│ │ │ └── settings/ # All settings endpoints
│ │ ├── auth/ # NextAuth route handler
│ │ └── public/ # Public APIs (no auth)
│ ├── documentation/ # Documentation page
│ ├── layout.tsx # Root layout
│ └── globals.css # Global styles
│
├── actions/ # Next.js Server Actions
│ ├── adminLogin/ # Login actions
│ ├── dashboard/ # Dashboard data fetching
│ ├── yoga/ # Yoga operations
│ ├── yogaSchedule/ # Schedule operations
│ ├── team/ # Team operations
│ ├── gallery/ # Gallery operations
│ ├── profile/ # Profile management
│ ├── settings/ # Settings management
│ ├── contacts/ # Contact management
│ ├── subscriptions/ # Subscription management
│ ├── whyChoseUs/ # Why Choose Us section
│ ├── yogaAtHome/ # Yoga at Home section
│ └── public/ # Public data fetching
│
├── components/ # React Components
│ ├── ui/ # 40+ Base UI components (shadcn/Radix)
│ ├── custom/ # Custom components
│ ├── features/ # Feature-specific components
│ │ ├── landing/ # 15+ landing page sections
│ │ ├── dashboard/ # Dashboard widgets
│ │ └── public/ # Public page components
│ ├── forms/ # Form field components
│ ├── layouts/ # Layout components (header, footer)
│ ├── providers/ # Context providers (auth, theme)
│ ├── shared/ # Shared utility components
│ └── tables/ # Data table components
│
├── model/ # Mongoose Database Models
│ ├── User.ts # Admin user model
│ ├── Yoga.ts # Yoga types
│ ├── Team.ts # Team members
│ ├── Gallery.ts # Image gallery
│ ├── VideoGallery.ts # Video gallery
│ ├── YogaSchedule.ts # Class schedules
│ ├── Banner.ts # Banner / hero
│ ├── HomeSection.ts # Dynamic home sections
│ ├── Settings.ts # Site settings (singleton)
│ ├── Subscribe.ts # Newsletter subscribers
│ └── Contactus.ts # Contact submissions
│
├── lib/ # Utility Libraries
│ ├── async-handler.ts # API wrapper with auth & validation
│ ├── async-formdata-handler.ts # FormData processing wrapper
│ ├── authenticate.ts # JWT token verification
│ ├── api-client.ts # Client-side API wrapper
│ ├── server-utils.ts # Server response & JWT helpers
│ ├── file-validator.ts # File type & size validation
│ ├── mongo-adapter.ts # MongoDB aggregation helpers
│ ├── validation-schema.ts # Zod validation schemas
│ ├── metadata.ts # SEO metadata generation
│ └── utils.ts # General utility functions
│
├── config/ # Configuration
│ ├── constant.ts # Roles & cache tag constants
│ ├── database.ts # MongoDB connection & seeding
│ ├── cloudinary.ts # Cloudinary upload/delete
│ ├── routes.ts # Route definitions
│ └── cache.ts # In-memory caching
│
├── hooks/ # React Custom Hooks
├── contexts/ # React Contexts
├── types/ # TypeScript Type Definitions
├── public/ # Static Assets (fonts, images)
│
├── .env # Environment variables
├── next.config.ts # Next.js configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── tsconfig.json # TypeScript configuration
├── Dockerfile # Docker containerization
├── postcss.config.mjs # PostCSS configuration
├── components.json # shadcn/ui configuration
└── package.json # Dependencies & scripts
Database Models
The application uses MongoDB with Mongoose ODM. Below are all 11 collections and their schemas.
User
| Field | Type | Description |
name | String | User display name |
email | String (unique) | Login email address |
password | String | Bcrypt-hashed password |
role | Enum | admin or user |
Yoga
| Field | Type | Description |
title | String | Yoga type name |
description | String | Detailed description |
image | String | Cloudinary image public_id |
icon | String | Cloudinary icon public_id |
position | Number | Display order (default: 0) |
status | Boolean | Active/inactive (default: true) |
Team
| Field | Type | Description |
name | String | Member name |
image | String | Cloudinary image public_id |
designation | String | Job title / role |
details | String | Biography or details |
position | Number | Display order (default: 0) |
status | Boolean | Active/inactive (default: true) |
YogaSchedule
| Field | Type | Description |
yoga | ObjectId (ref: Yoga) | Reference to Yoga type |
instructor | ObjectId (ref: Team) | Reference to Team member |
timeSlots | Array | [{startTime, endTime, days[]}] |
position | Number | Display order (default: 0) |
status | Boolean | Active/inactive (default: true) |
Gallery
| Field | Type | Description |
image | String | Cloudinary image public_id |
title | String | Optional caption |
status | Boolean | Active/inactive (default: true) |
orderBy | Number | Display order (default: 0) |
VideoGallery
| Field | Type | Description |
video | String | Video URL or Cloudinary public_id |
title | String | Optional video title |
status | Boolean | Active/inactive (default: true) |
orderBy | Number | Display order (default: 0) |
Banner
| Field | Type | Description |
heading | String | Banner headline text |
shortDesc | String | Short description |
imageOne | String | Primary image (Cloudinary ID) |
imageTwo | String | Secondary image (Cloudinary ID) |
sectionName | Enum | banner or section |
categories | String | Optional categories |
position | Number | Display order (default: 0) |
status | Boolean | Active/inactive (default: true) |
HomeSection
| Field | Type | Description |
sectionKey | String (unique) | Unique section identifier |
title | String | Section title |
subTitle | String | Section subtitle |
sectionImage | String | Section hero image |
images | Array | Array of Cloudinary image IDs |
videos | Array | Array of video URLs |
features | Array | [{title, description}] |
stats | Array | [{value, suffix, label}] |
content | Object | Flexible content object |
status | Boolean | Active/inactive (default: true) |
orderBy | Number | Display order (default: 0) |
Settings (Singleton)
| Section | Key Fields |
general | companyName, phone, address, email, logo, favicon, social links |
pageBanner | menu, location, gallery, reserveTable (Cloudinary IDs) |
cloudinary | cloudName, apiKey, apiSecret, folderName, secureUrlBase |
metadata | title, applicationName, description, keywords[], openGraphImage |
termsPolicy | terms, policy (HTML content) |
businessHours | Array of {dayOfWeek, openTime, closeTime, isClosed} |
Subscribe
| Field | Type | Description |
email | String (unique) | Subscriber email address |
Contactus
| Field | Type | Description |
name | String | Sender name |
email | String | Sender email |
message | String | Message content |
isCheck | Boolean | Read/unread status (default: false) |
Note: All models include automatic createdAt and updatedAt timestamps via Mongoose.
Authentication System
The application uses JWT-based authentication with NextAuth 5.
Login Flow
- Admin submits email and password to
POST /api/admin/auth/login
- Server verifies credentials against bcrypt-hashed password in database
- On success, a JWT token is generated with 30-day expiration
- Token payload contains:
{ email, role: 'admin' }
- Client stores the token and sends it in subsequent requests via
Authorization: Bearer {token} header
Route Protection
- Admin API routes use the
asyncHandler() middleware with authentication enabled
- JWT is verified on every request using the
NEXTAUTH_SECRET
- Invalid or expired tokens return
401 Unauthorized
- User data is extracted from the token and attached to the request context
Password Security
- Passwords are hashed using bcrypt with 10 salt rounds
- Password change requires the current password for verification
- New password confirmation is enforced via Zod validation
Cloudinary Integration
All media files (images and videos) are stored on Cloudinary CDN for optimized delivery and management.
Setup
- Create a free account at cloudinary.com
- Navigate to Admin Dashboard > Settings in your application
- Enter your Cloudinary credentials: Cloud Name, API Key, API Secret
- Set a Folder Name for organized storage
- Enter the Secure URL Base (e.g.,
https://res.cloudinary.com/your-cloud)
Features
- Automatic image optimization and responsive delivery
- Secure URL generation for all assets
- Folder-based organization
- Upload and delete operations via the admin panel
- File type and size validation before upload
Utility Functions
| Function | Description |
uploadImage() | Upload a single image to Cloudinary |
uploadToCloudinary() | Alternative upload with custom options |
deleteFromCloudinary() | Delete a file by its public_id |
cloudinarySecureUrlBase() | Get the configured base URL |
getCloudinaryFolderName() | Get the configured folder name |
API Reference: Authentication
Base URL: /api/admin/auth
| Method | Endpoint | Description | Auth |
| POST | /api/admin/auth/login | Admin login | No |
| GET | /api/admin/auth/me | Get admin profile | Yes |
| PUT | /api/admin/auth/me | Update admin profile | Yes |
| PUT | /api/admin/auth/password | Change password | Yes |
POST /api/admin/auth/login
Request body:
{
"email": "admin@example.com",
"password": "ChangeMe123!"
}
Success response:
{
"success": true,
"data": { "token": "eyJhbGciOiJIUzI1NiIs..." }
}
PUT /api/admin/auth/password
Request body:
{
"oldPassword": "ChangeMe123!",
"newPassword": "NewSecurePass456!",
"confirmPassword": "NewSecurePass456!"
}
API Reference: Yoga Management
Base URL: /api/admin/yoga — All endpoints require Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/yoga | Create yoga type (multipart/form-data) |
| GET | /api/admin/yoga | List all yoga types |
| GET | /api/admin/yoga/:id | Get single yoga type |
| PUT | /api/admin/yoga/:id | Update yoga type (multipart/form-data) |
| DELETE | /api/admin/yoga/:id | Delete yoga type |
| PUT | /api/admin/yoga/sort | Reorder yoga types |
| PUT | /api/admin/yoga/status/:id | Toggle active/inactive status |
Create/Update Yoga (multipart/form-data)
| Field | Type | Required | Description |
title | String | Yes | Yoga type name |
description | String | No | Description text |
image | File | Yes | Yoga image file |
icon | File | Yes | Yoga icon file |
position | Number | No | Display order |
status | Boolean | No | Active by default |
Reorder (PUT /api/admin/yoga/sort)
{ "sortedIds": ["id1", "id2", "id3"] }
Toggle Status (PUT /api/admin/yoga/status/:id)
{ "status": true }
API Reference: Team Management
Base URL: /api/admin/team — All endpoints require Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/team | Create team member (multipart/form-data) |
| GET | /api/admin/team | List all team members |
| GET | /api/admin/team/:id | Get single team member |
| PUT | /api/admin/team/:id | Update team member (multipart/form-data) |
| DELETE | /api/admin/team/:id | Delete team member |
| PUT | /api/admin/team/sort | Reorder team members |
| PUT | /api/admin/team/status/:id | Toggle active/inactive status |
Create/Update Team Member (multipart/form-data)
| Field | Type | Required | Description |
name | String | Yes | Member name |
designation | String | Yes | Job title / role |
details | String | Yes | Biography text |
image | File | Yes | Profile photo |
status | Boolean | No | Active by default |
API Reference: Gallery Management
Base URL: /api/admin/gallery — All endpoints require Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/gallery | Upload gallery image (multipart/form-data) |
| GET | /api/admin/gallery | List all gallery images |
| DELETE | /api/admin/gallery/:id | Delete gallery image |
| PUT | /api/admin/gallery/sort | Reorder gallery images |
| PUT | /api/admin/gallery/status/:id | Toggle image active/inactive |
API Reference: Video Gallery Management
Base URL: /api/admin/video-gallery — All endpoints require Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/video-gallery | Upload video (multipart/form-data) |
| GET | /api/admin/video-gallery | List all videos |
| GET | /api/admin/video-gallery/:id | Get single video |
| PUT | /api/admin/video-gallery/:id | Update video (multipart/form-data) |
| DELETE | /api/admin/video-gallery/:id | Delete video |
| PUT | /api/admin/video-gallery/sort | Reorder videos |
| PUT | /api/admin/video-gallery/status/:id | Toggle video active/inactive |
API Reference: Yoga Schedule Management
Base URL: /api/admin/yoga-schedule — All endpoints require Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/yoga-schedule | Create schedule |
| GET | /api/admin/yoga-schedule | List all schedules (with lookups) |
| GET | /api/admin/yoga-schedule/:id | Get single schedule |
| PUT | /api/admin/yoga-schedule/:id | Update schedule |
| DELETE | /api/admin/yoga-schedule/:id | Delete schedule |
| PUT | /api/admin/yoga-schedule/sort | Reorder schedules |
Create Schedule (POST /api/admin/yoga-schedule)
{
"yoga": "ObjectId",
"instructor": "ObjectId",
"timeSlots": [
{
"startTime": "09:00",
"endTime": "10:00",
"days": ["MON", "WED", "FRI"]
}
],
"position": 1,
"status": true
}
API Reference: Banner Management
Base URL: /api/admin/banner — Requires Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/banner | Create or update banner (multipart/form-data) |
| GET | /api/admin/banner | Get current banner |
API Reference: Home Section Management
Base URL: /api/admin/home-section — Requires Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/home-section | Create or update a home section |
| GET | /api/admin/home-section/name/:slug | Get section by slug key |
Create/Update Home Section
{
"sectionKey": "about-us",
"title": "About Our Studio",
"subTitle": "Where Mind Meets Body",
"features": [
{ "title": "Expert Teachers", "description": "Certified instructors" }
],
"stats": [
{ "value": "500", "suffix": "+", "label": "Students Trained" }
],
"status": true,
"orderBy": 1
}
API Reference: Subscription Management
Base URL: /api/admin/subscribe — Requires Bearer token authentication.
| Method | Endpoint | Description |
| GET | /api/admin/subscribe | List newsletter subscribers (paginated) |
Supports the same pagination query parameters as the Contact endpoint.
API Reference: File Management
Base URL: /api/admin/file — Requires Bearer token authentication.
| Method | Endpoint | Description |
| POST | /api/admin/file | Upload image(s) to Cloudinary |
| DELETE | /api/admin/file | Delete image(s) from Cloudinary |
Upload (POST, multipart/form-data)
| Field | Type | Description |
image | File | Single image upload |
images | File[] | Multiple images upload |
Response:
{
"success": true,
"data": {
"single": { "imageId": "public_id", "url": "https://..." },
"multiple": [{ "imageId": "public_id", "url": "https://..." }],
"all": [{ "imageId": "public_id", "url": "https://..." }]
}
}
Delete (DELETE)
{
"imageId": "single_public_id",
"imageIds": ["id1", "id2"]
}
API Reference: Dashboard Statistics
| Method | Endpoint | Description |
| GET | /api/admin/dashboard/stats | Get dashboard overview statistics |
Response:
{
"success": true,
"data": {
"yoga": { "active": 5, "inactive": 2, "total": 7 },
"gallery": { "active": 12, "inactive": 1, "total": 13 },
"team": { "active": 4, "inactive": 0, "total": 4 }
}
}
API Reference: Settings
All settings endpoints require Bearer token authentication.
General Settings
| Method | Endpoint | Description |
| GET | /api/admin/settings/general | Get general settings |
| PUT | /api/admin/settings/general | Update general settings (multipart/form-data) |
Update Fields (multipart/form-data)
| Field | Type | Description |
companyName | String | Company name |
companyDialCode | String | Phone dial code |
companyPhone | String | Phone number |
companyAddress | String | Company address |
supportEmail | String | Support email |
ownerName | String | Owner name |
ownerEmail | String | Owner email |
logo | File | Company logo image |
favicon | File | Site favicon image |
facebook | String | Facebook page URL |
instagram | String | Instagram profile URL |
twitter | String | Twitter/X profile URL |
youtube | String | YouTube channel URL |
Cloudinary Settings
| Method | Endpoint | Description |
| GET | /api/admin/settings/cloudinary | Get Cloudinary configuration |
| PUT | /api/admin/settings/cloudinary | Update Cloudinary configuration |
{
"cloudName": "your-cloud",
"apiKey": "123456789",
"apiSecret": "secret",
"folderName": "yoga-studio",
"secureUrlBase": "https://res.cloudinary.com/your-cloud"
}
Business Hours
| Method | Endpoint | Description |
| GET | /api/admin/settings/business-hour | Get business hours |
| PUT | /api/admin/settings/business-hour | Update business hours |
{
"businessHour": [
{ "dayOfWeek": 0, "openTime": 540, "closeTime": 1080, "isClosed": false },
{ "dayOfWeek": 6, "openTime": 0, "closeTime": 0, "isClosed": true }
]
}
Note: openTime and closeTime are in minutes from midnight (e.g., 540 = 9:00 AM, 1080 = 6:00 PM).
SEO Metadata
| Method | Endpoint | Description |
| GET | /api/admin/settings/metadata | Get SEO metadata |
| PUT | /api/admin/settings/metadata | Update SEO metadata (multipart/form-data) |
Page Banners
| Method | Endpoint | Description |
| GET | /api/admin/settings/page-banner | Get page banner images |
| PUT | /api/admin/settings/page-banner | Update page banners (multipart/form-data) |
Terms & Policies
| Method | Endpoint | Description |
| GET | /api/admin/settings/terms | Get terms & privacy policy |
| PUT | /api/admin/settings/terms | Update terms & privacy policy |
{
"terms": "<p>Your terms of service HTML content...</p>",
"policy": "<p>Your privacy policy HTML content...</p>"
}
API Reference: Public Endpoints
These endpoints do not require authentication and are used by the public-facing website.
| Method | Endpoint | Description |
| GET | /api/public/yoga | List active yoga types |
| GET | /api/public/team | List active team members |
| GET | /api/public/gallery | List active gallery images |
| GET | /api/public/video-gallery | List active videos |
| GET | /api/public/yoga-schedule | List active schedules |
| GET | /api/public/banner | Get banner data |
| GET | /api/public/home-section/:slug | Get home section by key |
| POST | /api/public/subscribe | Subscribe to newsletter |
| POST | /api/public/contact-us | Submit contact form |
| GET | /api/public/settings?context=... | Get public settings |
POST /api/public/subscribe
{ "email": "user@example.com" }
POST /api/public/contact-us
{
"name": "John Doe",
"email": "john@example.com",
"message": "I'd like to know more about your classes."
}
GET /api/public/settings
The context query parameter accepts one of:
general — Company info, logo, social links
pageBanner — Page banner images
cloudinary — Cloudinary base URL
metadata — SEO metadata
termsPolicy — Terms & privacy policy
businessHours — Business hours schedule
Admin Dashboard Pages
| Route | Description |
/admin/login | Admin authentication page |
/admin/dashboard | Overview with statistics cards and charts |
/admin/dashboard/intro | Hero/intro section content editor |
/admin/dashboard/about-us | About Us section editor with features & stats |
/admin/dashboard/why-choose-us | Why Choose Us section editor |
/admin/dashboard/types-of-yoga | Yoga types CRUD with drag-and-drop ordering |
/admin/dashboard/classes-and-programs | Classes & programs section editor |
/admin/dashboard/yoga-at-home | Yoga at Home section editor |
/admin/dashboard/team | Team members CRUD with drag-and-drop |
/admin/dashboard/gallery | Image gallery with drag-and-drop ordering |
/admin/dashboard/contact | Contact form submissions with read/unread status |
/admin/dashboard/subscriptions | Newsletter subscriber list |
/admin/dashboard/settings | General, Cloudinary, business hours, SEO, banners, terms |
Public Pages
| Route | Description |
/ | Landing page with all configurable sections |
/team | Team member directory page |
Landing Page Sections
The landing page is composed of the following configurable sections (all manageable from admin dashboard):
- Hero Banner
- About Us
- About Founder
- Types of Yoga
- Classes & Programs
- Yoga at Home
- Why Choose Us
- Image Gallery
- Video Gallery
- Yoga Categories
- Features
- Pricing Plans
- Testimonials
- FAQ
- Call to Action
- Contact Form
Component Library
The template includes 40+ base UI components built with Radix UI and shadcn/ui patterns, plus custom components for specific functionality.
Base UI Components (components/ui/)
Accordion, Alert, Alert Dialog, Aspect Ratio, Avatar, Badge, Button, Calendar, Card, Carousel, Chart, Checkbox, Collapsible, Command, Context Menu, Dialog, Drawer, Dropdown Menu, Form, Hover Card, Input, Input OTP, Label, Menubar, Navigation Menu, Pagination, Popover, Progress, Radio Group, Resizable, Scroll Area, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Switch, Table, Tabs, Textarea, Toast, Toggle, Toggle Group, Tooltip.
Custom Components (components/custom/)
| Component | Description |
rich-text-editor.tsx | SunEditor WYSIWYG editor wrapper |
img-dropzone-single.tsx | Drag-and-drop file upload zone |
PhoneInputField.tsx | International phone number input |
DynamicBreadcrumb.tsx | Auto-generating breadcrumb navigation |
CustomImage.tsx | Image component with Cloudinary URL support |
modal.tsx | Reusable modal dialog |
marquee.tsx | Scrolling marquee text component |
custom-button.tsx | Extended button with loading states |
Data Table Components (components/tables/)
Built with TanStack React Table, includes sortable columns, pagination, search toolbar, faceted filtering, and column visibility options.
Docker Deployment
A Dockerfile is included for containerized deployment.
# Build the Docker image
docker build -t yoga-studio .
# Run the container
docker run -p 3000:3000 --env-file .env yoga-studio
Tip: For production, use a process manager like PM2 or deploy to platforms like Vercel, Railway, or AWS ECS.
Customization
Theming
- Colors and styles are managed through Tailwind CSS configuration
- Dark/Light mode is built-in via
next-themes
- Custom CSS variables for theme colors are defined in
globals.css
Fonts
Four Google Fonts are loaded in the root layout:
| Font | CSS Variable | Usage |
| Poppins | --font-poppins | Primary body font |
| Outfit | --font-outfit | Headings |
| Montserrat | --font-montserrat | Accent text |
| La Belle Aurore | --font-labelleaurore | Decorative / script |
Adding New Sections
- Create a new Mongoose model in
model/
- Add API routes in
app/api/admin/
- Create server actions in
actions/
- Build the admin management page in
app/(private)/admin/dashboard/
- Add the public-facing component in
components/features/landing/
Changelog
Version 1.0.0 — Initial Release
- Full-stack Next.js 16 application with App Router
- React 19 with Tailwind CSS 4
- Admin dashboard with complete content management system
- 15+ configurable landing page sections
- MongoDB with Mongoose ODM (11 collections)
- Cloudinary media management integration
- JWT-based authentication with NextAuth 5
- 40+ Radix UI / shadcn components
- Dark/Light theme support
- Drag-and-drop content reordering
- Docker deployment support
- Fully responsive design
- SEO optimization with metadata management
Support
For support, questions, or feature requests, please reach out through the item support channel on the marketplace where you purchased this template.
When reporting an issue, please include:
- Your Node.js version (
node -v)
- Your package manager and version
- The error message or screenshot
- Steps to reproduce the issue