Full-stack barbershop management system — online booking, barber schedules, commission tracking, and inventory in one platform.
Public landing page
![]() Step 1 — Service & barber |
![]() Step 2 — Date & time |
![]() Step 3 — Your details |
Booking confirmation with reschedule option
Admin dashboard — real-time metrics
![]() Appointment management |
![]() Payments & commissions |
Inventory management with low-stock alerts
Barber panel — daily schedule
![]() OpenAPI documentation — auth, admin & scheduling endpoints |
![]() OpenAPI documentation — payments, inventory & public endpoints |
| Role | Login URL | Password | |
|---|---|---|---|
| Admin | https://barberos-os.vercel.app/admin/login | admin@barberos.com | demo1234 |
| Barber | https://barberos-os.vercel.app/barbero/login | carlos@barberos.com | demo1234 |
| Client | https://barberos-os.vercel.app/reservar | No account required | — |
Seed data includes 3 barbers, 5 services, 8 appointments across all statuses, and 6 inventory items.
- 🗓️ 3-step public booking — no account required, clients book in under 2 minutes
- 👥 Three-role system — Admin, Barber, and Client with fully isolated dashboards and auth flows
- 💰 Automated commission split — 40% barber / 60% shop, with bi-weekly earnings reports per barber
- 📧 Automated email reminders — APScheduler sends reminders at 24h and 2h before each appointment via Resend
- 📅 Client rescheduling — clients reschedule directly from their confirmation email link, no account needed
- 📦 Inventory management — stock tracking with configurable minimum thresholds and low-stock alerts
- 🔐 JWT auth with refresh tokens — separate OAuth2 flows for Admin and Barber roles, bcrypt password hashing
- 📊 Real-time admin dashboard — daily appointments, monthly revenue, pending count, and per-barber commission breakdown
- 🐳 Docker ready — full local environment with docker-compose in one command, includes PostgreSQL and nginx
- ✅ 37 passing tests — pytest suite covering auth flows, booking validation, role-based access, Pydantic schemas and commission calculations
- 📖 OpenAPI documentation — 25+ documented endpoints at /docs with request/response schemas
| Technology | Version | Role |
|---|---|---|
| Python | 3.12 | Language |
| FastAPI | 0.135 | HTTP framework / REST API |
| SQLAlchemy | 2.0 | Async ORM |
| PostgreSQL | 15 | Relational database |
| Alembic | — | Schema migrations |
| Pydantic | v2 | Schema validation |
| python-jose | — | JWT authentication (HS256) |
| passlib / bcrypt | — | Password hashing |
| APScheduler | — | Email reminder jobs |
| Resend | — | Transactional email delivery |
| Docker | — | Containerization |
| pytest | — | Testing (37 passing tests) |
| Technology | Version | Role |
|---|---|---|
| React | 19 | UI library |
| TypeScript | 5.9 | Strict typing |
| Vite | 8 | Bundler / dev server |
| Tailwind CSS | v4 | Styling (Vite plugin) |
| react-router-dom | v7 | SPA routing |
| TanStack Query | v5 | Server state / API cache |
| Zustand | v5 | Auth session state |
| axios | — | HTTP client with JWT interceptor |
| react-hook-form | v7 | Form management |
- Async SQLAlchemy 2.0 + asyncpg — non-blocking DB operations handle concurrent booking requests without thread overhead
- Pydantic v2 schemas — 2x faster validation vs v1; strict typing enforced across all API boundaries with zero
Anytypes - TanStack Query v5 — server state per role with automatic cache invalidation; no redundant API calls across dashboards
- APScheduler in-process — reminder jobs run inside uvicorn without Redis or Celery; ±15 min tolerance windows prevent duplicate sends
- UUID type safety — JWT
subfield explicitly cast touuid.UUIDbefore DB queries, preventing silent driver-level type coercion failures
barberos/ ├── backend/ │ ├── app/ │ │ ├── api/ │ │ │ └── routes/ # One router per domain (auth, admin, citas, horarios, pagos, inventario, public) │ │ ├── core/ │ │ │ ├── config.py # Environment variables via pydantic-settings │ │ │ └── security.py # JWT creation/verification + bcrypt hashing │ │ ├── db/ │ │ │ ├── database.py # Async engine + get_db dependency │ │ │ └── models/ # 12 SQLAlchemy models (one file per entity) │ │ ├── schemas/ # Pydantic v2 request/response schemas per domain │ │ ├── services/ # Business logic decoupled from HTTP layer │ │ └── main.py # FastAPI app, CORS middleware, router registration │ ├── alembic/ # Schema migration history │ ├── scripts/ │ │ └── seed.py # Demo data seeder (barbers, services, appointments) │ ├── tests/ │ │ ├── conftest.py # AsyncClient fixture with in-memory SQLite DB │ │ ├── test_auth.py # 6 HTTP tests — login flows and protected routes │ │ ├── test_citas.py # 5 HTTP tests — booking creation and validation │ │ ├── test_schemas.py # 11 unit tests — Pydantic schema validation │ │ ├── test_cita_service.py # Business rules — booking constraints and cancellation │ │ ├── test_pago_service.py # Commission calculations and payment rules │ │ └── test_security.py # JWT generation, hashing and token validation │ ├── .env.example │ └── requirements.txt │ └── frontend/ └── src/ ├── api/ # Axios instance + per-domain request functions ├── components/ # Shared components (layouts, route guards, UI) ├── pages/ │ ├── admin/ # AdminDashboard, AdminBarberos, AdminServicios, │ │ # AdminCitas, AdminHorarios, AdminPagos, AdminInventario │ ├── barbero/ # BarberoAgenda, BarberoGanancias, BarberoInventario │ └── public/ # HomePage, ReservarPage, CitaPage (3-step booking flow) ├── store/ # Zustand stores (authStore per role) ├── types/ # TypeScript interfaces mirroring backend schemas └── utils/ # Date/time helpers (Bogotá timezone)
git clone https://github.com/dacq7/barberos-os.git
cd barberos-os
cp .env.example .env # configure SECRET_KEY and RESEND_API_KEY
docker compose up --build -d
docker compose exec backend alembic upgrade head
docker compose exec backend python3 scripts/seed.py
# Frontend: http://localhost:3000
# Backend API: http://localhost:8000
# API Docs: http://localhost:8000/docsBackend:
cd backend
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # configure your variables
alembic upgrade head
python3 scripts/seed.py
uvicorn app.main:app --reload
# API available at http://localhost:8000Frontend:
cd frontend
npm install
npm run dev
# App available at http://localhost:5173| Variable | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL async connection string | postgresql+asyncpg://user:pass@localhost:5432/barberos_db |
SECRET_KEY |
JWT signing secret (use a strong random string) | your-secret-key-here |
ALGORITHM |
JWT algorithm | HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES |
Access token TTL in minutes | 30 |
REFRESH_TOKEN_EXPIRE_DAYS |
Refresh token TTL in days | 7 |
RESEND_API_KEY |
Resend API key for transactional emails | re_your_key_here |
ALLOWED_ORIGINS_STR |
Comma-separated list of allowed CORS origins | https://your-frontend.vercel.app |
BASE_URL |
Frontend base URL (used in email links) | https://your-frontend.vercel.app |
12 entities: admins · barberos · servicios · barbero_servicios · horarios · barbero_bloqueos · bloqueos_generales · clientes · citas · pagos · inventario · inventario_alertas
Key business rules:
- Minimum booking: 30 minutes in advance — maximum: 1 month ahead
- Client cancellation deadline: 1 hour before appointment
- Client rescheduling deadline: 30 minutes before appointment
- Commission split: 40% barber / 60% barbershop per completed service
- Email reminders: dispatched at 24h and 2h windows with ±15 min polling tolerance to prevent duplicates
- Appointment statuses:
pending→confirmed→completed/cancelled/no_show
cd backend
source venv/bin/activate
pytest tests/ -vExpected output: tests/test_auth.py::test_login_barbero_valido PASSED tests/test_auth.py::test_login_password_incorrecta PASSED tests/test_auth.py::test_login_usuario_inexistente PASSED tests/test_auth.py::test_login_admin_valido PASSED tests/test_auth.py::test_ruta_protegida_con_token PASSED tests/test_auth.py::test_ruta_protegida_sin_token PASSED tests/test_citas.py::test_crear_cita_datos_completos PASSED tests/test_citas.py::test_crear_cita_datos_incompletos PASSED tests/test_citas.py::test_listar_citas_admin PASSED tests/test_citas.py::test_crear_cita_fecha_invalida PASSED tests/test_citas.py::test_crear_cita_sin_horario PASSED tests/test_schemas.py::test_login_schema_email_valido PASSED tests/test_schemas.py::test_login_schema_email_invalido PASSED tests/test_schemas.py::test_cita_schema_completo PASSED tests/test_schemas.py::test_cita_schema_sin_campos_requeridos PASSED tests/test_schemas.py::test_barbero_schema_valido PASSED tests/test_schemas.py::test_barbero_schema_email_invalido PASSED tests/test_schemas.py::test_horario_schema_valido PASSED tests/test_schemas.py::test_inventario_schema_stock_negativo PASSED tests/test_schemas.py::test_pago_schema_valido PASSED tests/test_schemas.py::test_servicio_schema_precio_negativo PASSED tests/test_cita_service.py::test_crear_cita_falla_fecha_menos_30_min PASSED tests/test_cita_service.py::test_crear_cita_falla_slot_no_disponible PASSED tests/test_cita_service.py::test_cancelar_cita_cambia_estado PASSED tests/test_cita_service.py::test_cancelar_cita_falla_si_ya_cancelada PASSED tests/test_cita_service.py::test_cancelar_cita_falla_menos_de_1_hora PASSED tests/test_cita_service.py::test_cambiar_estado_cita_actualiza_correctamente PASSED tests/test_pago_service.py::test_registrar_pago_calcula_comisiones_correctamente PASSED tests/test_pago_service.py::test_registrar_pago_falla_si_cita_no_completada PASSED tests/test_pago_service.py::test_registrar_pago_falla_si_ya_existe_pago PASSED tests/test_pago_service.py::test_get_resumen_barbero_calcula_total_correcto PASSED tests/test_security.py::test_hash_password_difiere_del_texto_plano PASSED tests/test_security.py::test_verify_password_correcto PASSED tests/test_security.py::test_verify_password_incorrecto PASSED tests/test_security.py::test_create_access_token_genera_jwt_valido PASSED tests/test_security.py::test_create_refresh_token_incluye_type_refresh PASSED 37 passed in 3.75s
Diego Alejandro Correa — Full-Stack Developer · Founder of Veridis Dev
Medellín, Colombia 🇨🇴
- GitHub: @dacq7
- LinkedIn: Diego Alejandro Correa
- Email: team@veridisdev.com
- Web: veridisdev.com
Built with FastAPI + React · Deployed on Railway & Vercel · © 2025 Veridis Dev











