The Netlify Identity widget is a script tag and a global object
A zero config, framework free Netlify Identity widget
At a glance
- What is it?
- The Netlify Identity widget adds signup, login, password recovery, metadata and roles to a static site by including one script and two data attributes, then talks to a JWT based Identity service, and the same functionality is available as an npm module with an `init` call. It suits Netlify hosted sites that need user accounts without a backend of their own.
- Who is it for?
- Adopt the Netlify Identity widget when your site is hosted on Netlify and needs user accounts, because the whole integration is one script tag and a couple of data attributes, and the service handles signup, login, password recovery, metadata and roles. Do not adopt it if you are not on Netlify or you need to run the identity service yourself, since the widget talks to Netlify's hosted service and to the GoTrue client underneath it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly HTML, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One script tag, two data attributes
The integration is as small as a script include gets. The README says you simply include the widget on your site and things like invites and confirmation codes start working. The markup is a normal script tag pointing at the widget script, plus one element for a menu and one for a button:
<script
type="text/javascript"
src="https://identity.netlify.com/v1/netlify-identity-widget.js"
></script><div data-netlify-identity-menu></div>
<div data-netlify-identity-button>Login with Netlify Identity</div>The menu element renders a login and sign up control when the user is not logged in and a username and log out control when they are, and the button element is a simpler control that opens the modal. The widget attaches itself to the window object as `window.netlifyIdentity` when it loads, which is how the page talks to it. The project description calls it a zero config, framework free widget, and the primary language of the repository is HTML, which is the point: it does not require a React application or a build step of your own.
The Identity service is a hosted microservice
The widget is the front half; the service behind it does the work. Netlify's Identity service is described as a plug-and-play microservice for handling site functionalities such as signups, logins, password recovery, user metadata and roles. The README says you can use it from single page apps instead of rolling your own, and integrate with any service that understands JSON Web Tokens. That last point is what makes the widget useful beyond a login box. The token is a standard JWT, so your own functions or API can verify it, and the README shows the pattern with a fetch to a Netlify function using an `Authorization` header carrying the bearer token. The repository also exposes the underlying GoTrue client through `netlifyIdentity.gotrue`, with the caveat that the README attaches to it directly, since doing so brings a risk of getting out of sync between your state and the widget's state.
The global API, in four verbs
Once the script is on the page, the API is small enough to read in one go. `open()` shows the modal, and it takes arguments that matter: `open("login")` opens the modal on the login tab, `open("signup")` on the signup tab, and `open("signup", { full_name: "Jane Doe" })` passes metadata to pre-fill the signup fields. `on()` binds to events, and the widget emits `init`, which is when `currentUser()` becomes available, along with `login`, `logout`, `error`, `open` and `close`. `off()` unbinds, either all handlers for an event with `off("login")` or a single one with `off("login", handler)`. Then there is `close()` to dismiss the modal, `logout()` to end the session and `setLocale("en")` to change the language. The README notes that `currentUser()` is available after the `init` event is invoked, which is a small ordering trap for code that reads the user on page load.
The access token lives for one hour
Token handling is the part of the integration worth reading twice. The access token, the JWT issued by Netlify Identity, expires after one hour, and after expiry the widget automatically uses the refresh token to obtain a new access token when you call `refresh()`. The README's guidance is to call it before making authenticated requests, and it shows the shape in the login handler:
netlifyIdentity.on("login", async (user) => {
// Get a fresh JWT for API calls
const jwt = await netlifyIdentity.refresh();
// Use jwt in Authorization header for your functions/API
fetch("/.netlify/functions/my-function", {
headers: { Authorization: `Bearer ${jwt}` }
});
});The method returns a promise that resolves with the new JWT string, and the README is explicit that you do not need to call it on every request, only when the token may have expired, meaning more than an hour since the last login or refresh. That is the difference between a refresh per call and a refresh per session, and it matters for a busy page.
The module API, and the init options
The same functionality is available as a module on npm, installed with `yarn add netlify-identity-widget` and imported or required as usual, and then it needs an explicit `init` call with an options object. The options are where the real configuration lives. `container` is the selector the widget attaches to, defaulting to the document body. `APIUrl` is an absolute URL to the identity endpoint, and the README is emphatic that it should only be set in special cases, when the app is served from a domain that differs from where the identity endpoint is served, which it says is common for Cordova or Electron apps hosted from localhost or a file. `logo` can be set to false to hide the Netlify logo in the modal, `namePlaceholder` customises the name input, and `locale` takes a language code with a long list of available translations, ending in en, fr, es, pt, hu, pl, cs, sk, de, it, ar, zhCN, nl, sv, sw and ru, defaulting to en.
cookieDomain decides whether a subdomain sees the session
There is one option that quietly decides whether your login works across subdomains, and the README gives it its own paragraph. By default the `nf_jwt` cookie is scoped to the exact hostname that set it, so if your app spans multiple subdomains, with `app.example.com` and `api.example.com` as the examples given, the cookie is not sent to the other one. Setting `cookieDomain` to the parent domain with a leading dot, such as `".example.com"`, makes the cookie included across those subdomains. The default is the safer behaviour for a single host site, and the option exists for the multi-host case. It is the kind of setting that a team adds after an afternoon of wondering why one subdomain appears logged out while another does not.
The v1 in the script URL is not the module version
A versioning note in the README is easy to misread. The `v1` in the script tag URL is not pinned to the major version of the module API, and will only reflect breaking changes in the markup API. So the script you drop into a page and the npm package you import are versioned independently, and the module's own semver is what governs the JavaScript API. The practical consequence is that a page which loads the script from the CDN tracks the markup API, and a project that imports the module controls the version it installs. There is also a live demo at identity.netlify.com and a hosted index at identity.netlify.com/v1/index.html, which the repository description gives as the homepage.
The toolchain behind the widget, and where it stands
The repository is a modern JavaScript project even though the widget itself is framework free. The package manifest is an ES module with a `main` pointing at the built bundle, requires Node 20 or later, and lists Vite 7, Vitest 4, TypeScript 5.8, Preact, MobX and the `gotrue-js` client at version 1.0.1 among its development dependencies, with a `resolutions` entry pinning `vitest/vite` to Vite 7. The build uses Rollup with Babel and Terser, and the repository root carries `netlify.toml` for deploying the demo, an `index.html` and a `foo.html` for manual testing, a `releases/` directory, `renovate.json` for dependency updates, commitlint and Husky for commit discipline, and an `AGENTS.md`-style release process in `RELEASE.md`. The licence is MIT, the recent releases are v2.0.0, v2.0.1 and v2.0.3 all published on 2026-02-26, and the last push to the repository was on 2026-10-19.
Editorial conclusion
Adopt the Netlify Identity widget when your site is hosted on Netlify and needs user accounts, because the whole integration is one script tag and a couple of data attributes, and the service handles signup, login, password recovery, metadata and roles. Do not adopt it if you are not on Netlify or you need to run the identity service yourself, since the widget talks to Netlify's hosted service and to the GoTrue client underneath it. Verify first how your token is refreshed, since the access token expires after one hour and the README says to call `refresh()` in the login handler rather than on every request, and check the `cookieDomain` option if your app spans subdomains.
Frequently asked questions
How do I add Netlify Identity to a static site?
Include the widget script from `https://identity.netlify.com/v1/netlify-identity-widget.js` and add an element with the `data-netlify-identity-menu` or `data-netlify-identity-button` attribute. The widget attaches itself to the window as `window.netlifyIdentity`, and the README says invites and confirmation codes start working once it is included.
How long does the Netlify Identity JWT last and how do I refresh it?
The access token expires after one hour. After expiry the widget uses the refresh token to obtain a new access token when you call `netlifyIdentity.refresh()`, which returns a promise resolving with the new JWT. The README says to call it in the login handler rather than on every request.
What does the cookieDomain option do?
By default the `nf_jwt` cookie is scoped to the exact hostname that set it. If your app spans subdomains such as `app.example.com` and `api.example.com`, setting `cookieDomain` to the parent domain with a leading dot, such as `".example.com"`, makes the cookie available across them.
When should I set the APIUrl option?
The README says to avoid it and only set it when your app is served from a different domain than the identity endpoint, which it calls common for Cordova or Electron apps hosted from localhost or a file. The option is marked as only for special cases.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/netlify-netlify-identity-widget)Was this useful?