[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-netlify-netlify-access-control":3,"mdc-gd8e0r-key":33,"related-org-netlify-netlify-access-control":710,"related-repo-netlify-netlify-access-control":883},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":31,"mdContent":32},"netlify-access-control","manage Netlify site access control","Use when the task involves controlling who can reach a Netlify site, or telling Netlify Identity apart from Secure Access. Trigger whenever the user wants to lock a site or deploy to their company\u002Fteam, restrict access to employees only, build an internal or employees-only app, set up password protection, SSO, or SAML, asks \"who can access my site\", or is confused about Netlify Identity vs Secure Access vs team login vs OAuth providers. Routes the request to the right layer — app-level Identity, site-visitor Password Protection, the Auth0 extension, or Team\u002FOrg SAML SSO — and explains the two-layer (perimeter + in-app identity) pattern and its double-login tradeoff. For building the app-level auth itself, use the netlify-identity skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"netlify","Netlify","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fnetlify.png",[12,16,19,20],{"name":13,"slug":14,"type":15},"Security","security","tag",{"name":17,"slug":18,"type":15},"Permissions","permissions",{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},"Access Control","access-control",24,"https:\u002F\u002Fgithub.com\u002Fnetlify\u002Fcontext-and-tools","2026-07-14T05:40:29.082149",null,5,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":26},[],"https:\u002F\u002Fgithub.com\u002Fnetlify\u002Fcontext-and-tools\u002Ftree\u002FHEAD\u002Fskills\u002Fnetlify-access-control","---\nname: netlify-access-control\ndescription: Use when the task involves controlling who can reach a Netlify site, or telling Netlify Identity apart from Secure Access. Trigger whenever the user wants to lock a site or deploy to their company\u002Fteam, restrict access to employees only, build an internal or employees-only app, set up password protection, SSO, or SAML, asks \"who can access my site\", or is confused about Netlify Identity vs Secure Access vs team login vs OAuth providers. Routes the request to the right layer — app-level Identity, site-visitor Password Protection, the Auth0 extension, or Team\u002FOrg SAML SSO — and explains the two-layer (perimeter + in-app identity) pattern and its double-login tradeoff. For building the app-level auth itself, use the netlify-identity skill.\n---\n\n# Netlify Access Control\n\n\"Auth\" on Netlify means three different things that are easy to conflate. Picking the wrong one — or stacking two when one would do — is the main source of friction. This skill disambiguates the layers and routes you to the right one. For actually building app-level user auth, see the **netlify-identity** skill.\n\n## The three layers\n\n| Layer | Answers | Who it's for | Plan | How it's configured |\n|---|---|---|---|---|\n| **Netlify Identity** | \"Who is this user *inside my app*?\" (signups, logins, roles; issues `nf_jwt`) | Your app's end users | All plans, free | Dashboard + `@netlify\u002Fidentity` code |\n| **Password Protection** (Secure access to *sites*) | \"Can this request even *load the site*?\" | Basic: anyone with a shared password · Team login: Netlify team members | Basic: Pro+ · Team login: Enterprise | Dashboard-only |\n| **Team \u002F Org SAML SSO** (Secure access to *Netlify*) | \"Can you log in to the *Netlify dashboard*?\" (and, with strict mode, pass the site gate) | Netlify team members, via a corporate SAML IdP | Enterprise | Dashboard-only |\n\nThese are independent. The `nf_jwt` cookie is issued by app-level JWT auth: Netlify Identity, or a configured external JWT provider such as Auth0\u002FOkta (the two are mutually exclusive); Password Protection and SAML SSO sessions are separate, with their own lifecycles, and do not populate `nf_jwt`.\n\n> **Note on terminology:** Netlify's docs file Identity, Password Protection, role-based access, and more under an umbrella called \"Secure access to your sites,\" while SAML SSO lives under \"Secure access to Netlify.\" So \"Secure Access\" is not one feature — when a user says it, find out whether they mean *gating site visitors* (Password Protection) or *gating dashboard login* (SAML SSO).\n\n## Why Google causes confusion\n\nThe same provider can show up in two unrelated places:\n\n- **Google as a Netlify Identity OAuth provider** — your app's end users click \"Log in with Google.\" Any Google account works, it creates an Identity user, and it issues an `nf_jwt`. This is app-level auth.\n- **Google Workspace as a SAML IdP for Team\u002FOrg SSO** — your *Netlify team members* log in to the dashboard (and, with strict mode + team-login, pass the site gate) using their corporate Google account. It does **not** create an Identity user and does **not** issue an `nf_jwt`.\n\nBoth are \"sign in with Google,\" but they target different populations and produce different sessions. Don't assume one implies the other.\n\n## Pick the layer\n\nStart from what the user actually needs and walk down:\n\n1. **Does anyone need to be blocked from loading the site at all?**\n   - **No — the site is public, but I need user accounts\u002Froles inside the app** → **Netlify Identity** (open or invite-only registration). Use the **netlify-identity** skill. Done.\n   - **Yes — restrict who can reach it** → keep going.\n\n2. **What kind of restriction?**\n   - **Just keep the public out — a shared secret is fine, no per-user identity needed** (staging, a soft pre-launch gate) → **Basic Password Protection** (Pro+, one shared password). Dashboard-only.\n   - **Only my employees, it's an internal tool \u002F smaller team, and I also want to tell users apart inside the app** → **invite-only Netlify Identity** (all plans, free). Invite only company addresses; Identity itself becomes the gate because no uninvited user can sign in. **One login, full per-user identity, every plan.** This is the best default for \"employees-only internal tool.\" Tradeoff: you manage invites manually and rely on invite links not being shared — it doesn't auto-provision from a corporate directory.\n   - **Big company, app-level company SSO with a single sign-in (no double login), where company-only is enforced inside the IdP** → the **Auth0 extension**. The extension links an Auth0 tenant to your site and exposes `AUTH0_*` env vars so your app authenticates end users through Auth0; Auth0 federates to your corporate IdP (Okta, Entra, Google Workspace) and enforces who counts as company, so users sign in once. This is **app-level**, not a CDN-edge perimeter: the site still loads and your app redirects unauthenticated visitors. Use it when invite-only Identity won't scale to a real org but you don't need a true edge perimeter; that's Option D below. Configured via the Netlify Auth0 extension (dashboard); see the Netlify docs setup guide.\n   - **I genuinely need a CDN-edge perimeter (Enterprise team login \u002F SSO-gated site access) AND a separate app-level Identity** → the **two-layer pattern**. This works, but users sign in **twice** (once at the perimeter, once in the app) — there is no passthrough today. Read [references\u002Ftwo-layer-pattern.md](references\u002Ftwo-layer-pattern.md) before recommending it.\n\nIf the user isn't sure, the most common real answer is **invite-only Netlify Identity** for \"just my team\" and the **Auth0 extension** for \"my whole company with our existing IdP.\" Lead with those before reaching for the double-login stack.\n\n## The double login is real — name it early\n\nWhen Password Protection (team login) and Netlify Identity are both on, **users authenticate twice** and there is no documented bridge between them — no shared cookie, no header forwarding, no JWT exchange. Don't burn iterations trying to wire the perimeter session into the app session; it isn't supported. If single sign-on matters, that's a reason to choose the Auth0 extension (or invite-only Identity) instead of the two-layer stack. Full detail and the per-option tradeoffs are in [references\u002Ftwo-layer-pattern.md](references\u002Ftwo-layer-pattern.md).\n\nAlso flag the hidden cost of team-login: it admits only **Netlify team members**, so every employee who passes that gate needs a paid Netlify seat. That alone usually rules it out for company-wide apps.\n\n## Configuration is dashboard-only — hand it off, don't probe\n\nPassword Protection, Team\u002FOrg SAML SSO, and the Auth0 extension are all configured in the Netlify dashboard or the extensions UI — **there is no public API, CLI command, or MCP tool to set or read them**, and there is no way for an agent to see this state while writing code. So:\n\n- Give the user the dashboard location and an exact checklist; let them flip the setting and confirm.\n- **Do not** `curl https:\u002F\u002Fapi.netlify.com\u002F...`, read tokens off disk, or probe for an undocumented endpoint to inspect or change access settings.\n- If a documented path fails, report it to the user with context (what you tried, the URL, the error) and stop — don't work around it.\n\nFor the one piece an agent *can* read at runtime (which Identity providers are live), call `getSettings()` from `@netlify\u002Fidentity` rather than hard-coding assumptions. It hits `\u002F.netlify\u002Fidentity\u002Fsettings` and works against any origin serving the page, including localhost under `netlify dev` (which proxies to the live service). See the netlify-identity skill.\n\n## References\n\n- [Two-layer pattern (perimeter + in-app identity)](references\u002Ftwo-layer-pattern.md) — the four architecture options for \"company-only access + per-user identity,\" the double-login reality, plan\u002Fseat costs, and the visibility gap.\n",{"data":34,"body":35},{"name":4,"description":6},{"type":36,"children":37},"root",[38,46,60,67,255,274,302,308,313,371,376,382,387,548,565,571,588,599,605,617,648,691,697],{"type":39,"tag":40,"props":41,"children":42},"element","h1",{"id":4},[43],{"type":44,"value":45},"text","Netlify Access Control",{"type":39,"tag":47,"props":48,"children":49},"p",{},[50,52,58],{"type":44,"value":51},"\"Auth\" on Netlify means three different things that are easy to conflate. Picking the wrong one — or stacking two when one would do — is the main source of friction. This skill disambiguates the layers and routes you to the right one. For actually building app-level user auth, see the ",{"type":39,"tag":53,"props":54,"children":55},"strong",{},[56],{"type":44,"value":57},"netlify-identity",{"type":44,"value":59}," skill.",{"type":39,"tag":61,"props":62,"children":64},"h2",{"id":63},"the-three-layers",[65],{"type":44,"value":66},"The three layers",{"type":39,"tag":68,"props":69,"children":70},"table",{},[71,105],{"type":39,"tag":72,"props":73,"children":74},"thead",{},[75],{"type":39,"tag":76,"props":77,"children":78},"tr",{},[79,85,90,95,100],{"type":39,"tag":80,"props":81,"children":82},"th",{},[83],{"type":44,"value":84},"Layer",{"type":39,"tag":80,"props":86,"children":87},{},[88],{"type":44,"value":89},"Answers",{"type":39,"tag":80,"props":91,"children":92},{},[93],{"type":44,"value":94},"Who it's for",{"type":39,"tag":80,"props":96,"children":97},{},[98],{"type":44,"value":99},"Plan",{"type":39,"tag":80,"props":101,"children":102},{},[103],{"type":44,"value":104},"How it's configured",{"type":39,"tag":106,"props":107,"children":108},"tbody",{},[109,166,212],{"type":39,"tag":76,"props":110,"children":111},{},[112,121,143,148,153],{"type":39,"tag":113,"props":114,"children":115},"td",{},[116],{"type":39,"tag":53,"props":117,"children":118},{},[119],{"type":44,"value":120},"Netlify Identity",{"type":39,"tag":113,"props":122,"children":123},{},[124,126,132,134,141],{"type":44,"value":125},"\"Who is this user ",{"type":39,"tag":127,"props":128,"children":129},"em",{},[130],{"type":44,"value":131},"inside my app",{"type":44,"value":133},"?\" (signups, logins, roles; issues ",{"type":39,"tag":135,"props":136,"children":138},"code",{"className":137},[],[139],{"type":44,"value":140},"nf_jwt",{"type":44,"value":142},")",{"type":39,"tag":113,"props":144,"children":145},{},[146],{"type":44,"value":147},"Your app's end users",{"type":39,"tag":113,"props":149,"children":150},{},[151],{"type":44,"value":152},"All plans, free",{"type":39,"tag":113,"props":154,"children":155},{},[156,158,164],{"type":44,"value":157},"Dashboard + ",{"type":39,"tag":135,"props":159,"children":161},{"className":160},[],[162],{"type":44,"value":163},"@netlify\u002Fidentity",{"type":44,"value":165}," code",{"type":39,"tag":76,"props":167,"children":168},{},[169,185,197,202,207],{"type":39,"tag":113,"props":170,"children":171},{},[172,177,179,184],{"type":39,"tag":53,"props":173,"children":174},{},[175],{"type":44,"value":176},"Password Protection",{"type":44,"value":178}," (Secure access to ",{"type":39,"tag":127,"props":180,"children":181},{},[182],{"type":44,"value":183},"sites",{"type":44,"value":142},{"type":39,"tag":113,"props":186,"children":187},{},[188,190,195],{"type":44,"value":189},"\"Can this request even ",{"type":39,"tag":127,"props":191,"children":192},{},[193],{"type":44,"value":194},"load the site",{"type":44,"value":196},"?\"",{"type":39,"tag":113,"props":198,"children":199},{},[200],{"type":44,"value":201},"Basic: anyone with a shared password · Team login: Netlify team members",{"type":39,"tag":113,"props":203,"children":204},{},[205],{"type":44,"value":206},"Basic: Pro+ · Team login: Enterprise",{"type":39,"tag":113,"props":208,"children":209},{},[210],{"type":44,"value":211},"Dashboard-only",{"type":39,"tag":76,"props":213,"children":214},{},[215,229,241,246,251],{"type":39,"tag":113,"props":216,"children":217},{},[218,223,224,228],{"type":39,"tag":53,"props":219,"children":220},{},[221],{"type":44,"value":222},"Team \u002F Org SAML SSO",{"type":44,"value":178},{"type":39,"tag":127,"props":225,"children":226},{},[227],{"type":44,"value":9},{"type":44,"value":142},{"type":39,"tag":113,"props":230,"children":231},{},[232,234,239],{"type":44,"value":233},"\"Can you log in to the ",{"type":39,"tag":127,"props":235,"children":236},{},[237],{"type":44,"value":238},"Netlify dashboard",{"type":44,"value":240},"?\" (and, with strict mode, pass the site gate)",{"type":39,"tag":113,"props":242,"children":243},{},[244],{"type":44,"value":245},"Netlify team members, via a corporate SAML IdP",{"type":39,"tag":113,"props":247,"children":248},{},[249],{"type":44,"value":250},"Enterprise",{"type":39,"tag":113,"props":252,"children":253},{},[254],{"type":44,"value":211},{"type":39,"tag":47,"props":256,"children":257},{},[258,260,265,267,272],{"type":44,"value":259},"These are independent. The ",{"type":39,"tag":135,"props":261,"children":263},{"className":262},[],[264],{"type":44,"value":140},{"type":44,"value":266}," cookie is issued by app-level JWT auth: Netlify Identity, or a configured external JWT provider such as Auth0\u002FOkta (the two are mutually exclusive); Password Protection and SAML SSO sessions are separate, with their own lifecycles, and do not populate ",{"type":39,"tag":135,"props":268,"children":270},{"className":269},[],[271],{"type":44,"value":140},{"type":44,"value":273},".",{"type":39,"tag":275,"props":276,"children":277},"blockquote",{},[278],{"type":39,"tag":47,"props":279,"children":280},{},[281,286,288,293,295,300],{"type":39,"tag":53,"props":282,"children":283},{},[284],{"type":44,"value":285},"Note on terminology:",{"type":44,"value":287}," Netlify's docs file Identity, Password Protection, role-based access, and more under an umbrella called \"Secure access to your sites,\" while SAML SSO lives under \"Secure access to Netlify.\" So \"Secure Access\" is not one feature — when a user says it, find out whether they mean ",{"type":39,"tag":127,"props":289,"children":290},{},[291],{"type":44,"value":292},"gating site visitors",{"type":44,"value":294}," (Password Protection) or ",{"type":39,"tag":127,"props":296,"children":297},{},[298],{"type":44,"value":299},"gating dashboard login",{"type":44,"value":301}," (SAML SSO).",{"type":39,"tag":61,"props":303,"children":305},{"id":304},"why-google-causes-confusion",[306],{"type":44,"value":307},"Why Google causes confusion",{"type":39,"tag":47,"props":309,"children":310},{},[311],{"type":44,"value":312},"The same provider can show up in two unrelated places:",{"type":39,"tag":314,"props":315,"children":316},"ul",{},[317,335],{"type":39,"tag":318,"props":319,"children":320},"li",{},[321,326,328,333],{"type":39,"tag":53,"props":322,"children":323},{},[324],{"type":44,"value":325},"Google as a Netlify Identity OAuth provider",{"type":44,"value":327}," — your app's end users click \"Log in with Google.\" Any Google account works, it creates an Identity user, and it issues an ",{"type":39,"tag":135,"props":329,"children":331},{"className":330},[],[332],{"type":44,"value":140},{"type":44,"value":334},". This is app-level auth.",{"type":39,"tag":318,"props":336,"children":337},{},[338,343,345,350,352,357,359,363,365,370],{"type":39,"tag":53,"props":339,"children":340},{},[341],{"type":44,"value":342},"Google Workspace as a SAML IdP for Team\u002FOrg SSO",{"type":44,"value":344}," — your ",{"type":39,"tag":127,"props":346,"children":347},{},[348],{"type":44,"value":349},"Netlify team members",{"type":44,"value":351}," log in to the dashboard (and, with strict mode + team-login, pass the site gate) using their corporate Google account. It does ",{"type":39,"tag":53,"props":353,"children":354},{},[355],{"type":44,"value":356},"not",{"type":44,"value":358}," create an Identity user and does ",{"type":39,"tag":53,"props":360,"children":361},{},[362],{"type":44,"value":356},{"type":44,"value":364}," issue an ",{"type":39,"tag":135,"props":366,"children":368},{"className":367},[],[369],{"type":44,"value":140},{"type":44,"value":273},{"type":39,"tag":47,"props":372,"children":373},{},[374],{"type":44,"value":375},"Both are \"sign in with Google,\" but they target different populations and produce different sessions. Don't assume one implies the other.",{"type":39,"tag":61,"props":377,"children":379},{"id":378},"pick-the-layer",[380],{"type":44,"value":381},"Pick the layer",{"type":39,"tag":47,"props":383,"children":384},{},[385],{"type":44,"value":386},"Start from what the user actually needs and walk down:",{"type":39,"tag":388,"props":389,"children":390},"ol",{},[391,434],{"type":39,"tag":318,"props":392,"children":393},{},[394,399],{"type":39,"tag":53,"props":395,"children":396},{},[397],{"type":44,"value":398},"Does anyone need to be blocked from loading the site at all?",{"type":39,"tag":314,"props":400,"children":401},{},[402,424],{"type":39,"tag":318,"props":403,"children":404},{},[405,410,412,416,418,422],{"type":39,"tag":53,"props":406,"children":407},{},[408],{"type":44,"value":409},"No — the site is public, but I need user accounts\u002Froles inside the app",{"type":44,"value":411}," → ",{"type":39,"tag":53,"props":413,"children":414},{},[415],{"type":44,"value":120},{"type":44,"value":417}," (open or invite-only registration). Use the ",{"type":39,"tag":53,"props":419,"children":420},{},[421],{"type":44,"value":57},{"type":44,"value":423}," skill. Done.",{"type":39,"tag":318,"props":425,"children":426},{},[427,432],{"type":39,"tag":53,"props":428,"children":429},{},[430],{"type":44,"value":431},"Yes — restrict who can reach it",{"type":44,"value":433}," → keep going.",{"type":39,"tag":318,"props":435,"children":436},{},[437,442],{"type":39,"tag":53,"props":438,"children":439},{},[440],{"type":44,"value":441},"What kind of restriction?",{"type":39,"tag":314,"props":443,"children":444},{},[445,462,485,517],{"type":39,"tag":318,"props":446,"children":447},{},[448,453,455,460],{"type":39,"tag":53,"props":449,"children":450},{},[451],{"type":44,"value":452},"Just keep the public out — a shared secret is fine, no per-user identity needed",{"type":44,"value":454}," (staging, a soft pre-launch gate) → ",{"type":39,"tag":53,"props":456,"children":457},{},[458],{"type":44,"value":459},"Basic Password Protection",{"type":44,"value":461}," (Pro+, one shared password). Dashboard-only.",{"type":39,"tag":318,"props":463,"children":464},{},[465,470,471,476,478,483],{"type":39,"tag":53,"props":466,"children":467},{},[468],{"type":44,"value":469},"Only my employees, it's an internal tool \u002F smaller team, and I also want to tell users apart inside the app",{"type":44,"value":411},{"type":39,"tag":53,"props":472,"children":473},{},[474],{"type":44,"value":475},"invite-only Netlify Identity",{"type":44,"value":477}," (all plans, free). Invite only company addresses; Identity itself becomes the gate because no uninvited user can sign in. ",{"type":39,"tag":53,"props":479,"children":480},{},[481],{"type":44,"value":482},"One login, full per-user identity, every plan.",{"type":44,"value":484}," This is the best default for \"employees-only internal tool.\" Tradeoff: you manage invites manually and rely on invite links not being shared — it doesn't auto-provision from a corporate directory.",{"type":39,"tag":318,"props":486,"children":487},{},[488,493,495,500,502,508,510,515],{"type":39,"tag":53,"props":489,"children":490},{},[491],{"type":44,"value":492},"Big company, app-level company SSO with a single sign-in (no double login), where company-only is enforced inside the IdP",{"type":44,"value":494}," → the ",{"type":39,"tag":53,"props":496,"children":497},{},[498],{"type":44,"value":499},"Auth0 extension",{"type":44,"value":501},". The extension links an Auth0 tenant to your site and exposes ",{"type":39,"tag":135,"props":503,"children":505},{"className":504},[],[506],{"type":44,"value":507},"AUTH0_*",{"type":44,"value":509}," env vars so your app authenticates end users through Auth0; Auth0 federates to your corporate IdP (Okta, Entra, Google Workspace) and enforces who counts as company, so users sign in once. This is ",{"type":39,"tag":53,"props":511,"children":512},{},[513],{"type":44,"value":514},"app-level",{"type":44,"value":516},", not a CDN-edge perimeter: the site still loads and your app redirects unauthenticated visitors. Use it when invite-only Identity won't scale to a real org but you don't need a true edge perimeter; that's Option D below. Configured via the Netlify Auth0 extension (dashboard); see the Netlify docs setup guide.",{"type":39,"tag":318,"props":518,"children":519},{},[520,525,526,531,533,538,540,546],{"type":39,"tag":53,"props":521,"children":522},{},[523],{"type":44,"value":524},"I genuinely need a CDN-edge perimeter (Enterprise team login \u002F SSO-gated site access) AND a separate app-level Identity",{"type":44,"value":494},{"type":39,"tag":53,"props":527,"children":528},{},[529],{"type":44,"value":530},"two-layer pattern",{"type":44,"value":532},". This works, but users sign in ",{"type":39,"tag":53,"props":534,"children":535},{},[536],{"type":44,"value":537},"twice",{"type":44,"value":539}," (once at the perimeter, once in the app) — there is no passthrough today. Read ",{"type":39,"tag":541,"props":542,"children":544},"a",{"href":543},"references\u002Ftwo-layer-pattern.md",[545],{"type":44,"value":543},{"type":44,"value":547}," before recommending it.",{"type":39,"tag":47,"props":549,"children":550},{},[551,553,557,559,563],{"type":44,"value":552},"If the user isn't sure, the most common real answer is ",{"type":39,"tag":53,"props":554,"children":555},{},[556],{"type":44,"value":475},{"type":44,"value":558}," for \"just my team\" and the ",{"type":39,"tag":53,"props":560,"children":561},{},[562],{"type":44,"value":499},{"type":44,"value":564}," for \"my whole company with our existing IdP.\" Lead with those before reaching for the double-login stack.",{"type":39,"tag":61,"props":566,"children":568},{"id":567},"the-double-login-is-real-name-it-early",[569],{"type":44,"value":570},"The double login is real — name it early",{"type":39,"tag":47,"props":572,"children":573},{},[574,576,581,583,587],{"type":44,"value":575},"When Password Protection (team login) and Netlify Identity are both on, ",{"type":39,"tag":53,"props":577,"children":578},{},[579],{"type":44,"value":580},"users authenticate twice",{"type":44,"value":582}," and there is no documented bridge between them — no shared cookie, no header forwarding, no JWT exchange. Don't burn iterations trying to wire the perimeter session into the app session; it isn't supported. If single sign-on matters, that's a reason to choose the Auth0 extension (or invite-only Identity) instead of the two-layer stack. Full detail and the per-option tradeoffs are in ",{"type":39,"tag":541,"props":584,"children":585},{"href":543},[586],{"type":44,"value":543},{"type":44,"value":273},{"type":39,"tag":47,"props":589,"children":590},{},[591,593,597],{"type":44,"value":592},"Also flag the hidden cost of team-login: it admits only ",{"type":39,"tag":53,"props":594,"children":595},{},[596],{"type":44,"value":349},{"type":44,"value":598},", so every employee who passes that gate needs a paid Netlify seat. That alone usually rules it out for company-wide apps.",{"type":39,"tag":61,"props":600,"children":602},{"id":601},"configuration-is-dashboard-only-hand-it-off-dont-probe",[603],{"type":44,"value":604},"Configuration is dashboard-only — hand it off, don't probe",{"type":39,"tag":47,"props":606,"children":607},{},[608,610,615],{"type":44,"value":609},"Password Protection, Team\u002FOrg SAML SSO, and the Auth0 extension are all configured in the Netlify dashboard or the extensions UI — ",{"type":39,"tag":53,"props":611,"children":612},{},[613],{"type":44,"value":614},"there is no public API, CLI command, or MCP tool to set or read them",{"type":44,"value":616},", and there is no way for an agent to see this state while writing code. So:",{"type":39,"tag":314,"props":618,"children":619},{},[620,625,643],{"type":39,"tag":318,"props":621,"children":622},{},[623],{"type":44,"value":624},"Give the user the dashboard location and an exact checklist; let them flip the setting and confirm.",{"type":39,"tag":318,"props":626,"children":627},{},[628,633,635,641],{"type":39,"tag":53,"props":629,"children":630},{},[631],{"type":44,"value":632},"Do not",{"type":44,"value":634}," ",{"type":39,"tag":135,"props":636,"children":638},{"className":637},[],[639],{"type":44,"value":640},"curl https:\u002F\u002Fapi.netlify.com\u002F...",{"type":44,"value":642},", read tokens off disk, or probe for an undocumented endpoint to inspect or change access settings.",{"type":39,"tag":318,"props":644,"children":645},{},[646],{"type":44,"value":647},"If a documented path fails, report it to the user with context (what you tried, the URL, the error) and stop — don't work around it.",{"type":39,"tag":47,"props":649,"children":650},{},[651,653,658,660,666,668,673,675,681,683,689],{"type":44,"value":652},"For the one piece an agent ",{"type":39,"tag":127,"props":654,"children":655},{},[656],{"type":44,"value":657},"can",{"type":44,"value":659}," read at runtime (which Identity providers are live), call ",{"type":39,"tag":135,"props":661,"children":663},{"className":662},[],[664],{"type":44,"value":665},"getSettings()",{"type":44,"value":667}," from ",{"type":39,"tag":135,"props":669,"children":671},{"className":670},[],[672],{"type":44,"value":163},{"type":44,"value":674}," rather than hard-coding assumptions. It hits ",{"type":39,"tag":135,"props":676,"children":678},{"className":677},[],[679],{"type":44,"value":680},"\u002F.netlify\u002Fidentity\u002Fsettings",{"type":44,"value":682}," and works against any origin serving the page, including localhost under ",{"type":39,"tag":135,"props":684,"children":686},{"className":685},[],[687],{"type":44,"value":688},"netlify dev",{"type":44,"value":690}," (which proxies to the live service). See the netlify-identity skill.",{"type":39,"tag":61,"props":692,"children":694},{"id":693},"references",[695],{"type":44,"value":696},"References",{"type":39,"tag":314,"props":698,"children":699},{},[700],{"type":39,"tag":318,"props":701,"children":702},{},[703,708],{"type":39,"tag":541,"props":704,"children":705},{"href":543},[706],{"type":44,"value":707},"Two-layer pattern (perimeter + in-app identity)",{"type":44,"value":709}," — the four architecture options for \"company-only access + per-user identity,\" the double-login reality, plan\u002Fseat costs, and the visibility gap.",{"items":711,"total":882},[712,731,743,750,765,780,797,814,824,839,852,867],{"slug":713,"name":713,"fn":714,"description":715,"org":716,"tags":717,"stars":728,"repoUrl":729,"updatedAt":730},"configure-axis","configure AXIS agent evaluation scenarios","Author AXIS (Agent Experience Index Score) scenarios and axis.config.json for a project. Use when the user asks to set up AXIS, add a scenario, write or edit axis.config.json, or evaluate an AI agent with AXIS.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[718,721,724,727],{"name":719,"slug":720,"type":15},"Agents","agents",{"name":722,"slug":723,"type":15},"Configuration","configuration",{"name":725,"slug":726,"type":15},"Evals","evals",{"name":9,"slug":8,"type":15},32,"https:\u002F\u002Fgithub.com\u002Fnetlify\u002Faxis","2026-07-20T05:59:47.468757",{"slug":732,"name":732,"fn":733,"description":734,"org":735,"tags":736,"stars":728,"repoUrl":729,"updatedAt":742},"using-axis","run and interpret AXIS reports","Run AXIS, read its reports, navigate its project layout, and interpret scores. Use when the user asks to run AXIS, invoke the CLI, compare runs, explain a score, find a regression, manage baselines, or understand where AXIS writes its files.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[737,740,741],{"name":738,"slug":739,"type":15},"CLI","cli",{"name":725,"slug":726,"type":15},{"name":9,"slug":8,"type":15},"2026-07-14T05:40:13.443461",{"slug":4,"name":4,"fn":5,"description":6,"org":744,"tags":745,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[746,747,748,749],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":751,"name":751,"fn":752,"description":753,"org":754,"tags":755,"stars":23,"repoUrl":24,"updatedAt":764},"netlify-agent-runner","run AI agent tasks on Netlify","Run AI agent tasks remotely on Netlify using Claude, Codex, or Gemini. Use when the user wants to run an AI agent on their site, get a second opinion from another model, or delegate development tasks to run remotely against their repo.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[756,757,760,763],{"name":719,"slug":720,"type":15},{"name":758,"slug":759,"type":15},"Automation","automation",{"name":761,"slug":762,"type":15},"LLM","llm",{"name":9,"slug":8,"type":15},"2026-07-17T05:30:19.462913",{"slug":766,"name":766,"fn":767,"description":768,"org":769,"tags":770,"stars":23,"repoUrl":24,"updatedAt":779},"netlify-ai-gateway","route AI requests via Netlify AI Gateway","Reference for Netlify AI Gateway — the managed proxy that routes calls to OpenAI, Anthropic, and Google Gemini SDKs without provider API keys. Use this skill any time the user wants to add AI on a Netlify site (chat, completion, reasoning, image generation, image-to-image edit\u002Fstylize), choose or change a model, wire up the OpenAI \u002F Anthropic \u002F @google\u002Fgenai SDK, decide which provider to use for an image-gen feature (it's Gemini-only on the gateway), or debug \"model not found\" \u002F \"API key missing\" against the gateway. Required reading before pinning a model — the gateway exposes a curated subset, not every provider model.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[771,774,777,778],{"name":772,"slug":773,"type":15},"AI Infrastructure","ai-infrastructure",{"name":775,"slug":776,"type":15},"API Development","api-development",{"name":761,"slug":762,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T05:30:13.14555",{"slug":781,"name":781,"fn":782,"description":783,"org":784,"tags":785,"stars":23,"repoUrl":24,"updatedAt":796},"netlify-blobs","manage file storage with Netlify Blobs","Guide for using Netlify Blobs for file and asset storage — images, documents, uploads, exports, cached binary artifacts. Covers getStore(), CRUD operations, metadata, listing, deploy-scoped vs site-scoped stores, and local development. Do NOT use Blobs as a dynamic data store — use Netlify Database for that.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[786,789,792,793],{"name":787,"slug":788,"type":15},"Backend","backend",{"name":790,"slug":791,"type":15},"File Storage","file-storage",{"name":9,"slug":8,"type":15},{"name":794,"slug":795,"type":15},"Storage","storage","2026-07-17T05:30:16.503306",{"slug":798,"name":798,"fn":799,"description":800,"org":801,"tags":802,"stars":23,"repoUrl":24,"updatedAt":813},"netlify-caching","configure CDN caching on Netlify","Guide for controlling caching on Netlify's CDN. Use when configuring cache headers, setting up stale-while-revalidate, implementing on-demand cache purge, or understanding Netlify's CDN caching behavior. Covers Cache-Control, Netlify-CDN-Cache-Control, cache tags, durable cache, and framework-specific caching patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[803,806,809,810],{"name":804,"slug":805,"type":15},"Caching","caching",{"name":807,"slug":808,"type":15},"Deployment","deployment",{"name":9,"slug":8,"type":15},{"name":811,"slug":812,"type":15},"Performance","performance","2026-07-14T05:40:20.066717",{"slug":815,"name":815,"fn":816,"description":817,"org":818,"tags":819,"stars":23,"repoUrl":24,"updatedAt":823},"netlify-config","configure Netlify site settings","Reference for netlify.toml configuration and site environment variables. Use when configuring build settings, redirects, rewrites, headers, deploy contexts, the `[dev]` block that controls `netlify dev` (command, port, targetPort, framework), or any site-level configuration — and when managing environment variables or secrets with the Netlify CLI, including scoping values to specific deploy contexts. Covers the complete netlify.toml syntax including redirects with splats\u002Fconditions, headers, deploy contexts, functions config, edge functions config, and the `[dev]` block (including when `framework` must be `\"#custom\"` — required when both a custom `command` and `targetPort` are set).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[820,821,822],{"name":722,"slug":723,"type":15},{"name":807,"slug":808,"type":15},{"name":9,"slug":8,"type":15},"2026-07-17T05:30:21.284801",{"slug":825,"name":825,"fn":826,"description":827,"org":828,"tags":829,"stars":23,"repoUrl":24,"updatedAt":838},"netlify-database","provision and manage Netlify Database","Guide for using Netlify Database — the GA managed Postgres product built into Netlify. Use when a project needs any kind of dynamic, structured, or relational data. Covers provisioning via @netlify\u002Fdatabase, Drizzle ORM (@beta) setup, migrations, preview branching, and safe production data handling. Blobs is only for file\u002Fasset storage — any dynamic data belongs in the database.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[830,831,834,835],{"name":787,"slug":788,"type":15},{"name":832,"slug":833,"type":15},"Database","database",{"name":9,"slug":8,"type":15},{"name":836,"slug":837,"type":15},"PostgreSQL","postgresql","2026-07-20T05:58:58.934045",{"slug":840,"name":840,"fn":841,"description":842,"org":843,"tags":844,"stars":23,"repoUrl":24,"updatedAt":851},"netlify-deploy","deploy and host projects on Netlify","Deploy, host, and publish web projects on Netlify with the Netlify CLI. Use when the user wants to deploy a site or repository to Netlify, link a local project to a Netlify site, ship a production or preview\u002Fdraft deploy, set up Git-based continuous deployment, run a manual or local deploy, configure CI deploys, or troubleshoot a failed or misconfigured deploy. Also use to view or tail a deployed site's runtime logs — function and edge-function output, deploy logs — via `netlify logs` when debugging what a live site is doing (recent errors, recent activity, streaming output).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[845,846,847,848],{"name":738,"slug":739,"type":15},{"name":807,"slug":808,"type":15},{"name":9,"slug":8,"type":15},{"name":849,"slug":850,"type":15},"Web Development","web-development","2026-07-17T05:30:14.218977",{"slug":853,"name":853,"fn":854,"description":855,"org":856,"tags":857,"stars":23,"repoUrl":24,"updatedAt":866},"netlify-edge-functions","write Netlify Edge Functions","Guide for writing Netlify Edge Functions. Use when building middleware, geolocation-based logic, request\u002Fresponse manipulation, authentication checks, A\u002FB testing, or any low-latency edge compute. Covers Deno runtime, context.next() middleware pattern, geolocation, and when to choose edge vs serverless.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[858,861,864,865],{"name":859,"slug":860,"type":15},"Edge Functions","edge-functions",{"name":862,"slug":863,"type":15},"Middleware","middleware",{"name":9,"slug":8,"type":15},{"name":811,"slug":812,"type":15},"2026-07-14T05:40:34.147865",{"slug":868,"name":868,"fn":869,"description":870,"org":871,"tags":872,"stars":23,"repoUrl":24,"updatedAt":881},"netlify-forms","handle HTML forms with Netlify","Guide for using Netlify Forms for HTML form handling. Use when adding contact forms, feedback forms, file upload forms, or any form that should be collected by Netlify. Covers the data-netlify attribute, spam filtering, AJAX submissions, file uploads, notifications, and the submissions API.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[873,876,879,880],{"name":874,"slug":875,"type":15},"Forms","forms",{"name":877,"slug":878,"type":15},"HTML","html",{"name":9,"slug":8,"type":15},{"name":849,"slug":850,"type":15},"2026-07-14T05:40:16.075367",17,{"items":884,"total":933},[885,892,899,906,913,920,926],{"slug":4,"name":4,"fn":5,"description":6,"org":886,"tags":887,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[888,889,890,891],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":751,"name":751,"fn":752,"description":753,"org":893,"tags":894,"stars":23,"repoUrl":24,"updatedAt":764},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[895,896,897,898],{"name":719,"slug":720,"type":15},{"name":758,"slug":759,"type":15},{"name":761,"slug":762,"type":15},{"name":9,"slug":8,"type":15},{"slug":766,"name":766,"fn":767,"description":768,"org":900,"tags":901,"stars":23,"repoUrl":24,"updatedAt":779},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[902,903,904,905],{"name":772,"slug":773,"type":15},{"name":775,"slug":776,"type":15},{"name":761,"slug":762,"type":15},{"name":9,"slug":8,"type":15},{"slug":781,"name":781,"fn":782,"description":783,"org":907,"tags":908,"stars":23,"repoUrl":24,"updatedAt":796},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[909,910,911,912],{"name":787,"slug":788,"type":15},{"name":790,"slug":791,"type":15},{"name":9,"slug":8,"type":15},{"name":794,"slug":795,"type":15},{"slug":798,"name":798,"fn":799,"description":800,"org":914,"tags":915,"stars":23,"repoUrl":24,"updatedAt":813},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[916,917,918,919],{"name":804,"slug":805,"type":15},{"name":807,"slug":808,"type":15},{"name":9,"slug":8,"type":15},{"name":811,"slug":812,"type":15},{"slug":815,"name":815,"fn":816,"description":817,"org":921,"tags":922,"stars":23,"repoUrl":24,"updatedAt":823},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[923,924,925],{"name":722,"slug":723,"type":15},{"name":807,"slug":808,"type":15},{"name":9,"slug":8,"type":15},{"slug":825,"name":825,"fn":826,"description":827,"org":927,"tags":928,"stars":23,"repoUrl":24,"updatedAt":838},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[929,930,931,932],{"name":787,"slug":788,"type":15},{"name":832,"slug":833,"type":15},{"name":9,"slug":8,"type":15},{"name":836,"slug":837,"type":15},15]