> For the complete documentation index, see [llms.txt](https://docs.buildnatively.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildnatively.com/guides/integration/app-storage.md).

# App Storage

## What is App Storage?

App Storage lets your app save data directly on the user's device using a native key-value store. Unlike browser localStorage, stored values persist across app sessions and are not cleared when the browser cache is cleared. This makes it useful for storing user preferences, session tokens, onboarding state, or any other data that needs to survive app restarts.

{% hint style="warning" %}
Storing values larger than 1.42MB in a single write may cause the app to crash. Keep individual values small and split large data across multiple keys if needed.
{% endhint %}

## Prerequisites

{% hint style="success" %}
This feature is available in all plans. [See all plans](/getting-started/subscription-plans.md)
{% endhint %}

## Implementation

Choose your integration method below: **Bubble.io Plugin** (No-Code), **JavaScript SDK** (Code), or **AI Agents** (for AI-powered editors like Lovable, Base44, and Replit).

### Initialization

{% tabs %}
{% tab title="Bubble.io Plugin" %}
**Check Plugin**

Before starting, verify if the Natively plugin is already installed in your Bubble project.

1. Open your Bubble editor and navigate to the Plugins tab in the left sidebar.
2. **Check Installed Plugins:** Look through your list of installed plugins for "Natively iOS & Android app builder".
   * If it IS installed: Check the version number. If an update is available (e.g., you see a button saying "Update"), click it to ensure you have the latest features and bug fixes.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FmfnSUug82IdnxOAoBrak%252Fnatively_app_builder_bubble_plugin_update.png%3Falt%3Dmedia%26token%3Dc193f69f-b03b-4be4-b80b-f34ba37ac212&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=a89e4510&#x26;sv=2" alt=""><figcaption></figcaption></figure>

* If it is NOT installed: Click the + Add plugins button, search for "Natively", and click Install.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FC5rA42yQHcN1uGKFbzmF%252Fnatively_app_builder_bubble_plugin.png%3Falt%3Dmedia%26token%3Dd9706d9b-dbe8-459b-b9b3-5667648aa4b7&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=9aae2297&#x26;sv=2" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="JavaScript SDK" %}
**Check SDK**

Before writing any logic, ensure the Natively SDK is correctly installed and up-to-date in your codebase.

1. Open your project's main HTML file (or header settings) and look for the Natively script tag inside the `<head>` section.
2. Install/Update: If missing or outdated, add the following code. You can specify the SDK version in the URL (e.g., `@2.26.0`).

```javascript
<head>
  <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script>
</head>
```

{% hint style="info" %}
To ensure you are using the most up-to-date version, check the [Natively GitHub releases page](https://github.com/buildnatively/js-sdk/releases) for the latest version number.
{% endhint %}
{% endtab %}

{% tab title="AI Agents" %}
**Initialize the SDK**

AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features. Before implementing any feature, the Natively SDK must be initialized in your project.

Copy the line below and paste it into your AI agent to check and set up the Natively SDK in your project.

```
Check if the following Natively SDK script is present in the <head> of index.html. If missing or outdated, add it: <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script><script>function nativelyOnLoad() { window.natively.setDebug(true); console.log("✅ Natively SDK loaded successfully."); }</script> For reference: https://docs.buildnatively.com/guides/integration/how-to-get-started https://github.com/buildnatively/js-sdk/releases
```

{% endtab %}
{% endtabs %}

### Setup Logic

{% tabs %}
{% tab title="Bubble.io Plugin" %}

#### \[Element] Natively - Storage

#### Events:

* **Storage value received** - fires when a value is successfully retrieved by key.

#### States:

* **Latest requested storage value** - the value returned for the most recently requested key.
* **Latest requested storage key** - the key used in the most recent request.

#### Actions:

* **Store value to device storage** - saves a value under the specified key:
  * key - the identifier for the stored value;
  * value - the data to store.
* **Get value from device storage** - retrieves a value by key. Listen to the **Storage value received** event to access the result:
  * key - the identifier to look up.
* **Remove value from device storage** - deletes a specific key and its value:
  * key - the identifier to remove.
* **Reset device storage** - clears all data stored by your app.
  {% endtab %}

{% tab title="JavaScript SDK" %}

```javascript
// ============================================================================
// NATIVELY APP STORAGE - DOCUMENTATION & EXAMPLES
// ============================================================================

// Initialize
const storage = new NativelyStorage();

// ============================================================================
// ALL AVAILABLE METHODS
// ============================================================================
// storage.setStorageValue(key, value)
//   - Saves a value under the specified key.
//   - key: string - the identifier for the stored value
//   - value: string - the data to store
//   - No callback required.
//
// storage.getStorageValue(key, callback)
//   - Retrieves a value by key.
//   - key: string - the identifier to look up
//   - Returns the value via callback.
//
// storage.removeStorageValue(key)
//   - Deletes a specific key and its value.
//   - key: string - the identifier to remove
//   - No callback required.
//
// storage.resetStorage()
//   - Clears all data stored by your app.
//   - No callback required.

// ============================================================================
// CALLBACK RESPONSE FIELDS
// ============================================================================
// resp.key   - The key that was requested.
// resp.value - The stored value. Returns null if the key does not exist.

// --- App Storage. Store and Retrieve Example. Start ---

const key = "user_preference";
const value = "dark_mode";

// Store a value
storage.setStorageValue(key, value);

// Retrieve a value
const get_storage_callback = function(resp) {
    if (resp.value === null) {
        console.log("No value found for key:", resp.key);
        return;
    }
    console.log("Retrieved value:", resp.value);
};

storage.getStorageValue(key, get_storage_callback);

// --- App Storage. Store and Retrieve Example. End ---


// --- App Storage. Remove and Reset Example. Start ---

// Remove a specific key
storage.removeStorageValue(key);

// Clear all stored data
storage.resetStorage();

// --- App Storage. Remove and Reset Example. End ---
```

{% endtab %}

{% tab title="AI Agents" %}
AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features.&#x20;

Copy the line below and paste it into your AI agent.&#x20;

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively App Storage SDK: const storage = new NativelyStorage(); // storage.setStorageValue(key, value) — saves a value under the specified key. No callback required. // storage.getStorageValue(key, callback) — retrieves a value by key. resp.key: the requested key. resp.value: the stored value, null if key doesn't exist. // storage.removeStorageValue(key) — deletes a specific key and its value. No callback required. // storage.resetStorage() — clears all data stored by your app. No callback required. For reference: https://docs.buildnatively.com/guides/integration/app-storage
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Save the user's selected language preference to device storage and load it automatically on app start".
{% endhint %}
{% endtab %}
{% endtabs %}

### How to use

#### Persisting user preferences

Use App Storage to save user settings like theme (light/dark), language, notification preferences, or any other configuration that should persist between sessions. Store the value on change and retrieve it on app load to restore the user's last state.

#### Session and authentication tokens

App Storage is a good place to store session tokens or lightweight authentication data that needs to survive app restarts. Unlike browser localStorage, this data won't be wiped when the browser cache is cleared.

#### Onboarding and first-run state

Store a flag like `onboarding_complete: true` after a user finishes onboarding. On app load, check this value to decide whether to show the intro screens or go straight to the main app.

#### Always handle the null case

If you request a key that doesn't exist, `resp.value` returns `null`. Always check for this before using the value - especially on first launch, before any data has been stored.

#### Keep values small

App Storage is designed for lightweight key-value data. Storing values larger than 1.42MB in a single write may cause the app to crash. If you need to store larger data, split it across multiple keys or consider a different storage approach.

#### Keys are strings only

Both keys and values must be strings. If you need to store objects or arrays, serialize them with `JSON.stringify()` before storing and parse with `JSON.parse()` after retrieving.

## Troubleshooting

<details>

<summary><code>resp.value</code> returns <code>null</code></summary>

The key does not exist in storage yet. This is expected on first launch or if the key was never set. Always check for `null` before using the retrieved value.

</details>

<details>

<summary>Stored value not persisting between sessions</summary>

Make sure you are using `storage.setStorageValue()` and not browser localStorage - localStorage can be cleared by the system or the user. If the value is being set correctly but not retrieved after a restart, verify the key name is exactly the same in both the set and get calls.

</details>

<details>

<summary>App crashes when storing a value</summary>

The stored value likely exceeds the 1.42MB limit for a single write. Split the data across multiple smaller keys or reduce the size of the value being stored.

</details>

<details>

<summary><code>resetStorage()</code> cleared data I didn't expect</summary>

`resetStorage()` clears all data stored by your app - not just a specific key. Use `removeStorageValue(key)` if you only want to delete a specific entry.

</details>

<details>

<summary>Storing objects or arrays doesn't work</summary>

App Storage only supports string values. Serialize objects with `JSON.stringify()` before storing and deserialize with `JSON.parse()` after retrieving.

</details>

[^1]: Replace this placeholder
