Accessing database in Remix theme app extension

Hey, I have a Shopify typescript app that uses the theme app extension. It is an app embed, which basically shows a popup on the online store. Now my data for the styling and the text for that popup is stored in my prisma database table. How do I access it from the database? I tried making an API and calling it but that return a 401 unauthorized error so I cant directly access the database. I have a feeling am doing it wrong and there is a more shopify way to do it. Can anyone guide me?

There’s two ways of doing this.

  1. App Proxy - This allows you to make a call to your database via your app. I believe you’re getting a 401 because you’re using const { admin } = await shopify.authenticate.admin(request); to authenticate incoming request instead of using const {storefront, liquid} = await authenticate.public.appProxy(request);, but I’m not a Remix expert so I would recommend double checking this.

  2. Metafields. If you’re only storing styling options, a better way to do it would be storing a JSON in metafields that you can read from since this will be faster. If you’re taking this route, keep a backup of content in your database just in case something goes wrong.

Based on your context I would go the metafield route. Here’s an example:

const shopDetails = await client.request(
  `{
        shop {
            id
        }
      }`,
);

const shopId = shopDetails.data.shop.id;

const write_shipping_metafield = await client.request(
  `
    mutation CreateAppDataMetafield(
    $metafieldsSetInput: [MetafieldsSetInput!]!
    ) {
        metafieldsSet(metafields: $metafieldsSetInput) {
            metafields {
                key
                ownerType
                type
                value
                namespace
            }
            userErrors {
                field
                message
            }
        }
    }`,
  {
    variables: {
      metafieldsSetInput: [
        {
          ownerId: shopId,
          namespace: "namespace",
          key: "key",
          value: JSON.stringify({...styling_options}), //<-- Your styling JSON goes here
          type: "json",
        },
      ],
    },
  },
);

Then you can read from the metafield like this:

{% assign styling_options = shop.metafields.namespace.key.value %}
<button class="{{ styling_options.button.primary }}">Primary button</button>
1 Like

Okay so that does makes sense a little but I haven’t researched on metafields much so I can’t tell. But are you suggesting that instead of storing this data in a database I store it in metafields which can then be accessed on the storefront and used in the extension?
Can I do it such that I store them in the database which in turn stores them in the metafields which is used on the storefront?

As of now my data is stored in a field (json which is string wrapped) in the session table. So authenticating on the admin part hasn’t been difficult but I am struggling Authenticating on the frontend.

I would recommend storing in metafields AND in your database as a backup, just in case something goes wrong since metafields can be overwritten manually and by other apps. Storing styling in an app owned metafield makes little sense (to me), so in case your metafield is tampered with, you can make an API call and restore actual data from your db.

I would highly recommend researching into metafields to being with, but please do not store any API secrets in them

Oh okay makes sense, so now I have set up the metafield. Can I just access it directly from the liquid file? Or do I need any further access or authentication?

You can now directly access the metafield from your extension like any other metafield and you’re good to go!

Man, you are such a lifesaver. My app works exactly as expected, and it is so much simpler now. I owe you a lot. Thanks a lot. I am stuck with an app bridge problem that has been unanswered for the past few days. If you can help me with that as well, that would be great.

Also, I want to show variable content on the liquid block depending on the site visitors geolocation. Can you guide me on what the best way to do this is?