SweatUp is a fullstack fitness class booking application built to streamline the experience of finding, booking, and managing fitness classes. Designed for customers, instructors, and administrators, SweatUp allows users to explore available classes, purchase membership packages, book schedules, check in to sessions, and submit class reviews β all from an intuitive web interface.
The platform supports role-based access, automated class scheduling, real-time notifications, and secure online payments. With a powerful admin dashboard, administrators can manage instructors, class schedules, user bookings, and monitor activity across the system efficiently. SweatUp aims to bring convenience, structure, and scalability to fitness businesses through modern web technology.
SweatUp was developed to digitize and streamline the fitness class booking process for both customers and administrators. Traditional manual booking processes and third-party scheduling tools were inefficient, lacked flexibility for recurring schedules, and offered limited control over class attendance and instructor assignments. SweatUp was designed as an in-house, scalable alternative to unify all these features into one cohesive platform.
The platform became a key internal system for managing memberships, schedules, bookings, and attendance β reducing operational friction while improving user engagement and automation capabilities.
- Enable customers to browse and book fitness classes based on time, instructor, and location
- Support one-time and recurring class scheduling with automated generation
- Implement role-based dashboards (customer, instructor, admin)
- Handle class check-ins and attendance with QR code validation
- Integrate payments via Stripe or Midtrans
- Send real-time and scheduled reminders via email or in-app notification
The main challenge in developing SweatUp was designing a scheduling system flexible enough to accommodate recurring and non-recurring classes, its tricky to manage a schedule to prevent conflict between instructor at the same schedule, while supporting real-time booking availability, instructor assignments, and attendance tracking. The application also needed to handle role-based access, reminders, and multiple payment scenarios β all within a user-friendly interface for both customers and admins.
To address this, I built a fullstack web application using Go (Gin) for the backend and React for the frontend. The system featured a dynamic schedule engine that supported recurring class templates and one-time sessions, with conflict detection and automatic schedule generation via cron jobs. Users could purchase membership packages, book classes, check-in and check-out using codes. Instructors had tools to manage attendance and class updates, while admins could monitor system activity through a dashboard. Payment was integrated using Stripe and notifications were delivered via email and in-app alerts.
-
JWT + OAuth Authentication β Combines traditional login with Google OAuth integration
-
Automatic Caching System using TanStack React Query for optimal performance
-
Interactive Calendar Board for class management and scheduling
-
Scheduled & Recurring Class Generation powered by automated cron jobs
-
Class Booking Based on User Package Quotas
-
Attendance System using code for checkout
-
Review & Rating System for evaluating class and instructor quality
-
Frontend Google OAuth Login for seamless authentication
-
Automated Database Backup via scheduled cron jobs
-
Role-Based Access Control (Admin, Customer, Owner) for secure access and management
-
Admin Dashboard with real-time performance monitoring, user statistics, and revenue tracking
- React 18 with React Router v7
- TailwindCSS + Radix UI + ShadCN UI
- React Hook Form + Zod (validasi form)
- Zustand (state management)
- TanStack React Query (data fetching and caching)
- Framer Motion
- Google OAuth via
@react-oauth/google
- Vite (build tool)
- Golang (Gin Framework)
- GORM (ORM for MySQL)
- MySQL (Main database)
- Redis (Caching & token store)
- Stripe (Payment gateway)
- RabbitMQ (Event-driven notification)
- JWT Auth (Access & Refresh Token)
- VPS Hosting
- github Action for CI / CD
- Docker + Docker Compose
- Nginx for Reverse proxy
src/
βββ assets/ # Static files such as images, icons, and fonts
βββ components/ # Reusable global UI components
βββ pages/ # Page-level modules organized by main features
β βββ auth/ # Authentication pages (Login, Register)
β βββ public/ # Public pages (Home, About, Class/Package Details)
β βββ admin/ # Admin-specific pages and dashboards
βββ hooks/ # Global custom React hooks
β βββ useScrollToTop.js
β βββ useModal.js
βββ lib/ # Utility functions and configuration files
β βββ axios.js # Axios instance with baseURL and interceptors
β βββ utils.js # General utility functions
β βββ constant.js # Constants used across the app
β βββ schema.js # Zod schemas or validation rules
βββ middleware/ # Client-side route guards (e.g., protected routes)
β βββ protected_route.jsx
βββ service/ # API service modules to interact with the backend
β βββ auth.js
β βββ product.js
βββ store/ # Global state management (e.g., Zustand stores)
β βββ useAuthStore.ts
βββ App.jsx # Root component defining app layout and routes
βββ main.jsx # Entry point for rendering the React app
βββ vite-env.d.js # Vite environment types and setup
βββ index.html # HTML template used by Vite
server/
βββ cmd/ # Main entry point of the application
β βββ main.go # The main file that runs the server
βββ internal/
β βββ config/ # Initialization of DB, Redis, Stripe, Cloudinary, etc.
β βββ handlers/ # HTTP handlers for each feature (Controller layer)
β βββ services/ # Core business logic of the application
β βββ repositories/ # Direct access to the database (Query layer)
β βββ models/ # GORM model definitions
β βββ routes/ # Route grouping initialization per feature
β βββ seeders/ # Seeders for initial system data
β βββ dto/ # Data Transfer Objects for request/response handling
βββ pkg/
β βββ middleware/ # Reusable middleware (JWT, CORS, rate limiter)
β βββ utils/ # Common utility functions (e.g., conversion, time, etc.)
β βββ helper/ # Additional helpers (e.g., formatting, error handling)
βββ tests/
β βββ mocks/ # Mock data and objects for unit testing
β βββ handlers/
β βββ services/
β βββ repositories/
βββ go.mod # Go module dependency configuration
βββ Dockerfile # Docker build instructions
βββ docker-compose.yml # Multi-container setup for local development
βββ deploy.sh # Script for automated deployment
βββ .env # Environment variables for local configuration
- OTP Login & Google OAuth β Supports both email-based OTP authentication and Google sign-in for flexible user onboarding
- X-API-KEY Validation β Secures selected endpoints with API key verification for external service access
- Refresh Token Mechanism β Automatically refreshes access tokens to maintain user sessions without requiring re-login
- Role-Based Middleware β Protects routes based on user roles (customer, admin, instructor) to ensure proper access control
Method | Endpoint | Description |
---|---|---|
POST | /api/auth/login | User login |
POST | /api/auth/logout | User logout |
POST | /api/auth/register | User registration |
POST | /api/auth/send-otp | Send OTP |
POST | /api/auth/verify-otp | Verify OTP |
POST | /api/auth/refresh-token | Refresh access token |
GET | /api/auth/google | Google OAuth login |
GET | /api/auth/google/callback | Google OAuth callback |
GET | /api/auth/me | Get current user profile |
Method | Endpoint | Description |
---|---|---|
GET | /api/packages | Get all packages |
GET | /api/packages/:id | Get package detail |
POST | /api/admin/packages | Create new package (admin) |
PUT | /api/admin/packages/:id | Update package (admin) |
DELETE | /api/admin/packages/:id | Delete package (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/classes | Get all classes |
GET | /api/classes/:id | Get class detail |
POST | /api/admin/classes | Create new class (admin) |
PUT | /api/admin/classes/:id | Update class (admin) |
DELETE | /api/admin/classes/:id | Delete class (admin) |
POST | /api/admin/classes/:id/gallery | Upload class gallery (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/schedules | Get all class schedules |
GET | /api/schedules/:id | Get schedule detail |
GET | /api/schedules/status | Get user booking status |
GET | /api/instructor/schedules | Get instructor schedules |
GET | /api/instructor/schedules/:id/attendance | Get class attendances (instructor) |
PATCH | /api/instructor/schedules/:id/open | Open class for check-in |
POST | /api/admin/schedules | Create class schedule (admin) |
POST | /api/admin/schedules/recurring | Create recurring schedule (admin) |
PUT | /api/admin/schedules/:id | Update schedule (admin) |
DELETE | /api/admin/schedules/:id | Delete schedule (admin) |
Method | Endpoint | Description |
---|---|---|
POST | /api/bookings | Create booking (customer) |
GET | /api/bookings | Get user bookings (customer) |
GET | /api/bookings/:id | Get booking detail |
POST | /api/bookings/:id/check-in | Check-in to class |
POST | /api/bookings/:id/check-out | Check-out from class |
Method | Endpoint | Description |
---|---|---|
GET | /api/instructors | List instructors |
GET | /api/instructors/:id | Get instructor detail |
POST | /api/admin/instructors | Add instructor (admin) |
PUT | /api/admin/instructors/:id | Update instructor (admin) |
DELETE | /api/admin/instructors/:id | Delete instructor (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/categories | Get all categories |
GET | /api/categories/:id | Get category detail |
POST | /api/admin/categories | Create category (admin) |
PUT | /api/admin/categories/:id | Update category (admin) |
DELETE | /api/admin/categories/:id | Delete category (owner) |
GET | /api/subcategories | Get all subcategories |
GET | /api/subcategories/:id | Get subcategory detail |
GET | /api/subcategories/category/:id | Get subcategories by category |
POST | /api/admin/subcategories | Create subcategory (admin) |
PUT | /api/admin/subcategories/:id | Update subcategory (admin) |
DELETE | /api/admin/subcategories/:id | Delete subcategory (admin) |
... | Similar structure for types, levels, locations |
Method | Endpoint | Description |
---|---|---|
GET | /api/notifications | Get user notifications |
PATCH | /api/notifications/read | Mark all as read |
GET | /api/notifications/settings | Get notification settings |
PUT | /api/notifications/settings | Update notification settings |
POST | /api/admin/notifications/broadcast | Send broadcast (admin) |
Method | Endpoint | Description |
---|---|---|
POST | /api/payments | Create payment (customer) |
GET | /api/payments/me | Get user payment history |
GET | /api/payments/me/:id | Get payment detail |
POST | /api/payments/stripe/notifications | Stripe webhook |
GET | /api/admin/payments | Get all payments (admin) |
GET | /api/admin/payments/:id | Get payment detail (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/vouchers | Get all vouchers (customer) |
POST | /api/vouchers/apply | Apply voucher (customer) |
POST | /api/admin/vouchers | Create voucher (admin) |
PUT | /api/admin/vouchers/:id | Update voucher (admin) |
DELETE | /api/admin/vouchers/:id | Delete voucher (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/reviews/:classId | Get reviews by class |
POST | /api/reviews/:id | Submit review from booking |
Method | Endpoint | Description |
---|---|---|
GET | /api/admin/schedule-templates | Get all templates |
PUT | /api/admin/schedule-templates/:id | Update template |
POST | /api/admin/schedule-templates/:id/run | Start cron job |
POST | /api/admin/schedule-templates/:id/stop | Stop cron job |
DELETE | /api/admin/schedule-templates/:id | Delete template |
Method | Endpoint | Description |
---|---|---|
GET | /api/users/me | Get profile (customer/instructor) |
PUT | /api/users/me | Update profile |
PUT | /api/users/me/avatar | Update avatar |
GET | /api/admin/users | Get all users (admin) |
GET | /api/admin/users/:id | Get user detail (admin) |
GET | /api/admin/users/stats | Get user statistics (admin) |
Method | Endpoint | Description |
---|---|---|
GET | /api/user-packages | Get user packages |
GET | /api/user-packages/class/:id | Get packages valid for class |
VITE_API_SERVICES=https://your-api-domain.com/api
VITE_API_KEY=your-api-key
VITE_GOOGLE_CLIENT_ID=your-google-client-id
VITE_STRIPE_PUBLISHABLE_KEY=your-stripe-publishable-key
# ==== MySQL ====
DB_HOST=your-database-host # e.g. localhost or db
DB_PORT=3306
DB_USERNAME=your-database-username # e.g. root
DB_NAME=your-database-name # e.g. fitness_app
DB_PASSWORD=your-database-password
# ==== Cloudinary ====
CLOUDINARY_CLOUD_NAME=your-cloudinary-cloud-name
CLOUDINARY_API_KEY=your-cloudinary-api-key
CLOUDINARY_API_SECRET=your-cloudinary-api-secret
CLOUDINARY_FOLDER_NAME=your-cloudinary-folder-name
# ==== Nodemailer (Email Service) ====
USER_EMAIL=your-email-address
USER_PASSWORD=your-email-app-password # e.g. App Password from Gmail
# ==== Redis ====
REDIS_ADDR=your-redis-host:6379 # e.g. redis:6379 or localhost:6379
REDIS_PASSWORD=your-redis-password # leave blank if not used
# ==== Application Config ====
PORT=5000
API_KEY=your-api-key
JWT_ACCESS_SECRET=your-jwt-access-secret
JWT_REFRESH_SECRET=your-jwt-refresh-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# ==== Stripe ====
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret
STRIPE_PUBLIC_KEY=your-stripe-public-key
STRIPE_SECRET_KEY=your-stripe-secret-key
STRIPE_CANCEL_URL_DEV=http://localhost:5173/packages
STRIPE_SUCCESS_URL_DEV=http://localhost:5173/profile/transactions
STRIPE_CANCEL_URL_PROD=https://yourdomain.com/packages
STRIPE_SUCCESS_URL_PROD=https://yourdomain.com/profile/transactions
PAYMENT_TAX_RATE=0.10
# ==== Deployment (Optional) ====
# NODE_ENV=production
# TRUSTED_PROXIES=your-vps-ip
# COOKIE_DOMAIN=https://yourdomain.com
# ALLOWED_ORIGINS=https://yourdomain.com
# FRONTEND_REDIRECT_URL=https://yourdomain.com
# GOOGLE_REDIRECT_URL=https://your-api.yourdomain.com/api/auth/google/callback
For this project, the backend is deployed on a VPS using Docker and Nginx, while the frontend is deployed on a shared web hosting platform (e.g., Hostinger). This setup is cost-effective and scalable for small to medium projects.
-
Provision a VPS (e.g., Ubuntu-based)
-
Install Docker and Docker Compose
-
Clone the repository into your VPS
-
Configure .env file with your production credentials
-
Run the app with Docker Compose:
docker-compose up -d --build
-
Use Nginx as a reverse proxy and configure SSL with Certbot
-
Access your API via a custom domain (e.g., https://api.yourdomain.com)
-
Alternatively, the frontend is deployed on a web hosting platform. You can also use SaaS platforms like Vercel or Netlify. Here's how to deploy it:
-
Connect your Git repository
-
Add your .env variables to the hosting dashboard
-
Set the build command:
npm run build
- Set the output directory to: dist
-
Contributions are welcome! If you'd like to improve or extend this project:
-
Fork this repository
-
Create a new branch:
git checkout -b your-feature-branch
- Commit your changes:
git commit -m "feat: add new feature"
- Push to your branch:
git push origin your-feature-branch
- Open a Pull Request
This project is licensed under the MIT License. Feel free to use, modify, and distribute it for personal or commercial purposes.
MIT License
- π€ name : Ahmad Fiqri oemmry
- π email : fiqrioemry@gmail.com
- π Linkedin : https://www.linkedin.com/in/ahmadfiqrioemry
- πΌοΈ Live Preview : https://sweatup.ahmadfiqrioemry.com