WallpaperMachine
The wallpapers you love. A new home on your Mac.
Vig Barber é a plataforma de agendamento online para barbearias. Encontre uma barbearia, escolha o serviço e o profissional e reserve seu horário.
Translation pending
LifestyleTypeScript · CSSGitHub @Gabriel-VignoliOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
A booking platform for barbershops — browse services, schedule appointments, and manage bookings. Built with Next.js 16, React 19, Prisma ORM, and PostgreSQL (Supabase).
Taken from the repository README
Loading the full README.
Read the full README ↗A multi-tenant SaaS for barbershops, built with Next.js, TypeScript, Prisma and PostgreSQL. Many shops run on one deployment, each at its own URL (/b/<slug>) with its own data, branding and staff. Clients have one global account: they find a shop on the landing page and book a service with a specific barber. Staff work in role-specific areas of their shop, and shops pay a monthly subscription through Stripe.
Live: vig-barber.vercel.app (billing runs in Stripe test mode, so use the test card 4242 4242 4242 4242)
For clients
For shop staff (roles come from a membership in each shop, so one person can be an admin in one shop and a client in another)
/painel ("Minhas barbearias") lists every shop a person works atFor the platform
/platform) to create, suspend and reactivate shops, invite owners, see each shop's billing status and extend trialsBilling
pg driver adapterslug (or from a row the user already owns, like their booking). A barbershopId sent by the browser is never trusted.barbershopId. Updates and deletes filter by both the record id and the shop id, then check that a row was actually changed.Membership per user and shop, and are read from the database on every request. Platform admins get no implicit access to shops.The full design and the migration from a single-shop app are in docs/multi-tenant-plan.md; billing is in docs/billing-plan.md.
git clone https://github.com/Gabriel-Vignoli/vig-barber.git
cd vig-barber
# Also generates the Prisma client into app/generated/prisma
npm install
cp .env.example .env
Fill in .env. Only the database and NextAuth variables are required to start; the other services turn themselves off while their keys are missing.
| Variable | What it is for |
|---|---|
DATABASE_URL | Transaction pooler (port 6543), used by the app |
DIRECT_URL | Session pooler (port 5432), used by the Prisma CLI |
NEXT_AUTH_SECRET | NextAuth session secret |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | Google login |
RESEND_API_KEY, EMAIL_FROM | Password reset and invitation emails |
APP_URL | Absolute origin for links in emails (custom domain) |
UPLOADTHING_TOKEN | Shop logo and banner uploads |
CONTACT_EMAIL, CONTACT_WHATSAPP | Contact buttons on the landing page (hidden when unset) |
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_BASIC | Subscriptions and the webhook |
# Apply migrations and seed 3 demo shops
npx prisma migrate dev
npx prisma db seed
npm run dev
Open http://localhost:3000. The demo users (a platform admin, shop owners, barbers, a front-desk user and clients) are listed in prisma/seed.ts. You choose their logins in .env: SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD for the platform admin, SEED_PASSWORD for everyone else. A password left empty is generated at random and printed at the end of the seed.
Warning: the seed deletes every row in the database before it inserts the demo data. Never run it against a database with real shops.
To test billing locally, forward Stripe events to the webhook and put the secret it prints in STRIPE_WEBHOOK_SECRET:
stripe listen --forward-to localhost:3000/api/stripe/webhook --events checkout.session.completed,customer.subscription.created,customer.subscription.updated,customer.subscription.deleted,invoice.paid,invoice.payment_failed
Prisma 7:
migrate devno longer runsprisma generateor the seed. After you changeprisma/schema.prisma, runnpx prisma generateyourself. The CLI reads its settings fromprisma.config.ts.Connection errors? Some networks (school or corporate wifi) block port 6543. If you get P1017 (
Server has closed the connection) locally, try another network or point your localDATABASE_URLat the 5432 URL.
npm run test
The suite (400+ tests) runs against a throwaway PostgreSQL started by embedded-postgres, with the real migrations applied, so it needs no Docker and never touches your .env database. It covers cross-shop isolation for every mutation, booking rules and availability, reviews, invitations, plan limits, the billing gate and the Stripe webhook sync.
Before pushing: npm run lint, npm run build and npm run test.
vig-barber/
├── app/
│ ├── (landing)/ # Platform landing page and shop finder at /
│ ├── b/[slug]/ # One shop
│ │ ├── (client)/ # Shop home, service and barber pages
│ │ ├── admin/ # Admin panel (dashboard, services, staff, expenses, billing...)
│ │ ├── atendente/ # Front-desk walk-in screen and bookings
│ │ ├── staff/ # Barber's own bookings
│ │ └── assinatura-pendente/ # Shown to staff while the shop is unpaid
│ ├── platform/ # Super admin panel
│ ├── painel/ # "Minhas barbearias"
│ ├── convite/[token]/ # Accept an invitation
│ ├── login/ bookings/ profile/
│ ├── api/ # NextAuth, UploadThing and the Stripe webhook
│ ├── _actions/ # Server Actions, one per file
│ ├── _data/ # Server-only data fetchers used by pages
│ ├── _lib/ # Tenant helpers, auth, billing, Stripe, time logic, validations
│ └── components/ # Feature components (ui/ holds the shadcn primitives)
├── prisma/ # Schema, migrations and seed
├── tests/ # Vitest suite
├── docs/ # Multi-tenant and billing plans
├── prisma.config.ts # Prisma CLI config
└── proxy.ts # Requires a session on protected routes (roles are checked by pages)
Date math.{ ok, data } or { ok: false, error } instead, so the Portuguese messages reach the user.authorize(), so failed attempts are tracked by a separate Server Action called before sign-in.Decimal serialization: Prisma Decimal values are converted to number before they reach Client Components.Live and in active development. Billing still runs in Stripe test mode while the first shops try the system.