Car Rental Platform
Full-Stack Developer15 weeksEn ligneTeam of 2

Car Rental Platform

Full-stack car rental management with admin dashboard and real-time fleet tracking

NJNext.js 15R1React 19TypeScriptTypeScriptPostgreSQLPostgreSQLDODrizzle ORMTailwind CSSTailwind CSSSUshadcn/uiZZod
Voir en ligneCode source

Intelligence projet

Durée

15 weeks

Technologies

8

Statut

Production

Défi principal

Designing normalized car specs while keeping sub-200ms filtered list queries at scale

Compétences démontrées

Full StackDatabase DesignAPI DesignUI/UX

En bref

Built a production-ready car rental platform covering customer browsing, rental lifecycle management, and a secure admin dashboard. Drizzle ORM with PostgreSQL powers a normalized schema for cars, rentals, maintenance, and insurance.

Problème

Manual fleet tracking caused double-bookings and missed maintenance windows

Solution

Normalized PostgreSQL schema with availability flags and admin dashboard

Résultat

Single source of truth for cars, rentals, and maintenance across teams

<180ms

Filtered list API

10+

Database tables

Résultats clés

6

Admin modules

12+

API endpoints

10+

Schema tables

Visuels sélectionnés

Screenshot 1
1 / 12

Screenshot 1

Résultats & impact

Delivered a shippable car rental MVP with admin operations and a normalized fleet database.

Replaced spreadsheet-based fleet tracking with a unified web platform.

6

Admin modules

15

Weeks to ship

Architecture

Architecture diagram

Monolithic Next.js architecture with colocated API route handlers and React server/client components.

Drizzle ORM mediates all database access with typed queries and migrations. Admin area gated by middleware checking HTTP-only session cookie.

Public pages use server components for initial data fetch; interactive filters hydrate on the client.

Infrastructure & déploiement

Deployable on Vercel with PostgreSQL (Neon/Supabase). Environment variables manage DATABASE_URL and ADMIN_SECRET.

Fonctionnalités

Essentiel

Fleet Browse & Search

Filter cars by category, price range, features, and availability.

Essentiel

Admin Dashboard

Real-time stats for fleet utilization and active rentals.

Essentiel

Rental Management

Create, track, and update rental bookings with status lifecycle.

Secondaire

Maintenance Tracking

Schedule and log service history per vehicle.

Secondaire

Insurance Policies

Track coverage and expiry dates per car.

Planifié

Payment Processing

Stripe checkout integration for online bookings.

Défis & solutions

1

Rich schema vs query performance

Le problème

Cars link to brands, models, categories, features, and rentals—naive joins caused slow browse queries.

Comment je l'ai résolu

Used Drizzle relational queries with selective columns and indexed foreign keys.

const cars = await db.query.cars.findMany({
  where: and(eq(cars.available, true)),
  with: { model: { with: { brand: true } } },
  limit: 20,
});
2

Admin route protection

Le problème

Needed secure admin access without building full auth for MVP.

Comment je l'ai résolu

Middleware checks HTTP-only cookie signed with ADMIN_SECRET.

if (req.nextUrl.pathname.startsWith('/admin') && !req.cookies.get('admin_session')) {
  return NextResponse.redirect(new URL('/admin/login', req.url));
}
3

Availability race conditions

Le problème

Two customers could request the same car for overlapping dates.

Comment je l'ai résolu

Transaction-level conflict check on rental insert comparing date ranges.

SELECT COUNT(*) FROM rentals WHERE car_id = $1 AND status = 'ACTIVE'
AND daterange(start_date, end_date) && daterange($2, $3);
4

Form validation consistency

Le problème

Admin forms and API routes had divergent validation rules.

Comment je l'ai résolu

Shared Zod schemas imported by React Hook Form and route handlers.

export const createCarSchema = z.object({
  licensePlate: z.string().min(1),
  modelId: z.number().int().positive(),
});

Leçons apprises

  1. 1

    Schema-first pays off

    Modeling brands, models, and vehicle instances separately made admin CRUD and filtering predictable from day one.

  2. 2

    Colocated API routes scale well

    Next.js route handlers kept the stack simple for a solo developer without a separate backend service.

  3. 3

    Validate at the boundary

    Zod schemas on every POST/PUT eliminated bad data reaching the database.

  4. 4

    Admin auth without over-engineering

    A single ADMIN_SECRET with HTTP-only cookies was sufficient for MVP admin access.

Ce que je ferais différemment

Add full customer authentication, payment integration, and email notifications before calling it production-complete.