# base44 integration rules

This page is the detailed rule set referenced by the [base44 starter prompt](/docs/integrations/base44.md). It exists so the prompt you paste into the builder can stay short — the agent fetches this page and follows the rules below. It is intentionally kept out of the sidebar.

base44 builds **React** SPAs (Vite + Tailwind), so use the [`@ideal-postcodes/react`](https://docs.ideal-postcodes.co.uk/docs/address-finder/react.md) component. It renders its own `<input>`, attaches the widget, and hands the selected address back through `onAddressRetrieved` — no `useEffect`, `useRef`, CSS selectors, or controlled/uncontrolled juggling. The one thing base44 still gets wrong is the API key: it assumes a Secret can reach the browser when the plan doesn't allow it. The rule below pre-empts that.

## Install the package[​](#install-the-package "Direct link to Install the package")

* Install `@ideal-postcodes/react`. It pulls in `@ideal-postcodes/address-finder` automatically; you don't need to add it separately.

## Wiring the widget[​](#wiring-the-widget "Direct link to Wiring the widget")

* Render the component and read the resolved address from `onAddressRetrieved`:

  ```
  import { AddressFinder } from "@ideal-postcodes/react";



  <AddressFinder

    apiKey={apiKey}

    onAddressRetrieved={(address) => {

      setForm({

        line_1: address.line_1,

        line_2: address.line_2,

        line_3: address.line_3,

        post_town: address.post_town,

        postcode: address.postcode,

        country: address.country,

      });

    }}

  />
  ```

* The component draws its own search `<input>`. To reuse a styled input from your design system, pass it as a single child instead (wrap mode): `<AddressFinder apiKey={apiKey} ...><input className="..." /></AddressFinder>`.

* Populate every **other** field from the `onAddressRetrieved` callback into React state. Those fields are controlled (`value` + `onChange`) as normal — the component never writes to them directly.

* The stylesheet is auto-injected by default (`injectStyle` defaults to `true`), so the dropdown is styled out of the box. No separate CSS import is required.

## API key[​](#api-key "Direct link to API key")

The Ideal Postcodes API key is a **publishable** browser key — it is designed to ship in client-side code and is protected by [Allowed URLs](/docs/guides/allowed-urls.md), not by secrecy (exactly like a Stripe `pk_` publishable key). How you supply it to the `apiKey` prop depends on the base44 plan:

* **Free plan (no Secrets / backend functions):** Secrets and backend functions require Builder+. Do **not** try to read the key from a Secret, a `VITE_` env var, or a backend function — none of those are available, and the autocomplete will silently never load. Instead, pass the `ak_…` key **directly as the `apiKey` prop** as a constant. This is safe because it is a publishable key locked to your origin via Allowed URLs.
* **Builder+ plan:** read the key from the `IDEAL_POSTCODES_API_KEY` Secret via a small backend function that returns it to the frontend, fetch it on mount into state, and pass that state as `apiKey`. A `VITE_`-prefixed env var also works if your build injects it at build time.

If you are unsure which plan is active, just pass the key directly — it always works and is safe for a publishable key.

## Errors[​](#errors "Direct link to Errors")

* Pass `onSearchError` and `onSuggestionError` props. If the Ideal Postcodes API returns a 4xx error, surface the error's message to the user — do not swallow it. A `401` almost always means the app's origin is missing from the key's Allowed URLs.

## Reference docs[​](#reference-docs "Direct link to Reference docs")

* [React integration guide](https://docs.ideal-postcodes.co.uk/docs/address-finder/react.md)
* [Address Finder reference](https://docs.ideal-postcodes.co.uk/docs/address-finder.md)
