# Shopify app frontends  Gadget offers a comprehensive toolkit for quickly constructing frontends for Shopify Apps. When connecting a Gadget app to Shopify, it automatically includes a basic, hosted frontend powered by Vite. This frontend comes preloaded with support for OAuth, Shopify's Polaris design system, multi-tenant data security, and integration with Shopify's App Bridge for embedded applications. You have the flexibility to customize this frontend according to your preferences, or you can create an entirely new external frontend from scratch using Gadget's React packages. Frontends for Shopify apps interact with Gadget backends through the GraphQL API specific to your Gadget app, along with the corresponding JavaScript client for your application. To work with Gadget from a Shopify app frontend, there are several npm packages that are essential: | Package | Description | Available from | | --- | --- | --- | | `@shopify/app-bridge` | Shopify's React package for embedding React applications within the Shopify Admin | [npm](https://www.npmjs.com/package/@shopify/app-bridge) | | `@gadget-client/example-app` | The JS client for your specific Gadget application | [Gadget NPM registry](https://docs.gadget-canary.xyz/api/example-app/development/installing) | | `@gadgetinc/react` | The Gadget React bindings library, providing React hooks for making API calls | [npm](https://www.npmjs.com/package/@gadgetinc/react) | | `@gadgetinc/react-shopify-app-bridge` | The Gadget Shopify wrapper library for Shopify Embedded App setup and authentication | [npm](https://www.npmjs.com/package/@gadgetinc/react-shopify-app-bridge) | Gadget installs these packages into your Gadget-hosted frontend automatically, but if you're building an [external frontend](https://docs.gadget-canary.xyz/guides/frontend/external-frontends) you must install them yourself. Once you've set up your [Shopify connection](https://docs.gadget-canary.xyz/guides/plugins/shopify), your Gadget app will have a built-in frontend ready for construction in your app's `frontend` folder. This frontend can access data from your backend, including both models synced from Shopify and models created within your application. By default, your app uses React and Shopify's standard `@shopify/app-bridge-react` library, so Shopify's normal helpers for navigation and data fetching are ready for use as well. Gadget frontends for Shopify include Shopify's design system Polaris via the `@shopify/polaris` package as well, so your app is compliant with Shopify's App Store guidelines out of the box. If you'd like to build your frontend outside of Gadget, refer to the [external frontends](https://docs.gadget-canary.xyz/guides/frontend/external-frontends) guide. ## Reading data from your backend  To facilitate easy access to data from your Gadget application, including both the non-rate-limited copies of Shopify models and your custom models, you can leverage the @gadgetinc/react hooks library in your frontend. This library provides a set of hooks, such as `useFindOne`, `useFindMany`, and `useFindFirst`, specifically designed for fetching data from your Gadget app. When utilizing these hooks, each one returns an object that includes the requested data, the current fetching state, and an error object if any error occurred during the data retrieval process. Additionally, the returned object includes a refetch function that allows you to refresh the data if needed. By using the provided hooks from the `@gadgetinc/react` library, you can easily fetch and manage data from your Gadget app within your frontend code. These hooks simplify the process of data retrieval, provide relevant states and error handling, and offer a convenient mechanism for refreshing the data when necessary. For example, if you have the **Shopify Product** model enabled in your Connection, we can fetch product records in a variety of ways: ```typescript // fetch one product by id const [{ data, fetching, error }, refetch] = useFindOne(api.shopifyProduct, "10"); ``` ```typescript // fetch the first 10 products const [{ data, fetching, error }, refetch] = useFindMany(api.shopifyProduct, { first: 10, }); ``` ```typescript // fetch the first product with the title field equal to "Socks", throw if it isn't found const [{ data, fetching, error }, refetch] = useFindFirst(api.shopifyProduct, { where: { title: "Socks" }, }); ``` ```typescript // fetch the first product with the title field equal to "Socks", return null if it isn't found const [{ data, fetching, error }, refetch] = useMaybeFindFirst(api.shopifyProduct, { where: { title: "Socks" }, }); ``` Data from other models that you've created in your application is accessed the same way. For example, if we're building a free shipping banner app, you might create a **Banner** model that stores details about each shipping banner created. We can fetch banner records with the same React hooks: ```typescript // fetch one banner by id const [{ data, fetching, error }, refetch] = useFindOne(api.banner, "10"); ``` ```typescript // fetch the first 10 banners const [{ data, fetching, error }, refetch] = useFindMany(api.banner, { first: 10 }); ``` Each of these hooks must be wrapped in a React component to render. For example, we can use `useFindMany` to display a list of products in a component: ```tsx import { useFindMany } from "@gadgetinc/react"; import { api } from "../api"; export const ProductsList = () => { const [{ data, fetching, error }, _refetch] = useFindMany(api.shopifyProduct, { first: 10, }); if (fetching || !data) { return
Loading...
; } if (error) { return
Error: {error.message}
; } return ( ); }; ``` For more on reading data in the frontend, see the [building frontends](https://docs.gadget-canary.xyz/guides/frontend) guide and the [@gadgetinc/react reference](https://docs.gadget-canary.xyz/reference/react). ### Shopify permissions  Gadget incorporates multi-tenant data permissions as the default configuration for your application. By default, an app loaded for a specific Shopify shop can only access data within that particular shop and is not authorized to access data from other shops. This default setup utilizes the **Shopify App User role** for enforcing these permissions, and you have the flexibility to customize the permissions for this role on the Roles & Permissions page. In Gadget, multi-tenant data permissions are automatically enforced for Shopify models. However, access to your own models is not automatically granted. To enable frontend access to your models, you need to assign permissions to the **Shopify App User** role for each model you wish to make accessible. For instance, if you want to access a model named Banner, you can navigate to the Roles & Permissions screen and select the Read permission checkbox for the Banner model. For further guidance and details on managing access control, refer to the [access control guide](https://docs.gadget-canary.xyz/guides/access-control), which provides comprehensive information on configuring and customizing data permissions in Gadget. ## Writing data back to your backend  Shopify app frontends can use the `useActionForm`, `useAction` and `useGlobalAction` hooks from the `@gadgetinc/react` hooks library to write data back to your database. To update data within Shopify, you must make an API call to Shopify directly from your **backend**. See the section for more information. To write data back to your database for models you've created, or fields you've added to Shopify Models, use `useActionForm`, `useAction` or `useGlobalAction` hook in a React component. For example, if we create a new model within our app called `banner`, we can use the `useActionForm` hook to create a form for new banner records: ```tsx import { useActionForm } from "@gadgetinc/react"; import { api } from "../api"; export const CreateBannerForm = () => { const { register, submit, formState: { isSubmitting }, error, } = useActionForm(api.banner.create); if (isSubmitting) { return
Saving...
; } if (error) { return
Error: {error.message}
; } return (