npm.io
0.1.0 • Published yesterdayCLI

nit-app

Licence
MIT
Version
0.1.0
Deps
1
Size
120 kB
Vulns
0
Weekly
0

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

  1. The builder runs nit share <prototype-url>.
  2. Nit creates a scoped review grant and adds its one-time token to the existing prototype URL without discarding its path or query parameters.
  3. The reviewer opens the link. The widget creates an anonymous Supabase session, exchanges the grant, and removes the token from the visible URL.
  4. RLS allows that reviewer to read, comment, reply, and manage only their own feedback in that project.
  5. 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 in nit-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_URL and NIT_SUPABASE_PUBLISHABLE_KEY for the CLI.
  • NIT_CONFIG_URL to replace Nit's hosted public config.json endpoint.
  • NIT_WIDGET_URL for a self-hosted widget.
  • SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY at widget build time.
  • NIT_PROVISION_LIMIT, NIT_OWNER_EXCHANGE_LIMIT, NIT_JOIN_LIMIT, and NIT_RATE_LIMIT_SALT in 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

Keywords