Last month, a real estate client in Abu Dhabi asked for an admin dashboard that could manage 10k+ property listings in both Arabic and English. Their previous dashboard (built with a bloated third-party template) had become a maintenance nightmare. I rebuilt it from scratch using Next.js, Prisma, and custom components. Took 3 weeks. No UI kits, no paid tools. Just vanilla code and a clear plan.
Let me walk through how I structure these projects without relying on expensive templates or drag-and-drop builders.
Why I Stopped Using Third-Party Admin Templates
My last Laravel project in Dubai used a $500 admin theme. It looked great, but:
- •Half its JS dependencies broke when PHP 8.3 dropped
- •Customizing its routing for Arabic language switches meant 3 days of hacks
- •The client couldn't touch the codebase afterward
Now I avoid third-party tools for internal dashboards. Yes, it's more work upfront, but:
- •Zero dependency bloat
- •100% control over code quality
- •Easier to train a client's team on clean, explicit patterns
I'm not against libraries – we use next-auth.js and react-table – but core dashboard architecture is always custom.
Data Modeling: Starting with Prisma
Every dashboard starts with the data. For a UAE e-commerce client, I mapped their order flows in Prisma before writing any frontend code.
The schema looks like this in Prisma 5.0:
model Order {
id String @id @default(cuid())
status String @default("pending") // "processing", "delivered", "cancelled"
items Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}This simple model powers the whole order management section. Prisma Studio helps me visualize it during development – no separate admin panel needed.
One mistake I made: Adding a JSON column for order items early on seemed flexible. But when the client wanted search-by-product-name functionality 2 months in, I had to migrate to a proper Product model. Learn from me: denormalize data only when you absolutely need performance gains.
Caching Data in Next.js
I use the App Router’s fetch caching by default but override it for dynamic dashboard filters:
async function getOrders(filter: string) {
const response = await fetch(`/api/orders?status=${filter}`, {
cache: 'no-cache',
});
return response.json();
}This prevents stale data from showing after urgent admin actions. For read-heavy pages like statistics charts, I stick with cache: 'force-cache' – it reduced API calls by 70% for a logistics client in Sharjah.
Building UI Components from Scratch
I use Tailwind CSS but skip component libraries. For a limo booking dashboard I built in 2024 (Tawasul Limo), the team needed real-time ride tracking in both RTL and LTR layouts.
The solution:
- Create layout wrappers for language direction
- Style buttons manually using Tailwind classes
- Reuse a single
Tablecomponent across all dashboards
function DashboardTable({ data, columns }) {
// React-table implementation here
}Yes, it took longer than using a UI kit. But now I have a component that:
- •Handles right-to-left text properly
- •Works with any Prisma model
- •Doesn’t force clients to pay for licenses
Authentication & Role Management
For a Dubai fintech startup, I built role-based access using Next.js app directory patterns:
/app
/admin
/dashboard
/users
/api
/auth Middleware checks roles against a database field:
async function checkUserRole(request) {
const user = await getCurrentUser();
if (!user.permissions.includes('admin')) {
redirect('/unauthorized');
}
}They wanted granular permissions (like "can_edit_pricing" flags), so I stored role rules in a JSON column. Wasn’t perfect – JSON searches in PostgreSQL can be slow – but it worked well enough for their 200-user dashboard.
Handling Arabic Language Support
Any dashboard for GCC clients needs bidirectional text handling. For Reach Home Properties, I stored strings in Arabic/English pairs in the database:
{
"en": "Property added successfully",
"ar": "تم إضافة العقار بنجاح"
}Frontend displays the correct version using a locale helper:
function t(key: string) {
const lang = useLocalStorage('language', 'en');
return translations[key][lang.value];
}But right-to-left forms are tricky. For dates and currency inputs in Arabic, I used react-hook-form with custom RTL formatting – took 2 whole days to make dropdown arrows and text alignment look right.
Deployment and Maintenance
All my dashboards deploy on Vercel with PostgreSQL hosted on Neon. For larger UAE enterprise clients (like a corporate site I built for DAS Holding), I include:
- Daily database backups via Neon’s branching
- GitHub Actions for staging deployments
- Simple monitoring with Vercel logs and Sentry
Maintenance is where third-party tools usually break. One government client had 26 dashboard filters built with a UI library – when a major React update broke their codebase, fixing it cost them 10 dev days. With custom dashboards, you know exactly what will break where.
Frequently Asked Questions
Why not use tools like Retool or Supabase for internal dashboards?
They're great for prototypes, but for production use with complex auth/business rules, they get expensive and restrictive. Last year I built a Supabase dashboard for a UAE logistics company – they paid $500/month to exceed row limits. Custom dashboards on Neon cost them 1/10th that.
How do you handle performance with large datasets?
Prisma pagination. For a client with 200k orders, we implemented cursor-based pagination using skip and take with indexed database fields. Response time went from 6s to 0.3s.
What’s your stack for real-time features?
For stock management dashboards, I use Pusher with Laravel broadcasting and React Query for live updates. Pusher costs money, but it’s worth it for real-time data – unlike custom WebSocket implementations that take longer and have edge cases.
Can you use the same codebase for both admin and public dashboards?
Yes. At a high level, the architecture is the same. For a hotel booking platform, the admin and customer-facing dashboards shared the same Prisma ORM and auth logic – just different UI layers built with Next.js slots.
If you're building or rebuilding an admin dashboard and want to avoid third-party bloat, I’ve done this 40+ times for UAE and GCC clients. Let’s talk – book a free consultation to walk through your requirements.
Most of my clients come to me stuck with unscalable templates or broken dependencies. I help them build something that lasts 3-5 years without rewrite cycles.