Skip to main content
Spring Boot

Booking app for hair salons

For owners of small hair salons

A complete web app for hair salons with online booking, calendar, staff and admin. Built with Spring Boot and React. Try the live demo.

  • Booking from mobile and desktop
  • Services with price and duration
  • Choose a hairdresser or first available
  • Double-booking protection
  • Email confirmation
  • Admin for services, staff, absences and bookings
  • Spring Boot, Hibernate and PostgreSQL

If you run a salon, this will sound familiar

Clients message on Instagram, call while you are with another client, or send a text late in the evening. You answer when you can, but appointments quickly end up in several places: your phone calendar, a notebook, a message thread or your head.

When the salon grows a little, this becomes hard to manage. You need to keep track of services, prices, staff, absences and available times, while clients expect booking to be simple.

Nordic Cuts shows how this can be solved with a dedicated web app built for a small hair salon.

What Nordic Cuts is

Nordic Cuts is a complete web app for hairdressers and salons. Clients choose a service, hairdresser, date and time directly in the browser, on mobile or desktop, and see price and duration before they submit the booking.

Behind the public page there is an admin area where the salon manages services, hairdressers, absences and bookings. It is built with Java, Spring Boot, React and PostgreSQL. It is a real application, not a contact page with a form.

Nordic Cuts in the new design: the home page and booking flow scrolling past automatically

For your clients

The client chooses a service and sees which hairdressers perform it. If the client has no favourite, they pick “Hvem som helst” (anyone), and the system finds the first available hairdresser.

Then the client picks a date and a free time, enters name, phone and email, and accepts the privacy terms. The booking is stored in the same database the admin area uses.

For you as the salon owner

You see what is booked, who will do the work and which services the salon offers. Hairdressers are linked to the services they perform, absences are registered, and every booking has a status: pending, confirmed, cancelled or completed.

The solution can email a confirmation to the client, send an email when the status changes, and notify the salon about new bookings. You pay no commission per booking, and the client data stays in the salon's own database.

What the solution includes

  • A public landing page for the salon, in a dark, modern design.
  • Online booking in four steps: service, hairdresser, time and contact details.
  • “Hvem som helst” (anyone): the system picks the first available hairdresser who performs the service.
  • Double-booking protection, enforced in the backend.
  • Services with price, duration and description.
  • Hairdressers with photo, status and the services they perform.
  • Staff absence registration.
  • Bookings with status: pending, confirmed, cancelled and completed.
  • Email confirmation to the client and notifications to the salon.
  • Privacy (GDPR) consent in the booking form.
  • Login with administrator and user roles.

Who this fits

The solution fits hairdressers, barbers and small salons that want to own their booking flow. It also fits other appointment-based businesses where clients choose a person, a service and a time.

If you handle a lot manually today, a solution like this can save you time and make booking easier for your clients.

How we work

This is not a standard template where everyone gets exactly the same solution. We use the demo as a starting point and adapt it to your salon: services, prices, staff, languages, design and workflow.

There is a setup cost for development and configuration, followed by maintenance and hosting agreed up front. You know what is included before we start.

The technology behind Nordic Cuts

This part is for the curious, or for the developer you might ask for advice. In short: one Spring Boot application that serves both the API and the React app, with PostgreSQL as the database.

LayerTechnologyWhat it does
BackendJava 21, Spring Boot 4.1, JHipster 9.4REST API, booking rules, email and security
DatabasePostgreSQLStores services, hairdressers, absences and bookings
ORMHibernate 7 with Spring Data JPA and EhcacheMaps Java classes to tables, with caching for frequent reads
Schema changesLiquibaseVersioned changes applied automatically at startup
BuildMaven Wrapper and frontend-maven-pluginBuilds backend and frontend into one executable JAR
FrontendReact 19, TypeScript 5.9, Tailwind CSSPublic site and booking flow, mobile first
AdminReact, Redux Toolkit, Bootstrap 5Services, hairdressers, absences, bookings and users
SecuritySpring Security with JWTLogin and roles for administrator and user
HostingDocker on Railway (EU)Health check, automatic deploys from main and restart on failure
QualityGitHub Actions, JUnit, Jest, Cypress, TestcontainersEvery change is tested before it reaches production

Backend: Java 21 and Spring Boot 4.1

