{"id":31553,"date":"2023-10-24T07:00:00","date_gmt":"2023-10-24T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=31553"},"modified":"2025-03-30T12:03:24","modified_gmt":"2025-03-30T19:03:24","slug":"authenticated-images-cloudinary-next-js-13-supabase-part-1","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1","title":{"rendered":"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)"},"content":{"rendered":"\n<p>Security is a critical functionality on websites and applications. The need to gate content to specific users is important, especially when creating an application that requires some form of authenticated user base and that user base\u2019s ability to access certain data, not meant for general public use.<\/p>\n\n\n\n<p>This is a two-part blog post that explores how you can use Cloudinary to optimize and deliver your images, Supabase to store and gate them with security on the backend, as well as Next.js 13 to provide the Authentication user flow on the frontend.\u00a0<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<p>To benefit from this article, you should be familiar with the basics of <a href=\"https:\/\/nodejs.org\/en\" target=\"_blank\" rel=\"noreferrer noopener\">Node.js<\/a> and <a href=\"https:\/\/nextjs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js<\/a> 13.<\/p>\n\n\n<div class='c-callout  c-callout--inline-title c-callout--note'><strong class='c-callout__title'>Note:<\/strong> <p>To use Next.js 13, you must be on Node.js version 16.4 or higher.<\/p>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">Setting Up Local Development<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Cloudinary Setup<\/h3>\n\n\n\n<p>Follow the steps in this <a href=\"https:\/\/cloudinary.com\/documentation\/how_to_integrate_cloudinary\" target=\"_blank\" rel=\"noreferrer noopener\">guide<\/a> to set up your account and upload your images into Cloudinary if you don\u2019t already have one.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Supabase Setup<\/h3>\n\n\n\n<p>Supabase makes it simple to build your backend, providing you with a PostgreSQL database in a few clicks. Let\u2019s configure our new project in our Supabase dashboard:<\/p>\n\n\n\n<p>Sign up to <a href=\"https:\/\/app.supabase.com\" target=\"_blank\" rel=\"noreferrer noopener\">Supabase<\/a> and create a new project. Wait for your database to start. Once it has started up, follow these steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Click <strong>New project<\/strong>.<\/li>\n\n\n\n<li>Choose your organization.<\/li>\n\n\n\n<li>Pick a name and database password.<\/li>\n\n\n\n<li>Click <strong>Create new project<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p>After creating your project, navigate to <strong>Project Settings<\/strong> in the left-hand menu and select <strong>API<\/strong>.&nbsp;Copy and save these two values:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/gLznrn2XiqkDQ6Vf5mQFChuVpEVNemVwYoI1JhYA5qvdMGs_m5ULlZSB8iKaPqNCrH1EJFiXf8wohBTUvZ_pl1vHClHhom8lrgCHVoLR5xSlsjc1bqoKL-lawF6niuM3-rMrrZ_fLRh-vpz2eNTkfLE\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>These are the two values we\u2019ll use for our environment variables to process them in our Next.js 13 frontend.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting Up Supabase for Content<\/h2>\n\n\n\n<p>For this project example, we\u2019ll create an application that allows us to create, delete, and read data from Supabase with a Next.js 13 frontend. This data will include images from Cloudinary and only authenticated users will be allowed to access the site and its data. What we want is a blog that has images and content with priority levels on each blog. Let\u2019s add our data to Supabase:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create a new table and name it \u201cTickets\u201d.<\/li>\n\n\n\n<li>Check the box that says RLS.<\/li>\n\n\n\n<li>Leave the default columns and add the next custom columns like so:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>title<\/li>\n\n\n\n<li>body<\/li>\n\n\n\n<li>priority<\/li>\n\n\n\n<li>user_email<\/li>\n\n\n\n<li>image&nbsp;<\/li>\n<\/ul>\n\n\n\n<p>Once you create those columns, set them to regular texts as these will all be strings. This is what it should look like:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/7evkuSzmejb2uNX9SrQ38gu9kuA5kWnndipVodBn47AJ1jdV7kq00Jyougf1eswSduVJMNXrjsBVS3kGczsrPnwSXES3IdjwdpXZqx4zozmhJL2Cf290rV1vclPow_baixyUFEEwwhyY4gzkeXH9gGA\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>Now that we have our database set up, let&#8217;s create our auth and security.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Row Level Security in Supabase<\/h2>\n\n\n\n<p>Once you click <strong>Save<\/strong>, go to <strong>Authentication and Policies<\/strong>. We need to create new policies for our Row Level Security to allow users to create, delete and read image tickets. Click <strong>New Policy<\/strong>, which will ask if you want a customized policy. Click that and it will take you to this page:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/2fSd4_tRYCjsfflviFUdixE0jazXANpLcNKVOmmTXSAuzYn1-brR4EzMNNqSqHdGMupK8-JiCVSg0zs1MPHGKXtONMHgnfSxl42Ij9HppP1dEj6hjo1YAEL_1Z0FahxYSpZvkKoBQioW1C49h2iTbaw\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>Next step is to create these policies, their target roles, and their USING expression:<\/p>\n\n\n\n<p>Policy names:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Enable read access to all authenticated users.<\/li>\n\n\n\n<li>Enable all authenticated users to create new tickets.<\/li>\n\n\n\n<li>Allow delete for authors on their own tickets.<\/li>\n<\/ol>\n\n\n\n<p>Target roles:<\/p>\n\n\n\n<p>All roles should be selected as \u201cauthenticated\u201d.<\/p>\n\n\n\n<p>USING expression:<\/p>\n\n\n\n<p>The USING expression for the policies that are \u201cEnable read access to all authenticated users\u201d and \u201cEnable all authenticated users to create new tickets\u201d should be set to \u201ctrue\u201d.&nbsp; You must type the word \u201ctrue\u201d.&nbsp; It should look like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/3jPazaYiWkqEeRLnuIEIoVw1_LZyb26o-A7U4gvQ0NWm-kw7ub6lvWNTwlfaodYgRcEbMizITgo9nscDjugAHIarn-FMj_aHycgjl4_h_k7_OYZ6EwBMvDLyHsP9NQDBnvrUUpyA0QcZBdWcwA9K9gs\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>For the \u201cAllow delete for authors on their own tickets\u201d policy, we need to have the USING expression typed out like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">((auth.jwt() -&gt;&gt; <span class=\"hljs-string\">'email'<\/span>::text) = user_email)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We need this expression because it\u2019s a SQL conditional that allows the auth object to have authentication upon every request with access to the <a href=\"https:\/\/jwt.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSON Web Token<\/a>, and we\u2019re checking the email prop, which is text, and if it does equal the user email logged in, then they\u2019re allowed to delete tickets.<\/p>\n\n\n\n<p>We now have our policies all set, and once you review them and click <strong>Save<\/strong>, your policies should look like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/PlmiPzEaBlH5GOJN1PYY9X5QVp9wPpbCAgVAcY2Dk1Sd9xG-_pKoMWsDXtx_KxveMqzl9A7xpwQx57-_kb2mkCMedLxTqUBcpCtY9BSnCP6V_dL0RcQkoQZMFWsL0nBKPLAbzzBSxSPUNX9BFHuD_y4\" alt=\"\"\/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Adding Data to Supabase<\/h2>\n\n\n\n<p>We have our data tables ready for content input with security installed and authentication policies configured. Let\u2019s add some data to the tables we created. Go to the table editor and you should see your tickets table in the column:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/0evhQHqk_LZDSN8ifTtcCjRPFeJuQQMnz572b_jQt4mnpOL0qAGrMATmW4QEDspo-loA69q68WT9QpqP0pLi4SmaQszeEHvAa0aZ3z0wH5Q_F_YAm_MsOMO1aClymzifY6Xu1vtr2QVJxj9ojOUC6_w\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>When you click <strong>tickets<\/strong>, you\u2019ll see a green button that says <strong>Insert <\/strong>at the top of the page. Click it and select <strong>Insert row<\/strong>:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/pymv4vFYtOw4WSiXBhE-8bz-Lw6V6GSgOemNozfVkgiNtdvUEoL2GOPeif5pdlZ9NF72MQjWc26o36b72cZQVvUdF-1d7vXUmUJBEZvRjki3jEydsacR3WkAVHiHRSomKVOSPBmmKVokpzvoyaGIJk4\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>Once you\u2019re on the <strong>Add new row<\/strong> page, it will give you input boxes to start typing text into them. Add any data you want and for the image input box, make sure you add a source URL from your Cloudinary account on whatever image you want to add there.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/D2bnUA-gg_FsRIDzvWGcWnRUDqb1BaW6Q_nb4T3gMie0RMqXHnFAgHyW3qf-4hJeWrh64TEUJLe9GHWx4_urVbGyLWDpk0BNlxKtAGMVZoeD2mlbPi5-2tlEpu2rgcNBqZTTUiaT09ckBEzO0lBz6h0\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>We\u2019ll grab the Cloudinary image via the source URL in our Next.js frontend.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>We set up our security and database with Supabase and input the data we need. In part 2, we\u2019ll spin up our Next.js 13 frontend and render our data on the browser.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Security is a critical functionality on websites and applications. The need to gate content to specific users is important, especially when creating an application that requires some form of authenticated user base and that user base\u2019s ability to access certain data, not meant for general public use. This is a two-part blog post that explores [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":31554,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,212,388],"class_list":["post-31553","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-next-js","tag-optimize"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Securing &amp; Optimizing Images: Cloudinary, Supabase &amp; Next.js 13 (Part 1)<\/title>\n<meta name=\"description\" content=\"Enhance security &amp; image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup &amp; security with Supabase.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)\" \/>\n<meta property=\"og:description\" content=\"Enhance security &amp; image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup &amp; security with Supabase.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-24T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-03-30T19:03:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)\",\"datePublished\":\"2023-10-24T14:00:00+00:00\",\"dateModified\":\"2025-03-30T19:03:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\"},\"wordCount\":824,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Next.js\",\"Optimize\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2023\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\",\"url\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\",\"name\":\"Securing & Optimizing Images: Cloudinary, Supabase & Next.js 13 (Part 1)\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA\",\"datePublished\":\"2023-10-24T14:00:00+00:00\",\"dateModified\":\"2025-03-30T19:03:24+00:00\",\"description\":\"Enhance security & image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup & security with Supabase.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Securing & Optimizing Images: Cloudinary, Supabase & Next.js 13 (Part 1)","description":"Enhance security & image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup & security with Supabase.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1","og_locale":"en_US","og_type":"article","og_title":"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)","og_description":"Enhance security & image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup & security with Supabase.","og_url":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1","og_site_name":"Cloudinary Blog","article_published_time":"2023-10-24T14:00:00+00:00","article_modified_time":"2025-03-30T19:03:24+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1-jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)","datePublished":"2023-10-24T14:00:00+00:00","dateModified":"2025-03-30T19:03:24+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1"},"wordCount":824,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA","keywords":["Guest Post","Next.js","Optimize"],"inLanguage":"en-US","copyrightYear":"2023","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1","url":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1","name":"Securing & Optimizing Images: Cloudinary, Supabase & Next.js 13 (Part 1)","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA","datePublished":"2023-10-24T14:00:00+00:00","dateModified":"2025-03-30T19:03:24+00:00","description":"Enhance security & image optimization in your web applications using Cloudinary, Supabase, and Next.js 13. Part 1 covers setup & security with Supabase.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/authenticated-images-cloudinary-next-js-13-supabase-part-1#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Authenticated Images With Cloudinary, Next.js 13 and Supabase (Part 1)"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1697221980\/Blog-Authenticating_images_Part1\/Blog-Authenticating_images_Part1.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=31553"}],"version-history":[{"count":8,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31553\/revisions"}],"predecessor-version":[{"id":37316,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31553\/revisions\/37316"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/31554"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=31553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=31553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=31553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}