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/clerkConvex HTTP action, Svix-verified) handlinguser.created/user.updated/user.deleted, with an idempotentgetOrCreateCurrentUsersafety net in renter-facing booking mutations;user.deletedand self-serve account removal soft-delete + anonymize the row (deletedAt+ PII scrub) so booking references stay valid; client-sideUserEnsurer/ensureUserremoved; one-off Clerk backfill action added (migrations/backfillClerkUsers). Awaiting deploy + Clerk dashboard/webhook-secret config.
Infrastructure
- Dev environment:
developbranch now deploys to a dedicated Convex deployment (develop, same project) and is served at dev.rngo.ro; upgradedconvexto 1.42.1 and@convex-dev/resendto 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/googleGoogleTagManager, configured byNEXT_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_IDno 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
localearg, 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
- Schema:
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-defaulthreflang to all page alternates - Moved JSON-LD structured data from client components to server-rendered layouts (transfers, contact, about)
- Added
generateStaticParamsfor car detail and blog detail pages - Added breadcrumb JSON-LD schema for car detail pages
- Added
noindexmetadata for transactional pages (reservation, profile) - Fixed blog
keywordstype (was string, now string[])
- Created shared
Barrel import optimization: Added
optimizePackageImportsto next.config.ts- Configured for
lucide-react(80 files) anddate-fns(8 files) - Reduces cold start by 200-800ms, speeds up dev server boot
- Automatically transforms barrel imports to direct imports at build time
- Configured for
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
transferSeatsfield for accurate passenger capacity filtering- New
transferSeatsfield on vehicles schema (optional number) - Field only visible in admin when "Is Transfer Vehicle" is checked
- Filtering logic: uses
transferSeatsif set, otherwise falls back toseats - 2 - Transfer vehicle cards and emails show
transferSeats ?? seats - Admin dialogs show regular seats value as placeholder for reference
- New
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
transferSeatsto 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
- Links open in new tab with proper
[2.1.0] - 2026-01-20
Added
- Transfer email vehicle details: Added full vehicle information to transfer confirmation emails
- Extended
TransferVehicleInfotype with type, seats, transmission, fuelType - Reused
VehicleInfoSectioncomponent from reservation emails - Both user and admin transfer emails now display vehicle details
- Includes Romanian and English translations for vehicle section labels
- Extended
[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
- Added "Transfer Pricing" section to class detail page (
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
slugfield 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
getBySlugquery with uniqueness validation - Added
generateVehicleSlug()andvalidateVehicleSlug()utilities
- Added
Changed
- Vehicle cards now link to slug-based URLs (falls back to
_idfor 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-confirmationroute (only consumer of shared/email) - Production email system lives in
convex/emails/(self-contained with 4 templates and 8 components) - Kept
/api/send/reservation-emailroute (used by admin for manual resends, has inline HTML)
- Deleted
[1.8.0] - 2026-01-20
Changed
- Component directory restructuring: Reorganized ~130 components from type-based to feature-based structure
- Created
shared/directory withauth/,search-filters/,providers/,navigation/ - Created
features/directory withvehicles/,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
- Created
[1.7.0] - 2026-01-19
Removed
paymentstable from schema (never implemented)vehicles.classfield (replaced byclassId)vehicles.pricePerDayfield (replaced bypricingTiers)by_classindex from vehicles tablehooks/useSeasonalPricing.ts(replaced byuseDateBasedSeasonalPricing)VehicleClasstype export fromtypes/vehicle.ts- ~20 lines of TODO comments from
convex/reservations.ts - Legacy
pricePerDayfallbacks from pricing utilities
Added
convex/migrations/clearDeprecatedClassField.ts- Migration to clear deprecated class fieldconvex/migrations/clearDeprecatedPricePerDay.ts- Migration to clear deprecated pricePerDay field
Changed
- Admin vehicle dialogs now use
useDateBasedSeasonalPricinghook vehicles-table.tsxnow looks up class name viaclassIdreference- Pricing logic in
types/vehicle.tsnow requirespricingTiers(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
- Vehicle:
Changed
- Updated
components/vehicle/index.tsto remove stale exports
[1.5.0] - 2026-01-19
Added
- Sticky glassmorphic booking card on transfer vehicle selection page
- Card uses CSS
position: stickyto stay at bottom while scrolling TransferBookingFloatingCardcomponent with glass effect stylingonVehiclesLoadedcallback toTransferVehicleListcomponent
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