Recently, we’ve received an increasing number of requests to build custom booking systems with admin panels that can manage records and directories. This is particularly common among B2C services, such as beauty studios and clinics, that require an efficient admin panel that is quick to build, affordable, and easily integrated into existing workflows without disrupting operations or necessitating extensive training.
Most existing aggregator platforms follow a linear model: one specialist can provide one service per time slot. This sounds simple – until you need to support group bookings or overlapping workflows, in which a single staff member participates in different stages of a procedure.
Add to that the constant stream of changes — cancellations, reschedules, service swaps — and it quickly becomes clear: the system needs to respond instantly and update the interface in real time.
That’s why more businesses are turning to custom-built solutions. However, developers still face a few significant questions:
- Which frameworks are best for building admin panels in booking systems?
- What if a standard CRUD generator can’t handle the business logic?
- How can you build a custom UI without breaking compatibility across the system?
- How can development time be reduced without sacrificing flexibility?
How Admiral Enables Customization Without Compromise
Most admin panels today are built on top of pre-made frameworks. We used to rely on popular CRUD generators ourselves – the ones that promise a ready-to-go interface in 10 minutes. However, we kept running into the same issue: they were too rigid. The structure was set in stone, and it was impossible to implement custom logic or adjust things to fit the business's real needs.
We needed more flexibility. That's what led us to build our own framework, Admiral. We now use it in over 70% of our projects. It’s open source, and you can check it out here: https://github.com/dev-family/admiral.
What makes Admiral different?
Its main advantages are built on the following approach:
- You can build custom workflows that go beyond standard CRUD logic;
- You can create interactive dashboards with charts, metrics, and widgets that show meaningful data in a way that’s actually useful.
The story of how we created Admiral
Want the full backstory on how Admiral was built? You can read it here
How it works
At its core, Admiral boasts an extensible architecture. Rather than generating static files with fixed templates, it provides a flexible routing system and modular components on which you can build. This allows you to plug in your own logic and UI wherever you need it.
The result? A powerful, universal tool that adapts to your business, not the other way around.
Adding Custom Pages in Admiral
I would now like to share my experience customizing CRUD interfaces using Admiral in one of our recent projects. The client was a chain of spa salons, and their administrative staff needed to perform two core tasks:
- Create and manage service bookings;
- Monitor staff workload via a calendar.
We ended up building two clean, user-friendly interfaces that can easily be adapted to fit different scenarios. Below, I’ll break down the process step by step so you can quickly build the same for your own project.
Managing Bookings Page
Let’s start by building a custom page for creating and editing bookings using custom components.
First, create a React component that will render your custom page. You can combine your own components with Admiral’s built-in ones to maintain a consistent style and functionality throughout the interface.
Here’s how your custom booking interface might look using a combination of Admiral components and your own.

Now that you have the main RecordPage component, you’ll need to create files that use it depending on the operation type – creating or editing a record. These files will act as entry points for Admiral’s routing system.
For example, create the following files in the /pages/records/ directory:
- create.tsx – a page for creating a new record.
import React from 'react'
import RecordPage, { RecordPageType } from '../RecordPage'
const CreateRecordPage = () => {
return <RecordPage type={RecordPageType.CREATE} />
}
export default CreateRecordPage
- [id].tsx – a page for editing an existing record ([id] in the filename allows Admiral to dynamically resolve the route).
import React from 'react'
import RecordPage, { RecordPageType } from '../RecordPage'
const EditRecordPage = () => {
return <RecordPage type={RecordPageType.EDIT} />
}
export default EditRecordPage
- index.tsx – the base CRUD page that displays a list of all records.
import { CRUD } from '@/src/crud/records'
export default CRUD.IndexPage
As a result, you get a fully functional CRUD interface with a table of current records and custom pages for creating and editing entries.

Creating a Booking Calendar
The CRUD table we built solves the basic task of storing and retrieving records. However, for administrators, that’s often not enough. They need a clear overview of each team member’s availability, including open time slots, rescheduled bookings, and overlapping services.
In Admiral, custom pages are added just like CRUD ones.
You can create a separate React component in the /pages/main/ directory to render your calendar with interactive elements.
import React, { useEffect, useState } from 'react'
import { CalendarHeader, CalendarTable, CalendarRecordNote } from './ui'
import { TCalendarHeaderData, TGroupedServices, TCalendarHeaderData } from './ts'
import styles from './CalendarPage.module.scss'
const CelendarPage = () => {
const [isLoading, setIsLoading] = useState<boolean>(false)
const [timeSlots, setTimeSlots] = useState<string[]>([])
const [services, setServices] = useState<Array<TGroupedServices> | null>(null)
const [calendarHeaderData, setCalendarHeaderData] = useState<Array<TCalendarHeaderData>>([])
const [comment, setComment] = useState<string>('')
const fetchCalendarData = async ({date}: {date: string}) => {
// Connect API request to get data
}
useEffect(() => {
fetchCalendarData({
date: urlState.date || new Date()
})
}, [])
return <Page title="Main page">
<div className={styles.calendar_page}>
<CalendarHeader />
<CalendarRecordNote comment={comment} />
<CalendarTable
isLoading={isLoading}
timeSlots={timeSlots}
services={services}
calendarHeaderData={calendarHeaderData}
/>
</div>
</Page>
}
export default EditRecordPage
With this, administrators can now manage bookings using a visual, easy-to-read calendar interface tailored to their day-to-day workflow.

Integration Into Navigation
Once your pages are set up, the final step is to add them to your project’s navigation so users can easily access them.
To do that, create a navigation file. For example, menu.tsx (if it doesn’t already exist) and include your new pages as menu items.
import React from 'react'
import { Menu, MenuItemLink } from '@devfamily/admiral'
import { FiUsers, FiUser, FiSettings } from 'react-icons/fi'
const CustomMenu = () => {
return (
<Menu>
<MenuItemLink icon="FiUsers" name="Main" to="/main" /> // navigate to custom page
<MenuItemLink icon="FiUser" name="Records" to="/records" /> // navigate to page with custom components
<MenuItemLink icon="FiSettings" name="Services" to="/services" />
<MenuItemLink icon="FiSettings" name="Masters" to="/masters" />
</Menu>
)
}
export default CustomMenu
Conclusion
After using Admiral across multiple projects, we’ve seen firsthand how much it can offer:
- Built for complex logic – while typical CRUD generators hit structural limitations early on, Admiral gives you the space to keep building, no matter how custom the interface needs to be;
- Flexible without the overhead – its open architecture lets you plug in anything: custom components, business logic, calendar views whatever your project demands;
- Fast to launch, easy to scale – you can quickly set up a basic CRUD interface, then keep adding complexity as your product grows.
With Admiral, your team can save dozens of development hours and focus more on what really matters – delivering business value.