Nit
Visual feedback for live prototypes, built for teams shipping AI-generated UI across many tools and hosts.
Nit lets a builder add one widget, share a revocable review link, and receive anchored feedback without asking reviewers to create an account. Secure remote projects use anonymous Supabase Auth, UUID project boundaries, Postgres RLS, and narrowly scoped mutation RPCs.
Quick start
Install the nit-app package. The installed command is nit.
npm install --save-dev nit-app
nit init
nit share https://your-preview.example.com/path
nit init provisions a secure project, saves the owner credential on the builder's machine, commits only safe project configuration to .nit, and injects the widget tag. nit share creates a revocable review link that expires after 30 days by default.
To open the same feedback project on the deployed prototype and the maker's local build, create origin-safe links for both:
nit share https://your-preview.example.com --local http://127.0.0.1:5173
For a browser-only project with no remote collaboration:
nit init --local
You can also run the package without installing it:
npx nit-app init
What gets stored where
The committed .nit file contains no secrets:
{
"version": 1,
"mode": "remote",
"projectId": "5e31a6c3-7f13-4f80-b5cf-4cdd1de7d995",
"displaySlug": "swift-otter-a1b2c3",
"widgetUrl": "https://usenit.dev/widget.js"
}
Owner credentials and the anonymous Supabase session live in ~/.config/nit/credentials.json with owner-only file permissions. Back up that file securely. Losing it means losing administrative control until a future account-claiming flow exists.
The widget tag uses the UUID as its data boundary:
<script
src="https://usenit.dev/widget.js"
data-nit-project="5e31a6c3-7f13-4f80-b5cf-4cdd1de7d995"
data-nit-mode="remote"
></script>
Review flow
- The builder runs
nit share <prototype-url>. - Nit creates a scoped review grant and adds its one-time token to the existing prototype URL without discarding its path or query parameters.
- The reviewer opens the link. The widget creates an anonymous Supabase session, exchanges the grant, and removes the token from the visible URL.
- RLS allows that reviewer to read, comment, reply, and manage only their own feedback in that project.
- The builder can revoke the grant. Existing sessions created from it immediately lose project access.
An invalid, expired, wrong-origin, or revoked grant shows a locked state. Remote mode never falls back to local comments.
CLI
nit init [--local] [--force]
nit hooks
nit share <prototype-url> [--local <local-url>] [--expires 30d|never]
nit access list
nit access revoke <grant-id>
nit status [--json] [--type bug] [--page /dashboard]
nit comment resolve <comment-id> [accepted|dismissed|fixed]
nit comment reopen <comment-id>
nit comment delete <comment-id>
nit comment type <comment-id> <bug|design|idea|blocker|question>
nit owner rotate
Only the local owner session can list or revoke grants, resolve or reopen comments, remove another person's feedback, or rotate the owner credential. Deleting a parent keeps its replies under a deleted-comment tombstone.
Legacy plain-text .nit files are rejected. Run nit init --force to create a new secure project. Nit does not read or migrate comments from the legacy Supabase project.
State capture
Nit can capture and restore prototype state so a comment reopens the right tab, modal, or drawer.
import { useNitState } from 'nit-app';
function App() {
const [modalOpen, setModalOpen] = useState(false);
const [activeTab, setActiveTab] = useState(0);
useNitState({
modalOpen: [modalOpen, setModalOpen],
activeTab: [activeTab, setActiveTab],
});
}
Run nit hooks to find likely UI state and generate the registration call.
Architecture
src/: React state-capture library published innit-app.cli/: project provisioning, credentials, sharing, access, and feedback administration.widget/: standalone IIFE widget with anonymous Auth, grant exchange, RLS reads, secured RPC writes, and realtime updates.supabase/: migrations, RLS policies, mutation RPCs, Edge Functions, and database tests.demo/: local React demo.
The public Supabase publishable key is expected to be visible. It grants nothing by itself. Project UUID knowledge also grants nothing. Access requires an authenticated user with an active project membership derived from a valid owner credential or review grant.
See Security and threat model, local Supabase setup, and production rollout.
Development
npm install
npm --prefix widget install
npm --prefix demo install
npm run supabase:start
npm run supabase:reset
npm run dev
Copy the local Supabase URL and publishable key into widget/.env:
SUPABASE_URL=http://127.0.0.1:54321
SUPABASE_PUBLISHABLE_KEY=your_local_publishable_key
Set the matching CLI environment variables:
export NIT_SUPABASE_URL=http://127.0.0.1:54321
export NIT_SUPABASE_PUBLISHABLE_KEY=your_local_publishable_key
export NIT_WIDGET_URL=http://localhost:5173/widget.js
Verification:
npm run test:all
npm run build
npm --prefix widget run build
npm run supabase:test
npm run test:security
The secure schema must be deployed to a new Supabase project. Its migration intentionally stops if a public.comments table already exists.
Portable configuration
Open-source builds support:
NIT_SUPABASE_URLandNIT_SUPABASE_PUBLISHABLE_KEYfor the CLI.NIT_CONFIG_URLto replace Nit's hosted publicconfig.jsonendpoint.NIT_WIDGET_URLfor a self-hosted widget.SUPABASE_URLandSUPABASE_PUBLISHABLE_KEYat widget build time.NIT_PROVISION_LIMIT,NIT_OWNER_EXCHANGE_LIMIT,NIT_JOIN_LIMIT, andNIT_RATE_LIMIT_SALTin Edge Function secrets.
The CLI reads Nit-hosted public defaults from https://usenit.dev/config.json. Environment overrides keep source and self-hosted builds portable.
License
MIT