# Vehicle makes and models autocomplete in Next.js

A make-then-model form in Next.js: choosing a make narrows the model field to that make's models with the parent filter.

## How do I build dependent make and model fields in Next.js?
Use the same component inside a Client Component twice: one field on the makes list, one on the models list. When a make is chosen, pass its value as the parent of the model field. The runtime then returns only that make's models, because the models list is a two-level hierarchy of make and model.

## What is different about vehicle makes and models
- Two lists, one id space: The make field uses the vehicle makes list. Its item.value is the make id, the same id the vehicle models list uses for each make, so it can be passed straight through as the parent.
- The parent filter: A query with a parent returns only that parent’s children. The runtime accepts parent only for a hierarchical list; on a flat list it is an invalid request.
- Resetting the model: When the make changes, the model field must start fresh. Remount it, or clear it and set the new parent, so a model from the old make is never kept.
- Some makes have no models: The makes list holds every make, and a few have no models under them. The model field then shows an empty state, which is a normal answer and not an error.

## Steps
1. Create two publishable keys: one for the vehicle makes list and one for the vehicle models list.
2. Create a client for each and call bootstrap() on both, so each list’s own minimum length and debounce apply.
3. When a make is selected, pass its value as the parent of the model field.
4. Clear the model whenever the make changes, and disable the model field until a make is chosen.

## Code
```
// app/garage/vehicle-fields.tsx
'use client';

import { useState } from 'react';
import { AutoSugges } from '@autosugges/client/react';
import { AutosuggesProvider, type AutoSuggesItem } from '@autosugges/client/react-core';

// Two lists: every make, and the models under each make.
const lists = { makes: 'YOUR_MAKES_PUBLISHABLE_KEY', models: 'YOUR_MODELS_PUBLISHABLE_KEY' };

export function VehicleFields() {
  const [make, setMake] = useState<AutoSuggesItem | null>(null);
  const [model, setModel] = useState<AutoSuggesItem | null>(null);

  return (
    <AutosuggesProvider lists={lists} baseUrl={process.env.NEXT_PUBLIC_AUTOSUGGES_RUNTIME_URL!}>
      <AutoSugges
        list="makes"
        label="Make"
        value={make}
        onChange={(next) => {
          setMake(next as AutoSuggesItem | null);
          setModel(null);
        }}
      />
      <AutoSugges
        key={make?.value ?? 'no-make'}
        list="models"
        label="Model"
        disabled={make === null}
        value={model}
        onChange={(next) => setModel(next as AutoSuggesItem | null)}
        overrides={make === null ? {} : { parentId: make.value }}
      />
      <input type="hidden" name="make" value={make?.value ?? ''} />
      <input type="hidden" name="model" value={model?.value ?? ''} />
    </AutosuggesProvider>
  );
}

// app/garage/page.tsx — a Server Component.
import { VehicleFields } from './vehicle-fields';

async function saveVehicle(formData: FormData) {
  'use server';
  const make = formData.get('make'); // the make id
  const model = formData.get('model'); // "<makeId>:<modelId>"
  // persist both with your own data layer
}

export default function GaragePage() {
  return (
    <form action={saveVehicle}>
      <VehicleFields />
      <button type="submit">Save</button>
    </form>
  );
}
```

## Check that it works
1. Pick a make, then type in the model field. Only that make’s models appear.
2. Change the make. The model field is empty again and queries the new make.

## Security
A publishable key is public by design and belongs in client code exactly as written. Never place a secret key, a service-role credential or a database URL in this code or in generated code.

## Frequently asked questions

### How does the model field know which make was chosen?

You pass the chosen make’s value as the parent of the model field. The query then carries a parent parameter and the runtime returns only the children of that make.

### Why are there two keys?

A publishable key resolves to one list. The make field queries the makes list and the model field queries the models list, so each has its own key and its own query policy.

### What if a make has no models?

The model field shows its empty state. That is a valid answer to the query, not a failure, and the component never presents an error as no results.

### Can I pass a parent to any list?

No. The runtime accepts parent only for a hierarchical list. On a flat list such as currencies it returns an invalid request.

### What is the minimum number of characters before a query runs?

Two by default. A list owner can change the minimum, but it can never be 1. The client reads the real value from bootstrap and sends no request below it, so do not hardcode it.

---
Canonical page: https://docs.autosugges.com/integrations/nextjs/vehicle-models
