---
title: "Vehicle inventory"
description: "Dealer-group inventory on the Ring store — lead-only vehicles, rooftop threads, and no unlicensed history badges"
locale: "en"
---
# Vehicle inventory

On an automotive-dealer clone the store is the group's vehicle inventory. Each unit is a `store_products` row with `nichePreset: dealer-vehicle` and a `nicheData.vehicle` record (VIN, stock, miles, price, rooftop). Shoppers browse `/store`. A vehicle does not go in the cart.

> **Info**
> This page is the dealer-pack overlay of the store article. Founder and Developer tabs filter the sections below. Sidebar visibility still comes from Layer 1 `lib/docs/audience-curated-docs.ts`, which already lists `features/store`.

  The public listing does not show one-owner, clean-title, or Carfax badges, and the vendor form cannot tick those claims. Days on the lot stay on the desk, not on the advertisement. "Ask about financing" is a question to the rooftop. It is not a credit offer, and the form does not collect an SSN.

## What changed for a dealer group

| Earlier store behavior | Dealer pack |
|---|---|
| Add to cart and checkout | `nicheSuppressesCart` hides the cart on a dealer vehicle |
| Product agent answers as the store | The vehicle page does not mount the agent rail or the floating agent button |
| Chat link opens `agentChat=1` | "Chat with seller" posts a `vehicle_inquiry` and opens `/messages?c=` |
| History chips from feed flags | Flags may still sit on the record for a later licensed feed. The public card and detail do not read them |
| "Get pre-qualified" | Button label is "Ask about financing" |

### For founders

## What your rooftops publish

Shoppers search inventory, open a vehicle, and talk to the people who work at the rooftop that owns that unit. A second chat about the same car reuses the same thread. Test drive, trade-in, service, and a seller offer do the same: the shopper lands in Messages, and the rooftop sees the row on the lead desk.

  
- **[Inventory](/docs/features/store.md)** — `/store` lists vehicles. Filters cover condition, make, body, drivetrain, fuel, transmission, rooftop, year, and miles.

  
- **[Rooftops](/docs/features/entities.md)** — `/rooftops` is the public map. The login-gated entity directory is not the storefront.

  
- **[Leads](/docs/features/opportunities.md)** — Every shopper action that needs a person becomes an entity-visible lead and a messenger thread.

### What stays off the public page

- A product agent that can invent availability, a discount, or a payment.
- A history badge the store did not buy a license to show.
- A role quiz before someone can look at cars. Shoppers are the default. "How I shop" is an optional account note at `/profile/audience`.

### For developers

## Where the pack replaces Layer 1

Compose copies `ring/web`, then `ring-presets/automotive-dealer-app/web`. A pack file at the same path replaces the Layer 1 file.

| Surface | Path |
|---|---|
| Cart hidden | `features/store/niche/niche-commerce.ts` (`nicheSuppressesCart`) |
| Vehicle shape | `features/store/types/dealer-vehicle.ts` |
| Catalog card | `features/dealer/components/vehicle-card.tsx` |
| Vehicle page block | `components/store/niche-product-detail-section.tsx` |
| No agent on a vehicle | `components/wrappers/product-details-wrapper.tsx` |
| Lead create and reuse | `features/dealer/services/leads.ts` |
| Thread | `features/opportunities/lib/entity-lead-conversation.ts` |
| Post from the browser | `features/dealer/components/post-dealer-lead.ts` |

`readDealerVehicle` requires a VIN. The product-details wrapper uses that to skip `ProductAgentChatProvider`, the agent rail, and `FloatingProductChatToggle`. Other products on the clone keep the agent.

### Shopper opens a thread

The card, the vehicle page, the test-drive dialog, `/service`, `/sell-trade`, or the seller offer calls `postDealerLead`.

`POST /api/dealer/leads` requires a session. Unsigned callers receive 401 and the UI sends them to login with `callbackUrl`.

`createDealerLead` writes an opportunity with `visibility: 'entity'` and `organizationId` set to the rooftop. For `vehicle_inquiry`, an open lead for the same shopper and product (stage not `sold` or `lost`) is reused.

`openEntityLeadConversation` creates a conversation of type `opportunity` with the shopper and `getEntityTeamUserIds`. The id is stored on `metadata.conversationId`.

The browser goes to `/messages?c=`. `MessagesShell` already reads `c` or `conversation`.

History booleans are not written from the vendor form (`parse-niche-fields.ts`). `feed-map.ts` may still copy `carfax_1_owner` and `carfax_clean_title` onto the record. The card meta and the detail section do not render them.

## Frequently asked questions

### Impact

#### Does a vehicle still check out?

No. Dealer vehicles are lead-only. There is no add-to-cart on those cards.

#### Will a second click create a second lead?

Not for chat about the same vehicle. Test drives and other kinds still create their own lead, then open that lead's thread.

### Migration

#### Where did the product agent go?

It is still in Layer 1 for ordinary products. The pack overlay of `product-details-wrapper.tsx` skips it when the product has `nicheData.vehicle`.

### Ops

#### Can staff mark a unit one-owner?

Not from the vehicle form. Those checkboxes are gone, including the one that defaulted clean title to on.

## Later, only with a contract

  
- [getting-started/first-success](/docs/getting-started/first-success.md) — Prerequisite: the owner

  
- [features/entities](/docs/features/entities.md) — Prerequisite: rooftops and the dealer group that own this inventory.

  
- [features/inventory](/docs/features/inventory.md) — Same workflow: loading stock and taking a unit off the site.

  
- [features/opportunities](/docs/features/opportunities.md) — Next-step: the lead kinds those vehicles open.
