# Polishing and sharing your extension

Built an extension, and ready to share it? 🎉 This guide is for you! Here’s some things to check to get your extension polished and production ready.

## Permissions

Users of an extension have the same permissions in the extension as they do in the Airtable base. This means
that trying to perform an action that they can’t do in the base (for example, deleting a record as a read-only
collaborator) will throw an error.

-   When writing back to Airtable (to records or [`GlobalConfig`](https://airtable.com/developers/extensions/api/models/globalconfig.md)), first check that the
    user has permission to perform that action. The "Permissions" section of
    [this guide](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md#permissions) covers how to do this in detail.
    -   Note: only users with editor or above permission can update `GlobalConfig`.
-   Consider disabling the relevant UI when a user cannot perform a given action.
-   `checkPermissionsFor` helpers return a `reasonDisplayString` when a user doesn't have permission to perform the
    action. You can show this to the user to explain why.
-   When developing an extension, you can preview the extension with different permission levels using the “Advanced” tab.

## Settings

We recommend storing user settings in [`GlobalConfig`](https://airtable.com/developers/extensions/api/models/globalconfig.md), which is is a key-value store persisted
for each extension installation. It's unique per extension installation, but shared across all users of that extension installation.

-   Remove hard-coded references to models (e.g. field names) and allow users to configure them. We recommend using
    our picker components ([`TablePicker`](https://airtable.com/developers/extensions/api/ui/components/tablepicker.md),
    [`ViewPicker`](https://airtable.com/developers/extensions/api/ui/components/viewpicker.md), [`FieldPicker`](https://airtable.com/developers/extensions/api/ui/components/fieldpicker.md)) or their synced
    variants (e.g. [`TablePickerSynced`](https://airtable.com/developers/extensions/api/ui/components/viewpickersynced.md)). The `Synced` variants automatically save
    the model ids to `GlobalConfig`.
-   Add a settings screen where users can configure the extension and surface it to users with the
    [`SettingsButton`](https://airtable.com/developers/extensions/api/models/settingsbutton.md) API. This displays a settings gear icon outside of the extension's frame.
-   Watch for updates to settings with the [`useGlobalConfig`](https://airtable.com/developers/extensions/api/ui/hooks/useglobalconfig.md) hook.
-   If you anticipate multiple users interacting with the same extension installation simultaneously, be mindful of where and
    how `GlobalConfig` gets updated—especially if using `Synced` components like `TablePickerSynced`.
-   Check that your extension works as expected without any settings. To test this, you can clear your development extension's
    `GlobalConfig` from the extension developer tools.

## Interacting with the base

The schema of an Airtable base can change in real-time as your extension is being used: tables can be renamed and fields
can be deleted or change types.

-   Watch the base for schema changes with the [`useBase`](https://airtable.com/developers/extensions/api/ui/hooks/usebase.md) hook.
-   Use `ifExists` variants of functions that fetch models (eg.
    [`Base#getTableIfExists`](https://airtable.com/developers/extensions/api/models/base.md#getTableByIdIfExists)) to gracefully handle model deletion. (The plain
    variants throw an error when trying to get something that doesn’t exist, whilst these return `null`.)
-   Use ids instead of names when working with tables, views, and fields to handle renames smoothly.
-   If your extension requires a certain setup to work (e.g. a specific type of field), check for this and render an empty
    state or your settings screen.

## Watching for changes

Check you’re using the right hooks so that your extension re-renders when it needs to, and isn’t using outdated data.
See the ["Watching data" section of this guide](https://airtable.com/developers/extensions/guides/read-data-from-airtable.md#watching-data) for more details.

-   Keep your extension up-to-date with the [`useGlobalConfig`](https://airtable.com/developers/extensions/api/ui/hooks/useglobalconfig.md) and
    [`useBase`](https://airtable.com/developers/extensions/api/ui/hooks/usebase.md) hooks when relying on those models.
-   Watch for changes to the user's permission level with the [`useSession`](https://airtable.com/developers/extensions/api/ui/hooks/usesession.md) hook: this is
    important if your extension performs writes and renders UI based on permission checks.

## API keys and other credentials

Check that you haven’t hard-coded any credentials into your extension. For non-sensitive credentials, we recommend allowing
users to input them and storing them in `GlobalConfig`.

## Limit what record data is loaded

Airtable bases can contain a lot of records. If your extension loads record data, consider specifying fields in
[`RecordQueryResultOpts`](https://airtable.com/developers/extensions/api/recordqueryresultopts.md#fields) to only load the fields you need into the extension.

## Write limits

We enforce size and rate limits on writes back to Airtable from an extension. See
[this guide](https://airtable.com/developers/extensions/guides/write-back-to-airtable.md#size-limits-rate-limits) for details and a snippet showing how to split
updates to stay under the limits.

## Publish your extension to the marketplace

If you’d like to share your extension with the Airtable community, please [submit it to the Airtable marketplace](https://airtable.com/developers/extensions/guides/submit-to-marketplace.md). After reviewing your extension for functionality and security, we’ll publish it to the overall extensions Marketplace, so that other Airtable users can install it directly into their bases.

## Open-source you extension

If you’d like to keep your block open-source and help other Airtable developers learn from your work, please [submit your open source block](https://airtable.com/shrVsXvCPy0ajfk5C) and we’ll list it on our [examples page](https://airtable.com/developers/extensions/examples).
