# Addresses

> Show the logged-in customer's saved addresses and let them add, edit and delete them. Covers the address list, the field names of the address forms, and the country and province selects.

Status: Ready (Smootify 2.0)  
URL: https://www.smootify.io/docs/astro/build/addresses  
Updated: 2026-10-21

Customers keep their shipping addresses in their Shopify account. This page builds the list of saved addresses, with an edit and a delete form in each row, and the form that adds a new address. Smootify fills the country and province menus for you.

> [!NOTE]
> Customer accounts must be set up first: see [Customer accounts](https://www.smootify.io/docs/astro/build/account). Put these parts on an account page, since they need a logged-in customer.

## How it fits together

What Smootify needs:

- for the list: a `customer-addresses` element with one `customer-address` inside, the template of each row;
- for each form: a `<form>` with a `select` named `countryCode` (the country) and one named `zoneCode` (the province);
- the edit and delete forms inside the row, so they know which address they change.

What is up to you:

- the design of a row, and which details it shows;
- which fields the forms have, apart from the two `select` elements;
- where the forms go: in the row, in a popover inside the row, or in a section of their own for the new address.

## 1. List the addresses

1. Add a `customer-addresses` element.
2. Inside it, add a `customer-address` element. Design it as one row: Smootify repeats it once per address.
3. Inside the row, add an attribute to each text element that shows a part of the address.

```html
<customer-addresses>
  <customer-address>
    <div address="formatted">Name, street, city</div>
    <delete-address>
      <form><button type="submit">Delete</button></form>
      <div form-done hidden>Deleted</div>
      <div form-fail hidden>Something went wrong</div>
    </delete-address>
  </customer-address>
</customer-addresses>
```

| Attribute | What it shows |
|---|---|
| `address="formatted"` | the whole address, with the name, one line under the other |
| `address="name"` | the full name |
| `address="firstName"`, `address="lastName"` | the first name, the last name |
| `address="company"` | the company |
| `address="address1"`, `address="address2"` | the street, the second address line |
| `address="city"`, `address="zip"` | the city, the postal code |
| `address="zoneCode"`, `address="countryCode"` | the province and country codes, such as `CA` and `US` |
| `address="phoneNumber"` | the phone number |

**The default address.** The row of the customer’s default address gets the class `is-default`. Inside a row, `address-condition="default"` shows an element only on the default address, such as a “Default” pill, and `address-condition="not-default"` only on the others, such as a “Make default” button.

- **Write the values as in the table**, such as `firstName`. A value written with a dash, such as `first-name`, is not read.
- **Empty parts.** An element whose part of the address is empty is taken out of that row.
- **How many.** The list shows up to 10 addresses.
- **No addresses.** Show an empty state with `customer-condition="no-addresses"`, and hide a heading with `customer-condition="has-addresses"`.
- **The default address.** `customer="defaultAddress"` shows it anywhere on the page: see [Customer accounts](https://www.smootify.io/docs/astro/build/account).

For a visitor who is not logged in, the list removes itself. All the values are in [address values](https://www.smootify.io/docs/astro/reference/attributes/address).

## 2. The fields of an address form

The add form and the edit form use the same fields. Each field’s `name` tells Smootify what it holds. Write it exactly as shown here:

| Name | Field | What it holds |
|---|---|---|
| `firstName`, `lastName` | `input` | the first and last name |
| `company` | `input` | the company |
| `address1`, `address2` | `input` | the street and the second address line |
| `city`, `zip` | `input` | the city and the postal code |
| `phoneNumber` | `input` | the phone; Smootify removes its spaces |
| `countryCode` | `select` | the country (required) |
| `zoneCode` | `select` | the province or state |
| `defaultAddress` | `input` with `type="checkbox"` | makes this the default address when ticked |

When Shopify refuses an address, its message shows in the form’s `form-fail`.

**The country menu.** Smootify fills the `countryCode` `select` with the countries your store ships to, named in the site’s language and in alphabetical order. An option without a value that you write yourself, such as “Choose a country”, stays at the top. The customer must choose a country.

**The province menu.** When the customer picks a country, Smootify loads its provinces or states into the `zoneCode` `select`. The options you write in it are removed. Many countries have no provinces. Put the province menu and its label inside an element with `address-condition="zone"`, so they only show when they are needed:

| Country | Province menu (`zoneCode`) | Element with `address-condition="zone"` | Form |
|---|---|---|---|
| with provinces, such as United States | filled with its provinces or states | shown | no `no-zone` class |
| without provinces, such as Germany | empty, and still in the form | hidden | gets the class `no-zone` |

The `select` must stay in the form either way.

## 3. Add an address

Add a `create-address` element and put a `<form>` inside it, with the fields above. It can go on the same page as the list, or anywhere else.

```html
<create-address>
  <form>
    <input name="firstName">
    <input name="lastName">
    <input name="address1">
    <input name="city">
    <input name="zip">
    <select name="countryCode"><option value="">Choose a country</option></select>
    <div address-condition="zone"><select name="zoneCode"></select></div>
    <label><input type="checkbox" name="defaultAddress"> Use as my default address</label>
    <button type="submit"><span data-state="default">Save address</span><span data-state="loading">Saving…</span></button>
  </form>
  <div form-done hidden>Address saved</div>
  <div form-fail hidden>Something went wrong</div>
</create-address>
```

When the address is saved, `form-done` shows, and the page reloads a second later, so the list shows the new address.

## 4. Edit and delete in the row

**Edit.** Inside `customer-address`, add an `edit-address` element. Build its `<form>` like the add form, with the same fields. Smootify fills the fields with the address of that row, so the customer changes only what they need. When it is saved, the page reloads. Outside a row, the form has no address to fill in.

**Delete.** Inside `customer-address`, add a `delete-address` element, with a `<form>` and a submit button, as in the list above. It deletes the address of that row and removes the row.

- **The default address cannot be deleted.** Smootify removes the delete form from its row. To delete it, make another address the default first.
- **Changing the default.** The `defaultAddress` checkbox makes an address the default when it is ticked. Left unticked, the default address stays as it is.
- **A “Make default” button.** For a one-click button in the row, put an `edit-address` with only a hidden field and a submit: `<input type="hidden" name="defaultAddress" value="true">`. Without a Country field, the form changes only which address is the default and leaves every field of the address as it is. Show it with `address-condition="not-default"`.
- **In a popover.** The edit form can go in a popover inside the row. Each copy of the row gets its own popover.

## Where people get stuck

> [!STUCK]
> - **The address form disappears.** It has no `<form>`, or no `select` named `countryCode` or `zoneCode`. Both `select` elements are required, even when the province menu is hidden.
> - **A country is missing from the menu.** The menu lists only the countries your store ships to. Add the country to your shipping settings in Shopify.
> - **The edit form is empty.** It is outside `customer-address`, so it does not know which address to show.
> - **One row has no delete button.** It is the default address, which cannot be deleted.
> - **A value in the row stays empty.** It is written with a dash, such as `address="first-name"`. Write `address="firstName"`.
