Displaying an image from Supabase

Hi again everyone!

I know there’s a big update coming to the Supabase plugin and I’m super excited but I’m the meantime, here is my challenge. I would be grateful for any help :slight_smile:

I have figured out how to upload files to Supabase storage from the Weweb app I’m building. I am dealing with images in this particular case. More specifically, the idea is to have one image associated to each item of a collection, to be displayed when the “detail” page of that particular item is opened in Weweb.

How do I make that happen? What do I need to bind to the “Image” element for it to show the image from Supabase? I’ve read I should store the Supabase file path in the row of the item I am trying to display, which I figure I can do easily enough as part of the workflow I am using to upload the file to Supabase, but then what?

Thank you!

GD

Use the url of the image from your bucket instead !

Could you please expand on what you mean by that? Thanks!

Let’s say you have a product table , one columns could be an image and the field value would be the url of the full irl of your image if hosted on Supabase it’s in the bucket
Then in Supabase when you a value from collection for a image component you would choose the url fetched

Hey Zach, thanks for the reply! I understand what you’re saying conceptually and that’s the approach I would take, except I can’t figure out where to get a stable url for the hosted image/file. The “Get URL” button in the following capture only offers options for URLs that expire, and I don’t even know how to access that via WeWeb. Any further pointers you can offer? Thanks!

1 Like

You should be able to get the public url by right clicking the resource. I know there is also a way to construct the url by yourself by concatenating the parameters, but I don’t have that on hand rn.

Hi,

I know some users are using a js snippet to generate this URL, still, it will have an expiration date.

const { data } = await wwLib.wwPlugins.supabase.instance
  .storage
  .from('<bucket-name>')
  .createSignedUrl('folder/avatar1.png', 60)

In data you will have a working url for a given file.

Hello @gduteaud,

It will depend on the configuration of your bucket

If you have a public bucket, you will need to use this formula:

return wwLib.wwPlugins.supabase.settings.publicData.projectUrl+"/storage/v1/object/public/bucket_name/file_name.extension"

If you have a private bucket you will need to use this code:

const {data, error} = await wwLib.wwPlugins.supabase.instance
  .storage
  .from('bucket_private_name')
  .download('file_name.extension')

if (error)  throw error

  const link = document.createElement("a");

  link.href = URL.createObjectURL(data);
  link.download = file_name.extension;

  document.body.appendChild(link);

  link.dispatchEvent(
    new MouseEvent('click', { 
      bubbles: true, 
      cancelable: true, 
      view: window 
    })
  );

Thanks Mael, and what do I need to do with this code? I tried copy-pasting it in the image element binding, changing it from formula to Javascript, and replacing ‘bucket_private_name’ with the bucket name and ‘file_name.extension’ with the file name, but it’s not working.

You actually need to paste this in a workflow action block, custom javascript. Then once this action is completed, you will be able to access the URL in the responses/results tab (the one with a lightning bolt)

Thanks for the pointer.

I set up a workflow triggered on mouse enter on the container that hosts the image object. This is the JS snippet I used (the one @Mael provided was triggering a download, which is not what I’m trying to do):

const { data, error } = await wwLib.wwPlugins.supabase.instance
  .storage
  .from('photos')
  .download('78a414b4-fd59-429a-9e0a-96d90b563a97_1701304273563.jpg');

if (error) throw error;

// Get the URL without triggering a download
const downloadUrl = URL.createObjectURL(data);

// Now you can use 'downloadUrl' as needed in your code
console.log('Download URL:', downloadUrl);

// If you want to do something else with the URL, you can return it or use it accordingly
return downloadUrl;

Then the next action in the workflow updates a “imageURL” variable to the returned url.

It works but it’s kinda janky, surely there’s a better way to do this that loads the image when the page is opened instead?

You can go to your Page in the

Pages section → Desired Page → Gear icon → Workflows

There you can choose, when to trigger the workflow to run (Page Load, App Load etc…), then based on the parameters, for each page you can fetch your images, and add them to an array, or whatever logic you use and then just display - bind them.

for the URL only, instead of download you can use the code @Alexis provided.

or if your bucket is public, you can construct the public URL yourself, without the need to do all this JS in the first place.

THANK YOU! I think that’s finally all the pieces I needed.

This is what my workflow looks like on page load. The first action looks up the file path of the item to display via the item uuid that’s passed in the url, which is then used in the code snippet provided by Alexis (second action), and finally the third action sets a variable to the obtained URL. The variable is bound to the image element on the page.

image

It works but it’s a bit slow, there’s a noticeable delay between the page load and the image actually showing up.

EDIT: just kidding, it’s actually not working anymore. It was fine as of writing the post but it stopped working. I thought it might be because I was testing with the actualy file path string of my test photo in the js snippet and I replaced that with the output of the first action but it’s not even working when I put back the actual file path now. Not sure if this has to do with the url expiring or what.

EDIT 2: this seems to be causing an error in the js snippet:

.createSignedUrl('context.workflow['573eb89d-3efb-4d35-a03c-0736a4fafec9'].result', 60)

Probably because of the nested single quote marks. What’s the correct syntax for this?

Stil doesn’t work even with the actual url though so there must be another issue on top of that.

Edit: for the error, you need to remove the single quotes, the variable you’re using is most likely already of a type string (hopefully). Also you need to pass the path, not just the name, just saying.

so let’s say your URL parameter is the name of the image or whatever, you could skip the first step entirely, and just go and get the variable like this,

// Define your path variable via let
let path = 'folder_name/' + [your_query_parameter] 
// will return smth like .. 'my_folder/my_file.png' if the query parameter is 'my_filename.png'

then you just pass in the same file, the path variable into Alexis’ code

.createSignedUrl(path, 60)

this needs to be the same code block, be careful about that!

Yeah, it’s an async function, and it’s basically Your site ↔ Supabsase, so there is some latency.
You can

  1. Display skeleton/loader before the images get the signed URLS,
  2. Save the public URLs / construct them at the time of load, then you’ll either have to wait for only one DB fetch

Hey guys. Love this good comments. and nice solutions. do you know if there have been a easier way. where a custem javascript is not needed?

You should be able to make this happen with the Supabase plugin only now

1 Like

I think you are correct. Nut i still would like to see some kind of guide some place.