[{"data":1,"prerenderedAt":416},["ShallowReactive",2],{"blog-blueprints/cursor-supabase-netlify":3},{"id":4,"title":5,"body":6,"category":395,"date":396,"dateModified":397,"description":398,"draft":399,"extension":400,"faq":401,"featured":399,"headerVariant":402,"image":401,"keywords":401,"meta":403,"navigation":404,"ogDescription":405,"ogTitle":401,"path":406,"readTime":407,"schemaOrg":408,"schemaType":409,"seo":410,"sitemap":411,"stem":412,"tags":413,"twitterCard":414,"__hash__":415},"blog/blog/blueprints/cursor-supabase-netlify.md","Cursor + Supabase + Netlify Security Blueprint",{"type":7,"value":8,"toc":375},"minimark",[9,20,24,39,44,54,59,62,131,135,139,152,162,166,172,180,184,188,191,204,213,234,238,242,245,254,258,263,266,269,272,275,278,281,284,287,305,344,363],[10,11,12],"blueprint-summary",{},[13,14,15,19],"p",{},[16,17,18],"strong",{},"To secure a Cursor + Supabase + Netlify stack,"," you need to: (1) enable Row Level Security on all Supabase tables and create policies for each operation, (2) configure security headers in _headers file or netlify.toml, (3) store your Supabase service_role key in Netlify environment variables and use it only in Netlify Functions, (4) create a .cursorignore file to prevent AI from accessing your .env files, and (5) configure auth redirect URLs to include your Netlify domain. This blueprint covers Netlify-specific configuration while maintaining the same Supabase security fundamentals.",[21,22],"blueprint-meta",{"time":23},"2-3 hours",[25,26,27],"tldr",{},[13,28,29,30,34,35,38],{},"Deploying your Cursor + Supabase app on Netlify? Key differences from Vercel: use ",[31,32,33],"code",{},"netlify.toml"," or ",[31,36,37],{},"_headers"," for security headers, Netlify Functions for server-side code, and configure environment variables in the Netlify dashboard. Same Supabase security rules apply: enable RLS, protect the service_role key, and configure auth redirect URLs for your Netlify domain.",[40,41,43],"h3",{"id":42},"platform-guides-checklists","Platform Guides & Checklists",[45,46,51],"pre",{"className":47,"code":49,"language":50},[48],"language-text","      Cursor Security Guide\n\n\n\n      Supabase Security Guide\n\n\n\n      Netlify Security Guide\n\n\n\n      Pre-Launch Checklist\n","text",[31,52,49],{"__ignoreMap":53},"",[55,56,58],"h2",{"id":57},"stack-overview","Stack Overview",[13,60,61],{},"This stack combines Cursor for AI-assisted development, Supabase for backend services, and Netlify for hosting. Netlify offers different configuration patterns compared to Vercel:",[63,64,65,81],"table",{},[66,67,68],"thead",{},[69,70,71,75,78],"tr",{},[72,73,74],"th",{},"Feature",[72,76,77],{},"Netlify",[72,79,80],{},"Vercel Equivalent",[82,83,84,95,105,116],"tbody",{},[69,85,86,90,92],{},[87,88,89],"td",{},"Config file",[87,91,33],{},[87,93,94],{},"vercel.json",[69,96,97,100,102],{},[87,98,99],{},"Headers file",[87,101,37],{},[87,103,104],{},"vercel.json headers",[69,106,107,110,113],{},[87,108,109],{},"Server functions",[87,111,112],{},"Netlify Functions",[87,114,115],{},"API Routes / Edge Functions",[69,117,118,121,128],{},[87,119,120],{},"Build command",[87,122,123,124],{},"netlify.toml ",[125,126,127],"span",{},"build",[87,129,130],{},"package.json or vercel.json",[55,132,134],{"id":133},"part-1-netlify-security-headers-netlify","Part 1: Netlify Security Headers Netlify",[40,136,138],{"id":137},"using-_headers-file-netlify","Using _headers File Netlify",[13,140,141,142,144,145,34,148,151],{},"Create a ",[31,143,37],{}," file in your publish directory (usually ",[31,146,147],{},"public/",[31,149,150],{},"dist/","):",[153,154,156],"code-block",{"label":155},"public/_headers",[45,157,160],{"className":158,"code":159,"language":50},[48],"/*\n  X-Frame-Options: DENY\n  X-Content-Type-Options: nosniff\n  Referrer-Policy: strict-origin-when-cross-origin\n  Permissions-Policy: camera=(), microphone=(), geolocation=()\n  X-XSS-Protection: 1; mode=block\n\n# API routes might need different CORS settings\n/api/*\n  Access-Control-Allow-Origin: https://yourdomain.com\n",[31,161,159],{"__ignoreMap":53},[40,163,165],{"id":164},"using-netlifytoml-netlify","Using netlify.toml Netlify",[13,167,168,169,171],{},"Alternatively, configure headers in ",[31,170,33],{},":",[153,173,174],{"label":33},[45,175,178],{"className":176,"code":177,"language":50},[48],"[build]\n  command = \"npm run build\"\n  publish = \"dist\"\n\n[[headers]]\n  for = \"/*\"\n  [headers.values]\n    X-Frame-Options = \"DENY\"\n    X-Content-Type-Options = \"nosniff\"\n    Referrer-Policy = \"strict-origin-when-cross-origin\"\n    Permissions-Policy = \"camera=(), microphone=(), geolocation=()\"\n",[31,179,177],{"__ignoreMap":53},[55,181,183],{"id":182},"part-2-environment-variables-netlify-supabase","Part 2: Environment Variables Netlify Supabase",[40,185,187],{"id":186},"setting-variables-in-netlify-netlify","Setting Variables in Netlify Netlify",[13,189,190],{},"In the Netlify dashboard:",[192,193,194,198,201],"ol",{},[195,196,197],"li",{},"Go to Site settings > Environment variables",[195,199,200],{},"Add your Supabase credentials",[195,202,203],{},"Choose which contexts they apply to (Production, Deploy Previews, etc.)",[153,205,207],{"label":206},"Environment variables for Netlify",[45,208,211],{"className":209,"code":210,"language":50},[48],"# Public (for client-side frameworks, prefix varies)\n# React: REACT_APP_\n# Vite: VITE_\nVITE_SUPABASE_URL=https://xxx.supabase.co\nVITE_SUPABASE_ANON_KEY=eyJ...\n\n# Private (Netlify Functions only)\nSUPABASE_SERVICE_ROLE_KEY=eyJ...\n",[31,212,210],{"__ignoreMap":53},[214,215,216],"warning-box",{},[13,217,218,221,222,225,226,229,230,233],{},[16,219,220],{},"Framework prefix:"," Different frameworks use different prefixes for client-exposed variables. React uses ",[31,223,224],{},"REACT_APP_",", Vite uses ",[31,227,228],{},"VITE_",", and Next.js uses ",[31,231,232],{},"NEXT_PUBLIC_",". Make sure you're using the right prefix.",[55,235,237],{"id":236},"part-3-netlify-functions-netlify","Part 3: Netlify Functions Netlify",[40,239,241],{"id":240},"using-service-role-key-safely-netlify-supabase","Using Service Role Key Safely Netlify Supabase",[13,243,244],{},"Use Netlify Functions to run server-side code that needs the service_role key:",[153,246,248],{"label":247},"netlify/functions/admin-action.ts",[45,249,252],{"className":250,"code":251,"language":50},[48],"import { createClient } from '@supabase/supabase-js';\nimport type { Handler } from '@netlify/functions';\n\nconst supabaseAdmin = createClient(\n  process.env.VITE_SUPABASE_URL!,\n  process.env.SUPABASE_SERVICE_ROLE_KEY!\n);\n\nexport const handler: Handler = async (event) => {\n  // Verify authentication\n  const authHeader = event.headers.authorization;\n  if (!authHeader) {\n    return { statusCode: 401, body: 'Unauthorized' };\n  }\n\n  // Verify the user's JWT\n  const { data: { user }, error } = await supabaseAdmin.auth.getUser(\n    authHeader.replace('Bearer ', '')\n  );\n\n  if (error || !user) {\n    return { statusCode: 401, body: 'Invalid token' };\n  }\n\n  // Now safe to use admin operations\n  return {\n    statusCode: 200,\n    body: JSON.stringify({ success: true })\n  };\n};\n",[31,253,251],{"__ignoreMap":53},[55,255,257],{"id":256},"security-checklist","Security Checklist",[259,260,262],"h4",{"id":261},"pre-launch-checklist-for-cursor-supabase-netlify","Pre-Launch Checklist for Cursor + Supabase + Netlify",[13,264,265],{},"Security headers configured in _headers or netlify.toml",[13,267,268],{},"Environment variables set in Netlify dashboard",[13,270,271],{},"Service role key only used in Netlify Functions",[13,273,274],{},"RLS enabled on all Supabase tables",[13,276,277],{},"Auth redirect URLs include Netlify domain",[13,279,280],{},".cursorignore excludes .env files",[13,282,283],{},"Deploy previews use separate Supabase project (recommended)",[13,285,286],{},"HTTPS enforced (automatic on Netlify)",[288,289,290,294],"stack-comparison",{},[40,291,293],{"id":292},"alternative-stack-configurations","Alternative Stack Configurations",[288,295,296,299],{},[13,297,298],{},"Cursor + Supabase + Vercel\nSame database, different host. Vercel uses vercel.json instead of netlify.toml for configuration.",[45,300,303],{"className":301,"code":302,"language":50},[48],"      Cursor + Firebase + Vercel\n      Swap Supabase for Firebase. Different security model with Firestore rules instead of RLS.\n\n\n      Bolt.new + Supabase + Netlify\n      Swap Cursor for Bolt.new. Same Supabase/Netlify config, different AI code review approach.\n",[31,304,302],{"__ignoreMap":53},[306,307,308,321,327],"faq-section",{},[309,310,312],"faq-item",{"question":311},"Should I use _headers or netlify.toml for security headers?",[13,313,314,315,317,318,320],{},"Either works. The ",[31,316,37],{}," file is simpler for header-only configuration, while ",[31,319,33],{}," is better if you're also configuring redirects, build settings, and other Netlify features in one place.",[309,322,324],{"question":323},"Can deploy previews access my production Supabase?",[13,325,326],{},"By default, deploy previews use the same environment variables as production. For security, consider using different Supabase projects for production vs previews, or restrict what deploy previews can access.",[309,328,330],{"question":329},"How do Netlify Functions compare to Vercel API routes?",[13,331,332,333,336,337,34,340,343],{},"They serve the same purpose (server-side code) but have different file locations and syntax. Netlify Functions go in ",[31,334,335],{},"netlify/functions/",", while Vercel API routes go in ",[31,338,339],{},"pages/api/",[31,341,342],{},"app/api/",".",[345,346,347,353,358],"related-articles",{},[348,349],"related-card",{"description":350,"href":351,"title":352},"Same stack on Vercel","/blog/blueprints/cursor-supabase-vercel","Cursor + Supabase + Vercel",[348,354],{"description":355,"href":356,"title":357},"Deep dive into Netlify security","/blog/guides/netlify","Netlify Security Guide",[348,359],{"description":360,"href":361,"title":362},"Complete Supabase security","/blog/guides/supabase","Supabase Security Guide",[364,365,368,372],"cta-box",{"href":366,"label":367},"/","Start Free Scan",[55,369,371],{"id":370},"deploying-to-netlify","Deploying to Netlify?",[13,373,374],{},"Scan your app for security issues before going live.",{"title":53,"searchDepth":376,"depth":376,"links":377},2,[378,380,381,385,388,391,394],{"id":42,"depth":379,"text":43},3,{"id":57,"depth":376,"text":58},{"id":133,"depth":376,"text":134,"children":382},[383,384],{"id":137,"depth":379,"text":138},{"id":164,"depth":379,"text":165},{"id":182,"depth":376,"text":183,"children":386},[387],{"id":186,"depth":379,"text":187},{"id":236,"depth":376,"text":237,"children":389},[390],{"id":240,"depth":379,"text":241},{"id":256,"depth":376,"text":257,"children":392},[393],{"id":292,"depth":379,"text":293},{"id":370,"depth":376,"text":371},"blueprints","2026-02-02","2026-02-16","Security guide for Cursor + Supabase + Netlify stack. Configure RLS, set up Netlify headers, protect environment variables, and secure your deployment.",false,"md",null,"purple",{},true,"Complete security configuration for Cursor + Supabase deployed on Netlify.","/blog/blueprints/cursor-supabase-netlify","10 min read","[object Object]","Article",{"title":5,"description":398},{"loc":406},"blog/blueprints/cursor-supabase-netlify",[],"summary_large_image","rIEOXwYmYxXXBhT7Lod6x0MkIk0xD_GM9dd43DYpVPk",1775843932569]