TOE Visitor Management System is a full-stack visitor check-in/check-out web app for factory reception workflows.
Visitors scan a QR code, fill in the registration form, check in, and later scan a separate check-out QR code to find their active visit by phone number. Admin users can monitor live visitors, review history, export Excel reports, manage timeout settings, view audit logs, and generate printable visitor check-in/check-out QR codes.
- Visitor registration at
/ - QR-code based visitor entry
- Visitor check-in with server-side timestamps
- Visitor status page at
/visitor/status - Visitor check-out by phone-number active visit search
- Secure HttpOnly visitor session cookies
- Admin login at
/login - Protected admin control center at
/admin - Dashboard metrics and current visitor monitoring
- Visitor history with search, filters, sorting, pagination, detail view, and delete action
- Excel export for visitor records
- Persisted visitor timeout settings
- Audit log view
- Deployment-aware printable QR code generation
| Layer | Technology |
|---|---|
| Framework | Next.js 16 App Router |
| Language | TypeScript |
| UI | Tailwind CSS v4, shadcn/ui, Lucide icons |
| Database | PostgreSQL |
| ORM | Prisma 7 |
| Auth | Better Auth |
| Reports | ExcelJS |
| QR Code | qrcode |
| Local database | Docker Compose |
- Node.js 20 or newer
- npm
- Docker Desktop or Docker Engine
- Git
For production VPS deployment with a domain, see VPS_DEPLOYMENT_GUIDE.md.
For VPS deployment using only an IP address, see VPS_DEPLOYMENT_GUIDE_IP_ADDRESS.md.
Create .env from .env.example:
cp .env.example .envLocal defaults:
DATABASE_URL="postgresql://visitor_system:visitor_system_password@localhost:5433/visitor_system?schema=public"
BETTER_AUTH_SECRET="replace-with-a-secure-random-secret"
BETTER_AUTH_URL="http://localhost:3000"
ADMIN_SEED_NAME="System Administrator"
ADMIN_SEED_EMAIL="admin@example.com"
ADMIN_SEED_PASSWORD="replace-with-a-secure-admin-password"Important notes:
DATABASE_URLmust match your PostgreSQL host, port, database, username, and password.BETTER_AUTH_SECRETmust be a long random secret.BETTER_AUTH_URLmust match the public app URL in production.ADMIN_SEED_EMAILandADMIN_SEED_PASSWORDcreate the first admin login.
Install dependencies:
npm installStart PostgreSQL:
docker compose up -d postgresValidate Prisma and generate Prisma Client:
npm run db:validate
npm run db:generateApply database migrations:
npx prisma migrate devSeed the first admin user:
npm run auth:seed-adminStart the development server:
npm run devOpen:
- Visitor registration:
http://localhost:3000/ - Admin login:
http://localhost:3000/login - Admin dashboard:
http://localhost:3000/admin
| Script | Purpose |
|---|---|
npm run dev |
Start local development server |
npm run build |
Build production app |
npm run start |
Start production server after build |
npm run lint |
Run ESLint |
npm run db:validate |
Validate Prisma schema |
npm run db:generate |
Generate Prisma Client |
npm run db:migrate |
Run Prisma development migration |
npm run db:studio |
Open Prisma Studio |
npm run auth:seed-admin |
Create first admin auth user |
The local Docker Compose database uses:
- Image:
postgres:16-alpine - Database:
visitor_system - User:
visitor_system - Local host port:
5433 - Container port:
5432 - Volume:
visitor_system_postgres_data
Current Prisma models include:
VisitorVisitorSessionAdmin- Better Auth tables:
Users,Sessions,Accounts,Verifications SystemSettingAuditLog
- Visitor scans the generated QR code.
- Visitor opens
/. - Visitor fills in:
- Full name
- IC/passport number
- Phone number
- Vehicle/no-vehicle selection
- Vehicle plate number when applicable
- Company name
- Purpose of visit
- Person to meet/PIC
- System creates the visitor record and secure visitor session.
- Visitor is redirected to
/visitor/status. - Visitor scans the check-out QR code before leaving, enters the phone number used at check-in, confirms the unique active visit, and checks out.
- Admin opens
/login. - Admin signs in with the seeded admin account.
- Admin opens
/admin. - Admin can:
- View dashboard metrics
- See current visitors
- Search/filter/sort visitor history
- Export Excel reports
- Update timeout settings
- Generate and print the visitor registration QR code
- Review audit logs
The admin Settings tab generates a visitor registration QR code from the browser's current deployment origin.
Example:
- Local:
http://localhost:3000/ - Production:
https://your-domain.com/ - IP deployment:
http://your-server-ip/
This means the QR code automatically points to the correct registration page after deployment, without hardcoding the domain in code.
app/ Next.js app routes, pages, and route handlers
components/ui/ Generated shadcn/ui components
context/ Project planning and implementation context
lib/ Shared app utilities, auth, and Prisma client
prisma/ Prisma schema and migrations
repositories/ Database access layer
scripts/ Operational scripts such as admin seeding
services/ Business logic layer
types/ Shared TypeScript types
public/ Public assets
Run these before handing off or deploying:
npm run db:validate
npm run db:generate
npm run lint
npm run buildFor a local end-to-end smoke test:
- Start Docker PostgreSQL.
- Start the dev server.
- Register a visitor at
/. - Confirm visitor status page loads.
- Check out the visitor.
- Log in as admin.
- Confirm dashboard, visitors, export, settings, QR generation, and audit logs work.
Use the step-by-step VPS guide:
If you are deploying with only a server IP address: