Repository navigation
Releases: notils/create-notils
Release list
v0.7.0 — password visibility toggle, tighter required-field labels
v0.7.0 — password visibility toggle, tighter required-field labels
Added
- Password fields now render with a show/hide toggle.
SignInForm,
SignUpForm, and any other schema-driven form with a password field get an
eye-icon button inside the input, backed by a newPasswordInputin
@notils/ui. No schema or prop changes — every existing and future password
field picks this up automatically.
Fixed
- The required-field asterisk no longer sits a visible gap from its
label.Field's flexgap-2treated the marker as a second flex item,
adding an 8px gap on top of the literal space in front of the*. It's now
grouped with the label text as a single item, styledtext-destructive. - An unintended peer-dependency narrowing.
form-builderand
auth-better-authhad picked upreact ^19.3.0during dependency
maintenance, inconsistent withauth-custom/auth-ui/ui, which
stayed on^19.0.0. Reverted for consistency — nothing in either package
needs React 19.3 specifically.
Changed
- Further dependency maintenance across the template: Next.js, React, Zod,
Better Auth,@base-ui/react,lucide-react,shadcn,react-hook-form,
@hookform/resolvers, and@types/*, all at latest within their existing
major. TypeScript stays on 6.x — 7.x is not yet compatible with this
template's Next.js version.
@notils/cli@0.7.0
Ships the same template content in lockstep — add form-builder and
add auth-ui now scaffold the password toggle too, and the same
peer-dependency fix applies to a project added into afterward. See the
cli changelog.
Upgrading
Nothing to do in an existing project — this only changes what a fresh
create-notils scaffold or notils add produces going forward.
v0.6.2 — .env files are reliably gitignored
v0.6.2 — .env files are reliably gitignored
Fixed
-
.envfiles are now reliably gitignored. The template enumerated the files
to ignore (.env,.env.local,.env.development.local, …), so anything the
list didn't anticipate shipped unignored —.env.staging.local, from the
dev-staging-prodtier, was exactly that gap. Replaced with a blanket rule that
cannot have one:.env .env.* !.env.example
-
.env.examplewas itself gitignored in a standalone project. Next.js's
default app.gitignoreuses a bare.env*, which swallows the example file
too — and in a standalone scaffold that file becomes the project root's
.gitignore. So the one env file that should be tracked silently wasn't.
Changed
-
.env.exampleis now the only committed env file. The per-environment files
(.env.development,.env.staging,.env.production) were previously generated
as committed non-secret defaults; they are now local-only, like every other
.env*file..env.exampleremains the committed reference list of every
variable the project reads, and deployments set their values through the host's
environment or secret store rather than a file in the repo.The safer default: no
.env*file can be committed by accident, and there is no
per-file judgement call about whether a given value counts as secret.
Also in this release line
@notils/cli@0.6.2 fixed add dropping package READMEs; @notils/cli@0.6.3
picks up this template. See the cli changelog.
Upgrading
Existing projects: replace your env block in .gitignore with the three lines
above. If you were committing .env.development / .env.staging /
.env.production, move those values to your host's environment or secret store —
or keep committing them by adding your own negations, which is now an explicit
choice rather than the default.
@notils/cli v0.6.3 — picks up the v0.6.2 template
@notils/cli v0.6.3
No changes in this CLI itself. It fetches template source from a ref inlined at
build time, so picking up the .gitignore fix in
create-notils 0.6.2
requires a release.
notils add app now generates apps from the fixed template — .env files are
gitignored, and .env.example is tracked.
@notils/cli v0.6.2 — package READMEs
@notils/cli v0.6.2
Fixed
-
addnow writes each package'sREADME.md. It was dropped outright, though
create-notilsalready shipped them — so an added package came out without the
docs its scaffolded twin had.The README is rewritten rather than copied, by a rewriter shared with
create-notils:../../docs/links become URLs to the published docs (that
directory never ships, so those links were dead), the@notils/*scope becomes
the project's own, and a short note is prepended saying the code is yours.Standalone targets get it at
src/lib/<name>/README.md. Theuikit is skipped
there — it spreads acrosssrc/components/andsrc/lib/rather than occupying
one directory.
v0.6.0 — explicit scaffolding, add app, and a runnable Better Auth demo
v0.6.0 — explicit scaffolding, add app, and a runnable Better Auth demo
The scaffold used to copy everything the template supports and leave you to delete
what you didn't want. Now it asks, and generates only that.
Choose what goes in
? What would you like to create?
❯ Fresh app (recommended)
Demo app
? Authentication
❯ None
Custom authentication
Better Auth
? Select the packages you want to include
◉ UI ◉ API Client ◯ Form Builder
? Environment setup
❯ Single environment (recommended)
Every prompt has a flag, so CI can skip them:
npm create notils@latest my-app -- \
--auth better-auth --packages ui,api-client --env single -y- Fresh app is the default. A clean landing page and your production
configuration — no example pages to delete, no orphaned imports, no unused
dependencies.--demogives you the full reference application instead. - Authentication is one choice, never several.
auth-customand
auth-better-authanswer the same question, so picking one means the other is
never written, along with none of its dependencies. - Unselected packages leave nothing behind — not their workspace dependencies,
not the app imports, not the pages that used them. When something you selected
needs something you didn't, the CLI adds it and says why. - Environments are configurable (
single,dev-prod,dev-staging-prod) with
resolution centralized in one module, keyed onAPP_ENVrather thanNODE_ENV
— Next.js setsNODE_ENV=productionfor staging builds too.
Grow the project afterwards: notils add app
notils add app admin # apps/admin, on the next free dev port
notils add app console --demoGenerated from the same template the scaffolder uses, so an app added later is
indistinguishable from one created up front. It reads where apps live from
notils.json, matches the capabilities the project actually has, takes the next
free dev port, leaves existing apps untouched, and refuses duplicate names.
Better Auth is now a runnable demo
Both providers ship app-side wiring, and the seam is one file: each exports the
same auth, signInInputSchema, and signUpInputSchema, so every page works
unchanged against either. Swapping providers is swapping src/lib/auth.ts.
Better Auth gets its instance on the in-memory adapter (no database to provision
before dev works), its routes via one toNextJsHandler catch-all, its env vars
documented, and a /server-session page demonstrating gating on the server —
the capability a custom backend generally can't offer.
@notils/cli ships with your project
Installed as a devDependency at latest, so bun run notils / pnpm exec notils
work without a global install and each project carries one known-good binary. Note
your lockfile then pins whatever latest resolved to; moving forward is an
explicit <manager> update @notils/cli.
notils.json also gains a published JSON Schema at
https://notils.com/schema.json, so editors validate it as you type. Projects on
the old notils.dev URL — which never served a schema — are migrated automatically
the next time any command writes the file.
Fixed
- In-memory auth state is pinned to
globalThis. Next.js instantiates a
module-levelconstmore than once per server, so the mock auth store had a
separate copy per route:/api/auth/loginissued a token that
/api/auth/sessionrejected with 401. The demo auth flow now works end to end,
and survives hot reloads instead of signing you out on every file save. --packages noneno longer produces a broken standalone project (flatten
assumedpackages/uiexisted and threw partway through).- No dangling references when the UI kit is declined — theme provider, stylesheet,
and landing-page classes all adapt. add apprewrites the package scope intsconfig.json/biome.json, not just in
source imports, so a generated app inherits its compiler options.
Upgrading: nothing to do in an existing project. New scaffolds get the new
prompts; notils.json's $schema URL updates itself on the next CLI command.
⚠️ If you usenotils addin a monorepo, upgrade to@notils/cli@0.6.1Three bugs in 0.6.0 left an added workspace package broken: the generated
tsconfig.jsonextended a file that doesn't exist (TS5083, and with it no
compiler options at all), the manifest was missingscriptsand
devDependencies, and external dependencies were installed at the workspace
root instead of on the package that imports them.Fixed in
@notils/cli@0.6.1.
Standalone projects were unaffected, andcreate-notils@0.6.0needs no change.Already added a package with 0.6.0? Re-run
notils add <name>after upgrading —
your source files are kept and the manifest is regenerated.
@notils/cli v0.6.1 — monorepo add fixes
@notils/cli v0.6.1
Fixes for notils add in a monorepo, all reported from a real project running
0.6.0. Standalone targets were unaffected.
If you added a package with 0.6.0, re-run notils add <name> after upgrading —
your source files are kept, and the manifest and tsconfig are regenerated correctly.
Fixed
-
A package added to a monorepo now has a working
tsconfig.json. It extended
a hardcoded"../../tsconfig.json", which a create-notils monorepo does not have
— its packages extend@<scope>/config/*presets. That producedTS5083: Cannot read file '<root>/tsconfig.json', and because a brokenextendsinherits no
compiler options, the package then also failed onstrict, JSX, and module
resolution. -
The generated manifest was missing
scriptsanddevDependencies. Without
@<scope>/configtheextendshad no reason to resolve; and a package with no
typecheckscript is silently skipped by Turborepo, which is why a genuinely
broken package still reported a passingturbo run typecheck. -
External dependencies are declared on the package that imports them. They
were installed at the workspace root instead, sozodended up in the root
dependencieswhilepackages/auth-customdeclared nothing. The offered install
now runs in each package's own directory. -
add appasks whether you want a fresh or demo app, instead of silently
defaulting to fresh.--no-demois now accepted rather than rejected as unknown.
Not changed
The template ref stays v0.6.0 — this release is CLI code only, so there is no new
template content to fetch.
v0.5.0 — Better Auth, behind the same auth UI
v0.5.0 — Better Auth, behind the same auth UI
Added
-
A second auth provider: Better Auth
(@notils/auth-better-auth). For projects that would rather not run an auth
server — it works in-process with Next.js, with its own database adapters
(Drizzle, Prisma, …).The same auth components work with either provider.
SignInForm,
SignUpForm,ProtectedRouteandSessionStatusrender against Better Auth
exactly as they do against your own backend — no second set of components, no
provider-specific UI:// your own Rust/Express/Go auth API export const auth = createAuthContract(config, anonymousHttp, authedHttp); // …or Better Auth, same components downstream export const auth = createBetterAuthContract({ client, mapUser });
Use exactly one provider — they are alternatives, not layers.
It also ships
getServerSession()/hasServerSession()for server components
and route handlers, which is much of the point of Better Auth. Those sit
outside the shared contract deliberately: a hand-rolled auth backend can't
implement a server-side session read, and forcing it into the contract would
make the contract unimplementable for the projectsauth-customexists for. -
@notils/auth-core— the auth contract as its own types-only package.
Previously it lived insideauth-custom, which meant the auth UI depended on
the custom-backend provider just to import a type; a Better Auth user would
have installed a REST-backend package they don't have. Providers now depend on
the contract, never on each other.
Notes
- Provider-specific flows — 2FA, passkeys, magic links, SSO, organizations — are
deliberately not in the shared contract. Reach for the provider's own API, or
better-auth-ui for Better Auth, when you need
them. - Your auth provider and where your business logic lives are independent
choices. Remote auth with local Drizzle logic is as valid as Better Auth
alongside a separate service. Nothing in these packages assumes either. - The Better Auth provider is verified by types and by wiring the real client
through the real components; the template does not yet ship a runnable Better
Auth example app (the scaffolded example still wiresauth-customagainst mock
routes). Tracked in the roadmap.
Applies to create-notils 0.5.0 and @notils/cli 0.5.0.
v0.4.0 — the agent skill is finally discoverable
v0.4.0 — the agent skill is finally discoverable
Fixed
- The agent skill was invisible to Claude Code. It shipped to
.agents/skills/, but.claude/— the directory Claude Code actually reads —
never reached a scaffold at all, because it is gitignored in the template repo
(it holds Windows junctions git cannot represent), so the template fetch
skipped it entirely. Scaffolds now generate.claude/skills/as real files and
reference the skill fromCLAUDE.md. An AI agent opening a fresh project
finally knows what create-notils produced.
Changed
-
The shipped skill is now
notils-project(wasapp-guide), and reads as a
specification rather than documentation: Overview → Rules → Patterns →
Verification, so an agent can find the relevant section instead of scanning
prose. The name stays accurate as the document grows to cover database,
testing, and deployment. -
The vendored shadcn skill is gone (15 files). Skills for the libraries in
this stack are maintained by their own authors — a copy we did not maintain
would go stale silently. Install them with the
skillsCLI, which uses the same
.agents/skills/convention and records everything inskills-lock.json:bunx skills add shadcn-ui/ui
The generated README and the
notils-projectskill both point at it.
Added
--skills/--no-skills, with an interactive prompt defaulting to yes.
Declining removes the skill and prunes the empty directories, so a project that
does not want agent context carries no trace of it.
Applies to both create-notils and @notils/cli.
v0.3.2 — `add` now installs what it needs
v0.3.2 — add now installs what it needs
Fixed
addleft brownfield projects uncompilable. The packages it writes import
@base-ui/react,react-hook-form,zodand friends; if the project did not
already have them,addprinted an install command as a passive warning among
several others and exited successfully. A project with no shadcn/Base UI setup
— the primary use case — was left broken. It now states plainly that the
packages are required, and offers to install them (--with-depsto skip
the prompt, like--with-theme).next-themeswas missing from the reported dependencies, soadd uiwrote
theme.tsx/theme-toggle.tsximporting a package it never mentioned. The
dependency list was hardcoded in the CLI and had drifted from what the packages
actually declare; it is now read from each fetchedpackage.json(names only —
never the version ranges, which stay yours to resolve), so it cannot drift
again.- The install command named the wrong package manager in a project with no
lockfile yet — it saidnpm addeven when invoked throughbunx. Detection
now falls back to the runner that invoked the CLI (npm_config_user_agent)
before defaulting to npm. - Missing dependencies and the theme offer are no longer skipped when the source
files are already current. A project whose files are present but whose
dependencies are not still does not compile, so a re-run surfaces both.
Applies to both create-notils and @notils/cli.
v0.3.1 — fixes broken 0.3.0 installs
v0.3.1 — fixes broken 0.3.0 installs
0.3.0 of both packages is broken on npm — upgrade to 0.3.1.
Every install failed with:
GET https://registry.npmjs.org/@notils%2ftransform - 404
@notils/transform@0.1.0 failed to resolve
Both CLIs declared the private, never-published @notils/transform as a runtime
dependency. The published bundle was always fine — that code is inlined at build
time — but the manifest still asked npm to fetch a package that does not exist.
It is now a devDependency, where a build-time-only dependency belongs.
A check:publishable guard now runs from prepublishOnly in both packages, so
a workspace: range or an unpublished @notils/* package in dependencies
aborts the publish rather than shipping. It rejects the exact manifest that
caused this.
No functional changes — 0.3.0's features are unaffected. See the 0.3.0 release
notes for what this line adds.