CHANGELOG.md

Changelog

All notable changes to RentNGo are documented here.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning. From v2.4.0 onward, version sections below the [Unreleased] heading are generated automatically by release-please from Conventional Commits.

2.5.0 (2026-10-17)

Added

  • add migrations for deprecated vehicle fields (5aaee43)
  • add SEO-friendly vehicle slug URLs with real-time validation (b04609c)
  • add sticky booking card to transfer vehicle selection (69106ec)
  • add Terms & Privacy links to transfer booking page (3d5e683)
  • add transfer multiplier management UI to vehicle class page (9366355)
  • add transfer vehicle seats configuration for accurate passenger filtering (df89e6c)
  • add vehicle details section to transfer confirmation emails (52c9100)
  • added a px-49 to the header and a mx-49 to the footer to be more central (916ce71)
  • added engine capacity to the vehicle schema (005ca07)
  • admin: full-height table pages — fixed toolbars, scrolling table body (#95) (ce0a982)
  • admin: linear-style table ux (#96) (ef834ee)
  • admin: overview needs-attention row — upcoming, pending, recent (#99) (ed2e1c1)
  • admin: polish set — undo toasts, optimistic updates, empty states (#97) (cbf5efb)
  • admin: sticky table headers (#100) (d58d5ff)
  • admin: viewport-locked shell with inset sidebar (#93) (12630b3)
  • affiliate referral program with configurable tiers and consent-gated attribution (#51) (43a2ec7)
  • AI-crawler robots allows, llms.txt, bilingual FAQ page, company constants + LocalBusiness JSON-LD (#48) (96d7289)
  • app: enable Instant Navigations — cacheComponents + partialPrefetching (RNGO-35) (3836e7b)
  • app: enable Instant Navigations (cacheComponents + partialPrefetching) (e7e7a3c)
  • card design work in progress (c4ad9db)
  • cars: "from X €" badge on car cards without dates (#122) (207f147)
  • change the form a little and added a website icon (3400808)
  • change the selector for the locations to be more efficient and useable by utilizing the command (fc5d061)
  • contact: always-visible quick contact bubbles (#117) (5ae4a0f)
  • convex: scheduled gc for orphaned storage files (#76) (0223a66)
  • coupon codes with server-side validation and atomic redemption (#50) (4b9f1b0)
  • english terms page and ANPC badges in the footer (#133) (e6d96a3)
  • finish localization and secure transfer bookings (#70) (11415b5)
  • implement sequential calendar flow and default times (b0067d2)
  • implement tiered transfer pricing system (5786bee)
  • noindex non-production deployments and env-driven email differentiation (f592196)
  • referral: admin approvals queue, history, wallet top-ups (RNGO-55) (#115) (22c9e6b)
  • referral: first-rental-only discount, typed codes, self-service enrolment (RNGO-54) (#114) (71f2687)
  • referral: mint wallet credit on admin-approved conversions (RNGO-52) (#113) (50b4e23)
  • referral: redeem wallet credit at checkout (RNGO-53) (#112) (8d9c952)
  • referral: wallet and sharing on the profile, referral block in emails (RNGO-56) (#116) (cc8f7e0)
  • referral: wallet schema, credit math and widen migration (RNGO-51) (#111) (fc53872)
  • replace hardcoded admin IDs with Clerk role-based auth (bd7b396)
  • seo: localized fleet URLs (#120) (4477487)
  • server-authoritative pricing engine with shared lib/pricing module (#45) (d591cd7)
  • show included + extra km in reservation emails, localized SCDW label (#46) (d3db19e)
  • testimonials: google rating, reviews link, drop stock testimonials (#118) (346edc8)

Fixed

  • added engine details in the vehicle card component (b7e83b2)
  • admin ordering crash, datetime picker state bleed, mapbox coord fabrication, localized nav (#43) (3d3f1ce)
  • admin: full-height blogs table, truncated titles, sticky actions (#102) (5aa6ef3)
  • bump next + react (May 2026 security release) (#57) (827ca36)
  • correct typo in reservation-email-dialog filename (39b579c)
  • deps: next 16.4 and react 19.3 for the next.js security advisories (#126) (fc3ee92)
  • drop --webpack from mise dev:frontend task (#64) (d303ab4)
  • fix type compatibility for te vehicles from the ui (351abf7)
  • image previews (3ab7140)
  • image uploads via Convex upload URLs instead of bytes through action args (#42) (09f3cdc)
  • mobile: 3 contact bubbles bottom-right, no sideways scroll, drop stale search dates (#124) (0d111f2)
  • petrol/benzina validator mismatch + refactor: shared Convex validators (#89) (9268ff6)
  • profile, footer and faq UI polish (#52) (fb6c34e)
  • referral: discount the rental price only, not SCDW and add-ons (#119) (541f676)
  • require admin auth on Convex writes, booking ownership checks, PII query auth (#41) (59943c3)
  • seo: clean up the urls search console flags as unindexable (#121) (4ed9778)
  • seo: single-hop redirects for the old /cars urls (#123) (1f19ea9)
  • show admin edits on cached public pages (cars, homepage, blog) (#125) (39fdddc)
  • sitemap base url fix from .com to .ro (8fb5f8e)
  • sitemap base url fix from .com to .ro (bce70ff)
  • store reservation vehicle id in localStorage, not the url (#54) (528b81a)
  • support-email drift + locale-losing profile nav (#84) (4f09bd6)
  • sync clerk users to convex via webhooks (#66) (bda7465)
  • ui: defer render-time new Date() in booking widgets to post-hydration (47c00d2)
  • ui: lint-clean useToday via useSyncExternalStore + justified purity disable (09f08f9)
  • undefined index for car classes (b23d5a1)
  • undefined index for car classes (2ec2a4d)
  • upgrade Next.js to 15.5.7 for CVE-2025-66478 security patch (7f29c73)
  • url-encode order_by param in clerk backfill action (#67) (d3fa07e)
  • webhooks: svix 2.8 without breaking clerk user sync (#127) (6ab3e78)

Performance

  • admin: bound dashboard statistics (32bfaf8)
  • admin: bound dashboard statistics (b1cdd6f)
  • admin: paginate booking lists (b57b1c8)
  • admin: paginate booking lists (8eecf56)
  • bookings: allocate numbers with counters (6096c0a)
  • bookings: allocate numbers with counters (70ad48b)
  • convex: index blog and vehicle queries (16eb367)
  • convex: index blog and vehicle queries (24d9e8b)
  • convex: maintained aggregates for all-time dashboard totals (#78) (dd6fc55)
  • restore static rendering, code-split mapbox, optimize LCP images (#47) (b13f9c0)
  • switch dev server to turbopack (#63) (1cbe25f)

Changed

  • admin UI dedup — pricing fields, dashboard cards, breadcrumbs (#92) (4dae8c9)
  • admin: make tables the visual focus (#98) (bbc030e)
  • admin: shared season form + thin dialog wrappers (#77) (de9d803)
  • consolidate translation files and remove unused keys (1539485)
  • convert file names to kebab-case (1ca0ead)
  • createLocalStorage factory + shared search defaults (#85) (96ef68c)
  • decompose reservation page onto shared pricing module + persisted confirmation (#49) (1be3b3e)
  • finish company-identity migration onto lib/company.ts (#88) (c280aba)
  • parameterize vehicle filters by category config (#86) (e7f224f)
  • remove dead code and unused dependencies (#44) (9c81317)
  • remove deprecated field usage and dead code (c1d1a42)
  • rename vehicle classes admin section (8de6a2e)
  • restructure components directory to feature-based organization (85704be)
  • shared StatusBadge + formatting helpers (#91) (1335cf6)
  • transfer + car-detail storage-lifecycle dedup (#87) (b20b0cc)
  • type-safety + component leftovers (#90) (498089f)
  • uniform layout for reservation, car detail and transfers pages (#53) (d4f77f6)

[Unreleased]

Fixed

  • Clerk→Convex user sync (RNGO-32): users are now synced server-side via Clerk webhooks (POST /webhooks/clerk Convex HTTP action, Svix-verified) handling user.created/user.updated/user.deleted, with an idempotent getOrCreateCurrentUser safety net in renter-facing booking mutations; user.deleted and self-serve account removal soft-delete + anonymize the row (deletedAt + PII scrub) so booking references stay valid; client-side UserEnsurer/ensureUser removed; one-off Clerk backfill action added (migrations/backfillClerkUsers). Awaiting deploy + Clerk dashboard/webhook-secret config.

Infrastructure

  • Dev environment: develop branch now deploys to a dedicated Convex deployment (develop, same project) and is served at dev.rngo.ro; upgraded convex to 1.42.1 and @convex-dev/resend to 0.2.5
  • Non-production deployments are excluded from search indexing (robots.txt + noindex meta), and dev emails are visibly differentiated (env-driven sender name, [DEV] subject prefix, site-URL-aware logo)

[2.4.0] - 2026-06-02

Added

  • Google Tag Manager: wired in root layout via @next/third-parties/google GoogleTagManager, configured by NEXT_PUBLIC_GTM_ID

    • Only renders when env var is set
    • Direct Google Ads gtag removed from app/layout.tsx — Ads conversions are now configured as a tag inside the GTM container (NEXT_PUBLIC_GOOGLE_ADS_ID no longer used by app code)
  • Bilingual blog support: blogs now have separate Romanian and English content

    • Schema: title_ro/en, description_ro/en, content_ro/en, readingTime_ro/en
    • Public queries accept locale arg, return locale-resolved fields
    • Admin queries return both language variants for editing
    • Admin create/edit dialogs have RO/EN content tabs
    • Preview tab has locale toggle
    • Static generation and sitemap work with locale-aware queries
    • Migration script: npx convex run migrations/bilingualBlogs
  • SEO overhaul: comprehensive SEO improvements following Next.js best practices

    • Created shared buildMetadata() helper (lib/metadata.ts) eliminating duplicated metadata across all pages
    • Added jsonLdScriptContent() utility with XSS escaping for all JSON-LD structured data
    • Dynamic <html lang> attribute based on locale (was hardcoded to "ro")
    • Added x-default hreflang to all page alternates
    • Moved JSON-LD structured data from client components to server-rendered layouts (transfers, contact, about)
    • Added generateStaticParams for car detail and blog detail pages
    • Added breadcrumb JSON-LD schema for car detail pages
    • Added noindex metadata for transactional pages (reservation, profile)
    • Fixed blog keywords type (was string, now string[])
  • Barrel import optimization: Added optimizePackageImports to next.config.ts

    • Configured for lucide-react (80 files) and date-fns (8 files)
    • Reduces cold start by 200-800ms, speeds up dev server boot
    • Automatically transforms barrel imports to direct imports at build time
  • Dynamic import admin dialogs: Converted 10 admin dialogs to lazy-load with next/dynamic

    • CreateVehicleDialog, EditVehicleDialog
    • CreateBlogDialog, EditBlogDialog
    • CreateReservationDialog, EditReservationDialog, ReservationEmailDialog
    • CreateSeasonDialog, EditSeasonDialog
    • TransferPricingDialog, CreateClassDialog
    • Dialogs now load on-demand when opened, reducing initial page bundle
  • Memoize expensive components: Applied React.memo() and useMemo() optimizations

    • Components wrapped with React.memo(): VehicleCard, TransferVehicleCard, BlogCard, FilterCheckboxItem, VehiclePricingCard, TransferBookingFloatingCard
    • Calculations memoized with useMemo(): pricing tip in VehiclePricingCard, vehicle grouping in VehicleListDisplay, reservation pricing hook, pagination in UserReservationsTable, featured vehicles hook
    • Prevents unnecessary re-renders in list-rendered components and expensive calculations

[2.3.0] - 2026-01-20

Added

  • Transfer vehicle seats configuration: Added transferSeats field for accurate passenger capacity filtering
    • New transferSeats field on vehicles schema (optional number)
    • Field only visible in admin when "Is Transfer Vehicle" is checked
    • Filtering logic: uses transferSeats if set, otherwise falls back to seats - 2
    • Transfer vehicle cards and emails show transferSeats ?? seats
    • Admin dialogs show regular seats value as placeholder for reference

Changed

  • Transfer vehicle filtering now uses effective capacity (transferSeats ?? (seats - 2)) instead of adding +2 buffer
  • Transfer confirmation emails pass effective seats for vehicle info section
  • Transfer vehicle list component now passes transferSeats to vehicle cards

Fixed

  • Removed cursor-pointer from terms acceptance text on transfer booking page (only checkbox and links are clickable)

[2.2.0] - 2026-01-20

Added

  • Transfer booking Terms & Privacy links: Added links to Terms & Conditions and Privacy Policy
    • Links open in new tab with proper rel="noopener noreferrer"
    • Locale-based translations (Romanian/English)
    • Styling matches the reservation page implementation
    • Added border-top separator for visual distinction from payment methods

[2.1.0] - 2026-01-20

Added

  • Transfer email vehicle details: Added full vehicle information to transfer confirmation emails
    • Extended TransferVehicleInfo type with type, seats, transmission, fuelType
    • Reused VehicleInfoSection component from reservation emails
    • Both user and admin transfer emails now display vehicle details
    • Includes Romanian and English translations for vehicle section labels

[2.0.0] - 2026-01-20

Added

  • Vehicle class transfer multiplier UI: Admin can now edit transfer multiplier per class
    • Added "Transfer Pricing" section to class detail page (/admin/vehicles/classes/[classId])
    • Includes Base Fare and Rate Multiplier fields with inline editing
    • Separated pricing settings into "Rental Pricing" and "Transfer Pricing" sections

Changed

  • Class detail page pricing UI reorganized for better clarity
    • "Rental Pricing" section: Extra 50km Price
    • "Transfer Pricing" section: Base Fare, Rate Multiplier

[1.9.0] - 2026-01-20

Added

  • Vehicle slug URLs: SEO-friendly car detail page URLs
    • Added slug field to vehicles schema with unique index
    • Car detail pages now use /cars/[slug] instead of /cars/[id]
    • Admin dialogs include slug input with auto-generate button (sparkle icon)
    • Slug format: {make}-{model}-{year} (e.g., bmw-x5-2024)
    • Added getBySlug query with uniqueness validation
    • Added generateVehicleSlug() and validateVehicleSlug() utilities

Changed

  • Vehicle cards now link to slug-based URLs (falls back to _id for backwards compatibility)
  • Reservation page back button uses slug-based URL
  • Sitemap generates slug-based URLs for vehicles

[1.8.1] - 2026-01-20

Removed

  • Email components consolidation: Removed unused legacy email system
    • Deleted components/shared/email/ directory (10 files) - legacy code from before Convex migration
    • Deleted deprecated /api/send/request-confirmation route (only consumer of shared/email)
    • Production email system lives in convex/emails/ (self-contained with 4 templates and 8 components)
    • Kept /api/send/reservation-email route (used by admin for manual resends, has inline HTML)

[1.8.0] - 2026-01-20

Changed

  • Component directory restructuring: Reorganized ~130 components from type-based to feature-based structure
    • Created shared/ directory with auth/, search-filters/, providers/, navigation/
    • Created features/ directory with vehicles/, reservations/, transfers/, blog/, landing/
    • Reorganized admin/ into resource-based subdirectories: vehicles/, reservations/, transfers/, vehicle-classes/, seasons/, blog/
    • Moved 14 scattered top-level components to proper locations
    • Added barrel exports (index.ts) for cleaner imports
    • Updated all import paths across the codebase

[1.7.0] - 2026-01-19

Removed

  • payments table from schema (never implemented)
  • vehicles.class field (replaced by classId)
  • vehicles.pricePerDay field (replaced by pricingTiers)
  • by_class index from vehicles table
  • hooks/useSeasonalPricing.ts (replaced by useDateBasedSeasonalPricing)
  • VehicleClass type export from types/vehicle.ts
  • ~20 lines of TODO comments from convex/reservations.ts
  • Legacy pricePerDay fallbacks from pricing utilities

Added

  • convex/migrations/clearDeprecatedClassField.ts - Migration to clear deprecated class field
  • convex/migrations/clearDeprecatedPricePerDay.ts - Migration to clear deprecated pricePerDay field

Changed

  • Admin vehicle dialogs now use useDateBasedSeasonalPricing hook
  • vehicles-table.tsx now looks up class name via classId reference
  • Pricing logic in types/vehicle.ts now requires pricingTiers (no fallback)
  • Transfer page titles: removed "VIP" keyword from translations (en/ro)

[1.6.0] - 2026-01-19

Removed

  • 19 unused component files (~2,500 lines of code):
    • Vehicle: edit-vehicle-form, create-vehicle-form, vehicle-image-carrousel (typo), 4 skeletons
    • UI (shadcn): input-otp, navigation-menu, display-cards, slideshow, collapsible, drawer, progressive-blur
    • Admin: team-switcher, nav-projects
    • Top-level: location-search-input, rental-details-skeleton, login-form

Changed

  • Updated components/vehicle/index.ts to remove stale exports

[1.5.0] - 2026-01-19

Added

  • Sticky glassmorphic booking card on transfer vehicle selection page
  • Card uses CSS position: sticky to stay at bottom while scrolling
  • TransferBookingFloatingCard component with glass effect styling
  • onVehiclesLoaded callback to TransferVehicleList component

Changed

  • Transfer vehicle selection page uses full-width vehicle grid
  • Continue button always visible via sticky card at bottom of container

[1.4.0] - 2026-01-19

Changed

  • Renamed admin vehicle classes section from "ordering" to "classes"
  • Button: "Manage Ordering" → "Manage Classes"
  • Page title: "Class Ordering" → "Vehicle Classes"
  • URL: /admin/vehicles/ordering → /admin/vehicles/classes

[1.3.0] - 2026-01-19

Added

  • Tiered transfer pricing system with admin-configurable km ranges
  • Transfer base fare per vehicle class
  • Transfer pricing tiers management in admin panel

Changed

  • Transfer pricing now uses: base_fare + (extra_km × tier_price × class_multiplier)
  • Simplified client-facing transfer pricing display (distance + total only)

[1.2.0] - 2026-01-18

Added

  • Sequential calendar flow: return date calendar auto-opens after selecting pickup date

Changed

  • Applied sequential calendar behavior to all reservation pages

[1.1.0] - 2026-01-18

Changed

  • Default pickup and return time set to 10:00

[1.0.0] - 2026-01-18

Added

  • Initial PRD documentation
  • Vehicle reservations with tiered pricing
  • VIP transfer booking with Mapbox integration
  • Seasonal pricing system
  • Admin dashboard for vehicles, reservations, transfers, seasons, blogs
  • Email notifications via Resend
  • Romanian and English language support