A full-stack web application for managing 3D print jobs, featuring user authentication, print submission, administrative review, and file storage.
- Project Overview
- Architecture
- Directory Structure
- Environment Variables
- Backend Setup
- Frontend Setup
- API Overview
- Authentication Flow
- Print Submission Flow
- Admin Features
- Email Whitelist Feature
- Development & Contribution
- License
spooler is a platform for submitting, tracking, and managing 3D print jobs. It supports:
- User registration and login via email and OTP (One-Time Passcode)
- Print job submission with STL/3MF file upload and color selection
- Real-time preview of STL files and 3MF thumbnails
- Admin dashboard for reviewing, approving, denying, and managing print jobs
- File storage using Google Cloud Storage
- Role-based access control (user, admin, officer)
- Optional email whitelist for restricting registration and OTP requests
- Frontend: React + TypeScript, Vite, TailwindCSS
- Backend: Go (Gin), GORM (Postgres), Google Cloud Storage
- Database: PostgreSQL (Supabase)
- File Storage: Google Cloud Storage
- Authentication: JWT (stored in HTTP-only cookies), OTP via email
.
├── backend/
│ ├── cmd/server/ # Main server entrypoint and route setup
│ ├── config/ # Configuration loading
│ ├── internal/
│ │ ├── handlers/ # HTTP handlers (auth, prints, otp)
│ │ ├── middleware/ # Gin middleware (auth, role, whitelist)
│ │ ├── models/ # GORM models (User, Print, OTP, EmailWhitelist)
│ │ ├── services/ # Business logic (user, print, otp, bucket, whitelist)
│ │ └── util/ # Utilities (email, jwt, metadata)
│ ├── docs/ # API documentation (Swagger, Markdown)
│ ├── go.mod, go.sum # Go dependencies
│ └── .env, .env.example # Backend environment variables
├── ui/
│ ├── src/
│ │ ├── components/ # React components (Dashboard, Login, Register, etc.)
│ │ ├── context/ # React context (auth)
│ │ ├── types/ # TypeScript types (Print, PrintStatus)
│ │ ├── util/ # API utilities (auth, prints)
│ │ └── assets/ # Static assets (logo, etc.)
│ ├── public/ # Static files
│ ├── index.html # HTML entrypoint
│ ├── package.json # Frontend dependencies and scripts
│ ├── vite.config.ts # Vite configuration
│ ├── tailwind.config.js # TailwindCSS configuration
│ └── .env, .env.example # Frontend environment variables
├── .gitignore
└── README.md
| Variable | Description |
|---|---|
| PORT | Port for backend server |
| SMTP_EMAIL | Email address for sending OTPs |
| SMTP_PASSWORD | SMTP password |
| SMTP_HOST | SMTP server host |
| SMTP_PORT | SMTP server port |
| SUPABASE_HOST | PostgreSQL host |
| SUPABASE_PORT | PostgreSQL port |
| SUPABASE_USER | PostgreSQL user |
| SUPABASE_PASSWORD | PostgreSQL password |
| SUPABASE_DB | PostgreSQL database name |
| SECRET_KEY | JWT secret key |
| GCLOUD_PRINT_FILES_BUCKET | Google Cloud Storage bucket for print files |
| EMAIL_WHITELIST_ENABLED | Boolean to enable/disable email whitelist |
| ADMIN_EMAIL | Admin user email (created on startup) |
| ADMIN_FIRST_NAME | Admin user's first name |
| ADMIN_LAST_NAME | Admin user's last name |
| CORS_ALLOW_ORIGINS | Comma seperated list of allowed client urls |
| Variable | Description |
|---|---|
| VITE_SERVER_URL | Backend API base URL (e.g. http://localhost:8080) |
-
Install Go dependencies:
cd backend go mod tidy -
Configure environment:
- Copy
.env.exampleto.envand fill in all required values. - To enable the email whitelist feature, set
EMAIL_WHITELIST_ENABLED="true".
- Copy
-
Run the server:
go run cmd/server/main.go
The server will start on the port specified in your
.env.
-
Install Node dependencies:
cd ui npm install -
Configure environment:
- Copy
.env.exampleto.envand setVITE_SERVER_URLto your backend URL.
- Copy
-
Start the development server:
npm run dev
The app will be available at http://localhost:5173 by default.
POST /register— Register a new userPOST /otp/request— Request OTP for login/registrationPOST /otp/verify— Verify OTP and receive JWT (set as cookie)GET /me— Get current authenticated user info
POST /prints/new— Submit a new print job (authenticated)GET /me/prints— List user's print jobs (authenticated)POST /preview— Get STL/3MF file preview/thumbnailGET /bucket/:filename— Download print file
GET /prints/all— List all print jobs (admin only)PUT /prints/:id— Update print (admin only)DELETE /prints/:id— Delete print and file (admin only)GET /whitelist— List all whitelisted emails (admin only)POST /whitelist— Add email to whitelist (admin only)DELETE /whitelist— Remove email from whitelist (admin only)
-
Register:
User submits email, first name, last name → receives OTP via email. -
OTP Verification:
User enters OTP → backend verifies and issues JWT (stored in HTTP-only cookie). -
Login:
User requests OTP with email, enters OTP, receives JWT cookie. -
Session:
JWT is sent with each request via cookie for authentication.
-
User uploads STL/3MF file
.stl,.3mf: Generates a 3D preview (base64-encoded).
-
User selects filament color (if .stl file)
- Color is stored with the print job.
-
Submission
- File is uploaded to storage provider.
- Print job is created in the database.
- View all print jobs
- Approve, deny (with reason), or update status of any print
- Batch update or delete print jobs
- Download any print file
- Manage email whitelist (add, remove, list whitelisted emails)
npm run lintnpm run build- Backend: Go packages are organized by domain (handlers, services, models, util).
- Frontend: React components are colocated by feature. Types and API utilities are in
src/typesandsrc/util.
MIT. See LICENSE for more information.
For questions, contact northalltsa@gmail.com