---
title: "LeatherMaster · Case study · Adrian Nita"
description: "Website and a custom CMS for a leather upholstery restoration workshop. Customers book training courses and pay online, and the owner edits the content in the panel."
canonical_url: "https://www.adriannita.pl/en/projects/leathermaster"
meta:
  "og:description": "Website and a custom CMS for a leather upholstery restoration workshop. Customers book training courses and pay online, and the owner edits the content in the panel."
  "og:image": "https://www.adriannita.pl/_og/s/o_111307ebd3d124ff.png"
  "og:image:height": "630"
  "og:image:type": image/png
  "og:image:width": "1200"
  "og:title": "LeatherMaster · Case study · Adrian Nita"
  "twitter:image": "https://www.adriannita.pl/_og/s/o_111307ebd3d124ff.png"
---

> Index of every page on this site: [llms.txt](https://www.adriannita.pl/llms.txt)

[All projects](https://www.adriannita.pl/en#projects)

# **LeatherMaster**

Website and a custom CMS for a leather upholstery restoration workshop. Customers book training courses and pay online, and the owner edits the content in the panel.

<dl>

<dt>Role</dt>
<dd>**Design, backend, frontend, deployment**</dd>

<dt>Year</dt>
<dd>**2026**</dd>

<dt>Stack</dt>
<dd>**Laravel 13, Livewire 4, Tailwind CSS 4, MySQL, GitHub Actions, Cloudflare**</dd></dl>

- **BLIK**

  course payments through ING Pay
- **Passkey**

  panel sign-in, plus 2FA
- **250+**

  tests on every push
- **30 days**

  to restore deleted content

www.leathermaster.pl

![LeatherMaster homepage: hero with the leather restoration offer and a contact button](https://www.adriannita.pl/_ipx/pos_top&f_webp&fit_cover&s_2208x1380/images/projects/leathermaster.webp)

## The brief

A workshop near Poznań needed a website that shows its services and before-and-after makeovers, takes training bookings with online payment, and can be edited without a developer.

## What I did

All of it myself. I talked it through with the owner, designed the site, wrote the Laravel backend, the Blade and Tailwind front end and the Livewire panel, hooked up payments and set up CI/CD.

## Details

### Bookings and payments

One booking can hold several seats, with a name for each participant. The hold has a countdown and expires when it runs out, and once paid the customer gets an `.ics` file for their calendar. Company details fill in by themselves from the tax ID. They come from the Polish VAT registry and I cache them for 24 hours, because the API has a daily request limit.

Payments go through ING Pay, by BLIK or bank transfer. The webhook checks the signature, and a rejected or expired payment can be retried. The sandbox behaves differently from the docs in a few places, so I wrote that down in the README.

### Panel

Deleted items stay in the panel's bin for 30 days and can be restored. Every record has a change history, screens can be found with ⌘K, and on a phone the menu sits in a bottom bar.

![LeatherMaster panel dashboard: upcoming training dates with booked seats and recent bookings with payment status (sample data)](https://www.adriannita.pl/_ipx/w_1344&f_webp/images/projects/leathermaster-panel.webp)

### Security

The panel uses passkey and 2FA sign-in. I sign passkey handles with a separate secret so that rotating `APP_KEY` doesn't invalidate them.

### SEO

The sitemap and structured data are generated automatically. When a page's address changes, the old one redirects to the new one with a 301, and a switched-off site answers with a 503 and a `Retry-After` header.

## The result

The site is live at [leathermaster.pl](https://www.leathermaster.pl). The owner edits the content and adds training dates, and handles bookings in the panel without needing me.

## **A closer look**

- ![LeatherMaster training page: a photo from a class, the next date, price per person and a booking button](https://www.adriannita.pl/_ipx/f_webp&s_1792x1120/images/projects/leathermaster-training.webp)

  *****Training page.**** The next date, the price per person and the format. Customers book from here.*

- ![Three-step training booking form, with a summary of the date and price next to it](https://www.adriannita.pl/_ipx/f_webp&s_1792x1120/images/projects/leathermaster-booking.webp)

  *****Booking a date.**** Three steps, details, payment and confirmation. Company details fill in from the tax ID.*

- ![LeatherMaster panel dashboard: upcoming training dates and recent bookings with payment status (sample data)](https://www.adriannita.pl/_ipx/f_webp&s_1792x1120/images/projects/leathermaster-panel.webp)

  *****Dashboard.**** After signing in, the owner sees the upcoming dates, free seats and whether the latest bookings are paid.*

- ![Calendar of training dates in the panel, with group and one-to-one dates and a visibility switch](https://www.adriannita.pl/_ipx/f_webp&s_1792x1120/images/projects/leathermaster-terms.webp)

  *****Dates and bookings.**** A calendar of group and one-to-one dates. Any date can be hidden from the site with one switch.*

- ![Editing a training in the panel: description editor, image with an adjustable crop and a save button](https://www.adriannita.pl/_ipx/f_webp&s_1792x1120/images/projects/leathermaster-editor.webp)

  *****Editing a training.**** The description in an editor, an image with an adjustable crop, and ⌘S to save.*

- ### **Bookings and payments**

  Seat booking for training courses and BLIK payments through ING Pay, with verified webhooks and payment retries.
- ### **Livewire 4 panel**

  Navigation without reloads, a ⌘K screen search, change history and a restorable bin.
- ### **Security**

  Passkey and 2FA sign-in, a Content Security Policy, rate-limited forms and Turnstile.
- ### **CI/CD**

  Tests and static analysis on every push, deploys versioned with CalVer and checked by a smoke test.

## **Got a similar project?**

Tell me in a few sentences what you want to build.

[**Talk about your project**](https://www.adriannita.pl/en#contact) [**Visit LeatherMaster **(opens in a new tab)](https://www.leathermaster.pl)

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://www.adriannita.pl/en#website","@type":"WebSite","inLanguage":"en-US","name":"Adrian Nita","url":"https://www.adriannita.pl/en","publisher":{"@id":"https://www.adriannita.pl/#identity"},"translationOfWork":{"@id":"https://www.adriannita.pl/#website"}},{"@id":"https://www.adriannita.pl/en/projects/leathermaster#webpage","@type":"WebPage","description":"Website and a custom CMS for a leather upholstery restoration workshop. Customers book training courses and pay online, and the owner edits the content in the panel.","name":"LeatherMaster · Case study","url":"https://www.adriannita.pl/en/projects/leathermaster","breadcrumb":{"@id":"https://www.adriannita.pl/en/projects/leathermaster#breadcrumb"},"isPartOf":{"@id":"https://www.adriannita.pl/en#website"},"potentialAction":[{"@type":"ReadAction","target":["https://www.adriannita.pl/en/projects/leathermaster"]}]},{"@id":"https://www.adriannita.pl/#identity","@type":"Person","jobTitle":"Fullstack developer","name":"Adrian Nita","url":"https://www.adriannita.pl","knowsAbout":["Laravel","PHP","Vue","Nuxt","TypeScript","E-commerce","REST API","Payment integrations"],"sameAs":["https://github.com/adrian-nita","https://www.linkedin.com/in/adrian-nita-01"]},{"@id":"https://www.adriannita.pl/en/projects/leathermaster#article","@type":"Article","description":"Website and a custom CMS for a leather upholstery restoration workshop. Customers book training courses and pay online, and the owner edits the content in the panel.","headline":"LeatherMaster","inLanguage":"en-US","thumbnailUrl":"https://www.adriannita.pl/images/projects/leathermaster.webp","author":{"@id":"https://www.adriannita.pl/#identity"},"image":{"@id":"https://www.adriannita.pl/#/schema/image/1"},"isPartOf":{"@id":"https://www.adriannita.pl/en/projects/leathermaster#webpage"},"mainEntityOfPage":{"@id":"https://www.adriannita.pl/en/projects/leathermaster#webpage"},"publisher":{"@id":"https://www.adriannita.pl/#identity"}},{"@id":"https://www.adriannita.pl/en/projects/leathermaster#breadcrumb","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","name":"Adrian Nita","item":"https://www.adriannita.pl/en","position":1},{"@type":"ListItem","name":"LeatherMaster","position":2}]},{"@id":"https://www.adriannita.pl/#/schema/image/1","@type":"ImageObject","contentUrl":"https://www.adriannita.pl/images/projects/leathermaster.webp","inLanguage":"en-US","url":"https://www.adriannita.pl/images/projects/leathermaster.webp"}]}
```

## Sitemap

See the full [sitemap](https://www.adriannita.pl/sitemap.md) for all pages.
