# Getting Started

The **Limio SDK** is a React library that gives your custom components access to everything they need — offers, basket operations, user data, subscriptions, checkout state, and more. You import hooks like `useCampaign` or `useBasket`, and the platform injects the live data at runtime.

{% hint style="info" %}
You don't need to set up API calls, authentication, or state management yourself. The SDK handles all of that behind the scenes.
{% endhint %}

***

## What can you build?

Most Limio components fall into one of these categories:

| Component type              | SDK hooks you'll use                           | Examples                                        |
| --------------------------- | ---------------------------------------------- | ----------------------------------------------- |
| **Offer / pricing cards**   | `useCampaign`, `useBasket`                     | Display plans, let users add to basket          |
| **Cart and checkout UI**    | `useBasket`, `useCheckout`                     | Show basket contents, order totals, promo codes |
| **Account pages**           | `useUser`, `useSubscriptions`                  | Display profile, active subscriptions           |
| **Billing and invoices**    | `useUserAccountInformation`, `useUserInvoices` | Show invoices, payment info, account balances   |
| **Subscription management** | `useSubscriptions`, `useBasket`                | Change plan, cancel, update add-ons             |

***

## Install the SDK

The SDK is listed as a peer dependency — Limio provides it at runtime. Add it so your editor and bundler can resolve the types:

```
npm install --save @limio/sdk

# or

yarn add @limio/sdk
```

{% hint style="warning" %}
Do **not** bundle `@limio/sdk` into your component output. It must remain an external/peer dependency so the platform can inject the correct version at runtime.
{% endhint %}

***

## Your first component — an offer card

Here's a minimal component that reads the offers configured for the current page and lets the user add one to the basket:

```tsx
import React from "react"
import { useCampaign, useBasket } from "@limio/sdk"
import { getCurrentBasketId } from "@limio/shop/src/shop/checkout/basket"

const OfferCards = () => {
  const { offers = [] } = useCampaign()
  const { initiateCheckout, addOfferToBasket, basketLoading } = useBasket()

  const handleSelect = async (offer) => {
    const checkoutId = getCurrentBasketId()

    if (!checkoutId) {
      await initiateCheckout({ order: { orderItems: [{ offer, quantity: 1 }] } })
    } else {
      await addOfferToBasket({ offer, quantity: 1 })
    }
  }

  return (
    <section>
      {offers.map((offer) => {
        const attrs = offer.data.attributes

        return (
          <div key={offer.id}>
            <h2>{attrs.display_name__limio}</h2>
            <p>{attrs.display_price__limio}</p>
            <button disabled={basketLoading} onClick={() => handleSelect(offer)}>
              {attrs.cta_text__limio || "Subscribe"}
            </button>
          </div>
        )
      })}
    </section>
  )
}

export default OfferCards
```

**What's happening here:**

1. `useCampaign()` returns the `offers` array configured for the current Limio page
2. `useBasket()` gives you the methods to add items to the basket
3. Each offer's display data lives under `offer.data.attributes` — things like `display_name__limio`, `display_price__limio`, and `cta_text__limio`
4. `initiateCheckout` creates a new basket; `addOfferToBasket` adds to an existing one
5. `basketLoading` is `true` while an async basket operation runs — use it to disable buttons and prevent double-clicks

***

## Accessing offer attributes

Every offer carries its configuration under `offer.data.attributes`. The most common fields:

| Attribute                    | Description                                                  |
| ---------------------------- | ------------------------------------------------------------ |
| `display_name__limio`        | The offer's display name                                     |
| `display_price__limio`       | Formatted price string (e.g. `"$29/mo"`)                     |
| `display_description__limio` | Short description text                                       |
| `offer_features__limio`      | Rich HTML string listing features                            |
| `cta_text__limio`            | Call-to-action button text                                   |
| `price__limio`               | Array of charge objects with `value`, `currencyCode`, `type` |
| `group__limio`               | Group label for grouping offers into tabs or sections        |

{% hint style="info" %}
Use `sanitiseHTML` from the SDK when rendering `offer_features__limio` or any rich-text attribute to prevent XSS:

```javascript
import { sanitiseHTML } from "@limio/sdk"

<div dangerouslySetInnerHTML={{ __html: sanitiseHTML(attrs.offer_features__limio) }} />
```

{% endhint %}

{% hint style="info" %}
When running locally in the Storybook playground, the SDK automatically populates hooks with sample data so you can develop without a live Limio environment.
{% endhint %}

For setting up your component repo, local Storybook development, configurable props, and deploying to Limio, see the [Custom Components](/developers/custom-components/custom-components.md) guide.

***

## Common patterns

### Loading and error states

Wrap your component with `ErrorBoundary` and provide a `Skeleton` for Suspense:

```tsx
import React, { Suspense } from "react"
import { ErrorBoundary } from "@limio/sdk"

const MyComponent = () => {
  // ... your component logic
}

MyComponent.Skeleton = () => (
  <div className="skeleton-placeholder">Loading...</div>
)

const MyComponentWrapper = (props) => (
  <ErrorBoundary fallback={<p>Something went wrong.</p>}>
    <Suspense fallback={<MyComponent.Skeleton />}>
      <MyComponent {...props} />
    </Suspense>
  </ErrorBoundary>
)

export default MyComponentWrapper
```

### Page Builder detection

Use `useLimioContext` to detect when your component is rendering inside the Page Builder. This is useful for showing placeholder content during editing:

```tsx
import { useLimioContext, useCampaign } from "@limio/sdk"

const OfferCards = () => {
  const { isInPageBuilder } = useLimioContext()
  const { offers = [] } = useCampaign()

  if (isInPageBuilder && offers.length === 0) {
    return <p>Offer cards will appear here once offers are configured.</p>
  }

  return /* ... */
}
```

***

## SDK reference

For full details on each hook, see the dedicated pages:

{% content-ref url="/pages/cJa6jvpldLRIrNjA4hBf" %}
[Page, Offers & Add-Ons](/developers/limio-sdk/page.md)
{% endcontent-ref %}

{% content-ref url="/pages/lv6dFcpThWC5a0cOuNkH" %}
[Basket (Cart)](/developers/limio-sdk/basket.md)
{% endcontent-ref %}

{% content-ref url="/pages/Me23pN3eZxhDmJlbIjnH" %}
[Checkout](/developers/limio-sdk/checkout.md)
{% endcontent-ref %}

{% content-ref url="/pages/QSUIfUKonEPK7Y8j1Vh4" %}
[User & Subscriptions](/developers/limio-sdk/user.md)
{% endcontent-ref %}

{% content-ref url="/pages/SOy5dzXyvw5sFSYaxFq3" %}
[Billing & Account](/developers/limio-sdk/billing-account.md)
{% endcontent-ref %}

{% content-ref url="/pages/wdwkcNUsLMYQZTiBDz2p" %}
[Update Subscription](/developers/limio-sdk/subscription-update-checkout.md)
{% endcontent-ref %}

{% content-ref url="/pages/YPGVy7X0AcEf4QbMPQ9M" %}
[Advanced Methods](/developers/limio-sdk/advanced-methods.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.limio.com/developers/limio-sdk/getting-started.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