The foundation was generated with JHipster 9.4 and then adapted and extended for a salon. The code is layered: REST resources receive requests, service classes hold the business rules, and repositories talk to the database. DTOs are mapped with MapStruct, and all input is validated with Bean Validation before anything is saved.

The booking rules live in the backend, not only in the browser. Before a booking is saved, the system checks that the hairdresser has no other booking that overlaps in time. Cancelled appointments do not count. When the client picks “Hvem som helst”, the backend finds an active hairdresser who performs the service and is free at that time. The calendar fetches occupied times from a dedicated endpoint and shows them as unavailable.

Emails are sent with Spring Mail and Thymeleaf templates: a confirmation to the client, a message when the status changes, and a notification to the salon.

Database: PostgreSQL, Hibernate and Liquibase

Four JPA entities describe the salon: Tjeneste (service), Frisor (hairdresser), Fravaer (absence) and Bestilling (booking). A hairdresser can perform many services (many-to-many), a booking points to one service and one hairdresser, and an absence belongs to one hairdresser. Hibernate 7 maps between the Java objects and the PostgreSQL tables, and Ehcache serves as a second-level cache for data that is read often.

The database schema is never changed by hand. Every change is a versioned Liquibase changelog in Git, applied automatically when the app starts. Locally we use H2, the tests run against a real PostgreSQL in Docker through Testcontainers, and production uses PostgreSQL on Railway.

Security and API

The admin area is protected with Spring Security and JWT tokens, with separate administrator and user roles. Without logging in, you can only do what a client needs: read services and active hairdressers, see occupied times and submit a booking. Everything else requires login, and the admin API requires the administrator role.

The API is documented with OpenAPI (springdoc). Spring Boot Actuator provides a health check and Prometheus-format metrics, so you can always see that the app is alive.

Frontend: React 19 and TypeScript

The frontend is written in TypeScript with React 19, React Router 7 and Redux Toolkit, and bundled with Webpack 5. Forms use react-hook-form with per-field validation, API calls go through Axios, and dates are handled with Day.js.

The public part is styled with Tailwind CSS in its own dark “amber glass” design: glass panels, warm light spots, film grain and soft animations. The animations switch off when the user has chosen reduced motion in the operating system. The admin area uses Bootstrap 5.

Maven builds everything into one file

One Maven command builds the whole solution. The Maven Wrapper pins the Maven version, and frontend-maven-plugin installs Node 24 and builds the React app as part of the Maven build. The result is one executable JAR with both backend and frontend.

The Dockerfile builds in two stages. A JDK image compiles and packages the app, and the final image contains only the Java 21 runtime and the JAR. That means a smaller image with fewer things that can break.

Tests and CI

Every pull request goes through GitHub Actions before it is merged: ESLint, TypeScript checks, Jest tests, a production build of the frontend, Java formatting checks with Prettier and Spotless, and finally Maven verify with unit tests and integration tests against PostgreSQL. The whole run takes about five minutes.

In total there are more than 500 automated tests: 318 in Java and 219 in the frontend. There are also end-to-end tests in Cypress and architecture tests in ArchUnit that keep the layering honest.

Hosting on Railway

The app runs as a Docker container on Railway in the EU, with PostgreSQL as a separate service. When main changes, Railway builds a new image and only sends traffic to it once /management/health answers. If the app crashes, it restarts automatically, and an earlier version can be rolled back.

The workflow is the same for every change: its own branch, a pull request, green CI, a merge into develop and then a release to main, which deploys automatically.

“Can't this be built in five minutes with vibe coding?”

Sure. You type “make a booking app for a hair salon”, press Enter, and five minutes later you have something that looks like a booking app. Then Saturday morning arrives: two clients are at the door with the same appointment, nobody knows where the bookings were saved, and the app only works on the developer's own laptop.

Nordic Cuts took a little more than five minutes: 88 commits, 39 pull requests and more than 500 automated tests since January 2026. The only thing that actually takes five minutes is the CI run. We use AI every day too, and it saves us a lot of hours, but it is the backend rules, the tests and the operations that keep booking working when the salon is fully booked on a Saturday.

Try the demo and get in touch

The demo is open. Test the booking flow and see how it feels for a client. If you have questions, we can talk through what would fit your salon.

Wondering whether your own app pays off for your salon? Read our guide Hair salon booking system: your own app or a ready-made solution?.