Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Trouble With Media Items

default discord avatar
schwig2 months ago
20

Hello, I'm genuinely at a loss and really need some guidance. I'm pretty sure most of my issues are from using the Starter Website Template instead of building my site up from scratch, but when I first started this project figured skipping some of the tedious steps would've been worth my time. I've gotten the site to the point where I want to get images working properly. Right now the site is up and I can see the content, but I can't fetch images from my Cloudflare R2.



I'm using the S3 Plugin as I've seen mentioned in tutorials and it is properly uploading the images from the Admin Panel. The trouble comes when the site tries to find the appropriate images, it's still trying to find the images in local storage. I'm using Vercel from my deployments, so I need to figure out where to make any changes to the Template code to allow it to find me R2 and ignore local storage properly.



Apologies if this is a duplicate issue or in the wrong sectio. Thank you in advance for any help.

  • discord user avatar
    seanzubrickas
    2 months ago

    Hey

    @175753360740319233

    can you clarify, are you using the AWS S3 plugin or the Cloudflare R2 plugin?

  • default discord avatar
    schwig2 months ago

    The S3 plugin.


    Most of the write-ups or tutorials I came across suggested using it over the R2 plugin.



    @364562745447940099
  • discord user avatar
    seanzubrickas
    2 months ago

    Ok, just wanted to make sure as you mentioned both in your message



    so you have an Amazon S3 bucket and all your credentials in your env file?



    S3_BUCKET = the name of the bucket you created in AWS
    S3_ACCESS_KEY_ID = from AWS IAM → Users → Security credentials → Access keys
    S3_SECRET_ACCESS_KEY = shown once when creating the access key, can't be retrieved after
    S3_REGION = wherever your bucket was created (us-east-1, eu-west-1, etc.)
  • default discord avatar
    schwig2 months ago

    My bucket is an R2 on Cloudfare, but yes all my credentials are in my env file and I have the plugin configured using them.



    I'll admit some of the guides and write-ups I used were a little older, so if the R2 plugin is more mature than mentioned in those articles/videos I can give it a try.

  • discord user avatar
    seanzubrickas
    2 months ago

    That might explain the issue. If you are using Cloudflare then you need to use the R2 plugin. They are not interchangeable. S3 for AWS R2 for Cloudflare. Even if you have your env variables in there, if you don't have it setup properly your local instance is just going to default to uploading media to /api/media, which makes sense why you don't see your images once deployed

  • default discord avatar
    schwig2 months ago

    Ok, that's a little confusing then because the Payload documentation for the [Storage Adapters](

    https://payloadcms.com/docs/upload/storage-adapters

    ) says to use the S3 plugin because Cloudflare supports the S3 API and the R2 Plugin is still marked as "in Beta."

  • discord user avatar
    seanzubrickas
    2 months ago

    Ohhh



    you are right



    my mistake!



    So it does look like cloudflare exposes an S3-compatible HTTP endpoint for R2—meaning any S3 client can talk to it



    So I think what you'd need to update for your ENV variables is:



    S3_REGION=auto S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
  • default discord avatar
    schwig2 months ago

    That is currently how they are set.


    s3Storage({
        enabled: true,
        clientUploads: true,
        collections:{
          media: {
            disableLocalStorage: true
          },
        },
        //@ts-ignore
        bucket: process.env.R2_BUCKET,
        config: {
          credentials: {
            //@ts-ignore
            accessKeyId: process.env.R2_ACCESS_KEY_ID,
            //@ts-ignore
            secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
          },
          region: 'auto',
          endpoint: `https://${process.env.R2_ENDPOINT}`,
          forcePathStyle: true,
        },
      })
  • discord user avatar
    seanzubrickas
    2 months ago

    and you have each of those envs defined on your Vercel project? I know you mentioned env above, just double checking all the simple things first

  • default discord avatar
    schwig2 months ago

    Yes, both the Environment page on the Vercel dashboard and my local .env share the same variable names and values.

  • discord user avatar
    seanzubrickas
    2 months ago

    Ok, if you go to a media item in payload and hover the name what does the URL look like

  • default discord avatar
    schwig2 months ago

    Currently it seems my admin panel is down in production, when I spin it up on local host the url is

    localhost:3000/api/media/file/<image-file>
  • discord user avatar
    seanzubrickas
    2 months ago

    aha



    Did you upload those files

    before

    you enabled the s3 plugin?



    also what images specifically are not being found in production?

  • default discord avatar
    schwig2 months ago

    It is possible, I've been working on this project for a couple months now. I can confirm the images are in the R2 Bucket, however.



    Currently no images are being found in prod

  • discord user avatar
    seanzubrickas
    2 months ago

    Ok two things:



    1. Is your bucket set to private or public right now? If private, you need to set it to public-this is what gives you the *.r2.dev URL to use as R2_PUBLIC_URL


    2. Add this into your media config under disableLLocalStorage



    generateFileURL: ({ filename }) =>

    https://${process.env.R2_PUBLIC_URL}/${filename}

    ,

  • default discord avatar
    schwig2 months ago

    Public access is currently disabled, let me change it and I'll check back



    Cloudflare is providing me a warning that this link is not intended for production use



    Cloudflare suggests not using the Public Dev URL and rather using the Custom Domains feature to properly link the website and the R2, would the Custom Domain take the place of the *.r2.dev URL?



    Or would I use the S3 API url provided by Cloudflare?

  • discord user avatar
    seanzubrickas
    2 months ago

    Yes (to your first question) so it should look like this:



    s3Storage({
      enabled: true,
      clientUploads: true,
      collections: {
        media: {
          disableLocalStorage: true,
          generateFileURL: ({ filename }) =>
            `https://${process.env.R2_PUBLIC_URL}/${filename}`,
        },
      },
      bucket: process.env.R2_BUCKET || '',
      config: {
        credentials: {
          accessKeyId: process.env.R2_ACCESS_KEY_ID || '',
          secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || '',
        },
        region: 'auto',
        endpoint: `https://${process.env.R2_ENDPOINT}`,
        forcePathStyle: true,
      },
    })


    with these ENVs:



    R2_BUCKET=my-bucket
    R2_ACCESS_KEY_ID=...
    R2_SECRET_ACCESS_KEY=...
    R2_ENDPOINT=<account-id>.r2.cloudflarestorage.com
    R2_PUBLIC_URL=media.theirdomain.com
  • default discord avatar
    schwig2 months ago

    Ok, then I think the Media issue should be resolved. I think I'll have to open a new issue, however as my local deployment is showing up without styling and when I pushed my changes to my preview branch, Vercel logs are showing a build error:



    Failed to compile.
    Type error: Type 'typeof import("/vercel/path0/src/app/(frontend)/next/preview/route")' does not satisfy the constraint 'RouteHandlerConfig<"/next/preview">'.
      Types of property 'GET' are incompatible.
        Type '(req: { cookies: { get: (name: string) => { value: string; }; }; } & Request) => Promise<Response>' is not assignable to type '(request: NextRequest, context: { params: Promise<{}>; }) => void | Response | Promise<void | Response>'.
          Types of parameters 'req' and 'request' are incompatible.
            Type 'NextRequest' is not assignable to type '{ cookies: { get: (name: string) => { value: string; }; }; } & Request'.
              Type 'NextRequest' is not assignable to type '{ cookies: { get: (name: string) => { value: string; }; }; }'.
                The types returned by 'cookies.get(...)' are incompatible between these types.
                  Type 'RequestCookie | undefined' is not assignable to type '{ value: string; }'.
                    Type 'undefined' is not assignable to type '{ value: string; }'.
    Next.js build worker exited with code: 1 and signal: null
     ELIFECYCLE  Command failed with exit code 1.
    Error: Command "pnpm run build" exited with 1
  • discord user avatar
    seanzubrickas
    2 months ago

    Glad we got that sorted out! If this pops up again, let me know!

  • default discord avatar
    schwig2 months ago

    Sure thing, I've also opened a new post with the build error I'm experiencing if you have the time to look.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.