{"_id":"@alextechhq/promptetheus","name":"@alextechhq/promptetheus","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@alextechhq/promptetheus","version":"0.1.0","description":"CLI for fetching, filling and copying AI prompt templates from Promptetheus","keywords":["prompt","ai","cli","promptetheus","llm"],"license":"MIT","private":false,"publishConfig":{"access":"public"},"engines":{"node":">=18"},"bin":{"pt":"scripts/pt.mjs"},"scripts":{"dev:supabase":"pnpm dlx supabase start","dev:next":"next dev","dev:local":"bash ./scripts/dev-local.sh","dev":"concurrently \"pnpm dlx supabase start\" \"next dev\"","build":"next build","start":"next start","lint":"eslint .","pt":"node scripts/pt.mjs","seed":"node scripts/seed-library.mjs","seed:remote":"node scripts/seed-library.mjs --remote","test":"playwright test","test:ui":"playwright test --ui","test:headed":"playwright test --headed"},"dependencies":{"@hookform/resolvers":"^3.9.1","@radix-ui/react-accordion":"1.2.12","@radix-ui/react-alert-dialog":"1.1.15","@radix-ui/react-aspect-ratio":"1.1.8","@radix-ui/react-avatar":"1.1.11","@radix-ui/react-checkbox":"1.3.3","@radix-ui/react-collapsible":"1.1.12","@radix-ui/react-context-menu":"2.2.16","@radix-ui/react-dialog":"1.1.15","@radix-ui/react-dropdown-menu":"2.1.16","@radix-ui/react-hover-card":"1.1.15","@radix-ui/react-label":"2.1.8","@radix-ui/react-menubar":"1.1.16","@radix-ui/react-navigation-menu":"1.2.14","@radix-ui/react-popover":"1.1.15","@radix-ui/react-progress":"1.1.8","@radix-ui/react-radio-group":"1.3.8","@radix-ui/react-scroll-area":"1.2.10","@radix-ui/react-select":"2.2.6","@radix-ui/react-separator":"1.1.8","@radix-ui/react-slider":"1.3.6","@radix-ui/react-slot":"1.2.4","@radix-ui/react-switch":"1.2.6","@radix-ui/react-tabs":"1.1.13","@radix-ui/react-toast":"1.2.15","@radix-ui/react-toggle":"1.1.10","@radix-ui/react-toggle-group":"1.1.11","@radix-ui/react-tooltip":"1.2.8","@supabase/supabase-js":"^2.100.1","@vercel/analytics":"1.6.1","autoprefixer":"^10.4.20","class-variance-authority":"^0.7.1","clsx":"^2.1.1","cmdk":"1.1.1","date-fns":"4.1.0","embla-carousel-react":"8.6.0","input-otp":"1.4.2","lucide-react":"^0.564.0","next":"16.2.0","next-themes":"^0.4.6","openai":"^6.33.0","react":"19.2.4","react-day-picker":"9.13.2","react-dom":"19.2.4","react-hook-form":"^7.54.1","react-resizable-panels":"^2.1.7","recharts":"2.15.0","sonner":"^1.7.1","tailwind-merge":"^3.3.1","vaul":"^1.1.2","zod":"^3.24.1"},"devDependencies":{"@playwright/test":"^1.59.1","@tailwindcss/postcss":"^4.2.0","@types/node":"^22","@types/react":"19.2.14","@types/react-dom":"19.2.3","concurrently":"^8.2.2","postcss":"^8.5","tailwindcss":"^4.2.0","tw-animate-css":"1.3.3","typescript":"5.7.3"},"gitHead":"c33407b3dfce2a43e2d5cc9e88f00d6c822c0949","_id":"@alextechhq/promptetheus@0.1.0","_nodeVersion":"20.20.2","_npmVersion":"11.12.1","dist":{"integrity":"sha512-8uwo67vSwKfxS1hd6XW7Js16ZAJybi7kbWUnRD/KEmRcjGEYuwtPOeGWw/vmOYYTTbPrtLMmAgoQAbx6s2m9ow==","shasum":"123785ae069883c7ad635228483f9131f8e8d81f","tarball":"https://registry.npmjs.org/@alextechhq/promptetheus/-/promptetheus-0.1.0.tgz","fileCount":4,"unpackedSize":37912,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDk/IksQlDVWLj7iIyX7lip+OFICi3cB+VUBVKSNRORfAIhAPWM0n1nKUj4T9PSYwERIDU0xBavn2UVGHl9CUJu70i8"}]},"_npmUser":{"name":"alextechhq","email":"info@alextechhq.com"},"directories":{},"maintainers":[{"name":"alextechhq","email":"info@alextechhq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/promptetheus_0.1.0_1775824918252_0.01937616564632827"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-10T12:41:58.164Z","0.1.0":"2026-04-10T12:41:58.394Z","modified":"2026-04-10T12:41:58.630Z"},"maintainers":[{"name":"alextechhq","email":"info@alextechhq.com"}],"description":"CLI for fetching, filling and copying AI prompt templates from Promptetheus","keywords":["prompt","ai","cli","promptetheus","llm"],"license":"MIT","readme":"# Promptetheus\n\nA Next.js + Supabase SaaS for creating, sharing, and discovering AI prompt templates.\n\n---\n\n## Tech Stack\n\n- **Next.js 15** (App Router) + TypeScript\n- **Supabase** (Postgres, Auth, RLS)\n- **Tailwind CSS** + shadcn/ui\n- **Recharts** for analytics\n- **Vercel** for hosting\n\n---\n\n## Local Development\n\n```bash\n# 1. Install deps\npnpm install\n\n# 2. Start local Supabase (Docker required)\npnpm dev:supabase        # or: supabase start\n\n# 3. Start Next.js dev server (uses .env.local)\npnpm dev:next\n\n# Or start both together:\npnpm dev:local           # runs scripts/dev-local.sh\n```\n\n**`.env.local`** — copy the values from `supabase status` after `supabase start`:\n\n```env\nNEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321\nNEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_...\nSUPABASE_SERVICE_ROLE_KEY=sb_secret_...\n```\n\n---\n\n## Vercel Development (`vercel dev`)\n\n> ⚠️ **Important**: `vercel dev` downloads your Vercel project's environment variables from the Vercel dashboard and injects them **before** Next.js boots. This means **`.env.local` is completely ignored** — the app will always hit the **remote** Supabase.\n\nUse `pnpm dev:next` when you want to work against the local Supabase instance.\n\n---\n\n## E2E Tests (Playwright)\n\nTests live in `tests/e2e/` and run against the local dev server and local Supabase.\n\n**Prerequisites**: Dev server must be running (`pnpm dev:local`) and local Supabase must be up.\n\n```bash\n# Run all tests headlessly (CI-friendly)\npnpm test             # or: pnpm exec playwright test\n\n# Run with the Playwright interactive UI (step-through, trace viewer)\npnpm test:ui\n\n# Run in headed browser (watch the browser open)\npnpm test:headed\n\n# Run a specific test file\npnpm exec playwright test tests/e2e/01-library-upvote.spec.ts --project=chromium\n\n# Show the last HTML report\npnpm exec playwright show-report\n```\n\n**Test files**:\n\n| File | What it tests |\n|---|---|\n| `01-library-upvote.spec.ts` | Upvote a community prompt → appears in Starred |\n| `02-create-prompt.spec.ts` | Create a prompt → appears in My Prompts |\n| `03-delete-prompt.spec.ts` | Delete a prompt → removed from My Prompts |\n| `04-saves-reflect-in-stats.spec.ts` | Another user saves a prompt → `stat_saves` increments |\n| `05-authorization.spec.ts` | Auth guards redirect to `/login`; Supabase RLS enforced |\n| `06-prompt-detail.spec.ts` | `/prompt/[id]` renders without React hooks errors |\n\nEach test uses `createTestUser` / `deleteTestUser` helpers that create and clean up isolated Supabase auth users. If a test fails mid-run and leaves stale users, subsequent runs auto-detect and delete them before re-creating.\n\n---\n\n## `pt` CLI\n\n`pt` is a zero-dependency Node.js CLI (requires Node ≥ 18) for fetching, filling, and copying AI prompt templates from the command line.\n\n### Installation\n\n```bash\nnpm install -g @alextechhq/promptetheus\n```\n\n### First-time setup\n\nRun once after installing to save the product's Supabase URL and anon key to `~/.config/pt/config.json`:\n\n```bash\npt init\n# pt init — Set up the Promptetheus CLI\n#\n# The following fixed product credentials will be saved:\n#   PT_SUPABASE_URL  https://jxistuzrdnamzhekafdx.supabase.co\n#   PT_ANON_KEY      sb_publishable_...\n#\n# Save to ~/.config/pt/config.json? [Y/n]\n# ✓ Config saved  (mode 0600)\n#\n# Next: pt login — sign in with your Promptetheus account\n```\n\n### Login\n\nAuthenticate with your Promptetheus account (same credentials as the website):\n\n```bash\npt login\n# Email: you@example.com\n# Password: ········\n# ✓ Logged in as you@example.com\n# Session stored at ~/.config/pt/session.json\n```\n\nThe session token is stored locally (mode 0600) and refreshed automatically 60 s before expiry.\n\n### Auth commands\n\n```bash\npt login     # sign in with your Promptetheus account\npt logout    # remove the local session\npt whoami    # show current user and token expiry\n```\n\n### Prompt commands\n\n```bash\n# List all your prompts — shows stable #ID and required variables\npt list\npt list --cat=debugging\n\n# Get a prompt by stable numeric ID (always the same, stored in DB)\npt get 3\n\n# Get by text — shows ALL matching prompts if ambiguous\npt get youtube\n# → shows disambiguation list:\n#   # 5  YouTube Script Generator     {{title}}\n#   # 6  YouTube Description Generator  {{title, transcript}}\n#   # 8  YouTube Intro Generator      {{topic}}\n#   Use pt get <#N> to select one.\n\n# Fill variables and print\npt fill 8 topic=\"How to become an AI engineer\"\n\n# Fill and copy to clipboard\npt copy 8 topic=\"How to become an AI engineer\"\n\n# Search by title or description\npt search \"debugging\"\n\n# Pipe to another tool\npt fill 8 topic=\"AI tools\" | llm\npt get 3 > prompt.txt\n```\n\nWhen you run `pt get <#N>`, the CLI shows:\n- The template with a **variable table** (name + label + example)\n- An **⚠ unfilled warning** with the exact `pt fill` command to run next\n\n### Security model\n\n| Credential | What it is | Where it lives |\n|---|---|---|\n| `PT_SUPABASE_URL` | Fixed product URL (same for all users) | `~/.config/pt/config.json` (written by `pt init`) |\n| `PT_ANON_KEY` | **Shared, public** project anon key — safe to store unencrypted | `~/.config/pt/config.json` (written by `pt init`) |\n| Access token | **User-specific** JWT issued by Supabase Auth after `pt login` | `~/.config/pt/session.json` (mode 0600) |\n| Refresh token | Used to silently refresh the access token | `~/.config/pt/session.json` (mode 0600) |\n\n`pt init` only saves the anon key — it is **not a secret**. It is the same key the website sends in every browser request, and it cannot access data beyond what Row-Level Security policies allow. User-specific privileges come exclusively from the JWT stored after `pt login`.\n\nConfig resolution order (highest → lowest priority):\n\n1. `process.env` — CI / shell overrides  \n2. `~/.config/pt/config.json` — set by `pt init`  \n3. `.env.local` / `.env.remote` / `.env` — repo-level dev fallbacks\n\n---\n\n## MCP Endpoint (Model Context Protocol)\n\nThe app exposes a read-only MCP endpoint for IDE integrations (e.g. VS Code Copilot, Cursor):\n\n```\nGET /api/mcp/prompts\n```\n\nReturns all static prompts as JSON:\n\n```json\n[\n  {\n    \"name\": \"YouTube Script Generator\",\n    \"description\": \"...\",\n    \"variables\": [\"topic\", \"length\"],\n    \"template\": \"Act as a YouTube scriptwriter...\"\n  }\n]\n```\n\n### VS Code Copilot integration\n\nAdd to your VS Code settings (`settings.json`) or `.vscode/settings.json`:\n\n```json\n{\n  \"github.copilot.chat.codeGeneration.instructions\": [\n    {\n      \"url\": \"http://localhost:3000/api/mcp/prompts\"\n    }\n  ]\n}\n```\n\nOr configure as an MCP server if your tool supports the protocol directly (e.g. Cursor, Continue.dev).\n\n---\n\n\n\nMigrations live in `supabase/migrations/`. They run in filename-timestamp order.\n\n```bash\n# Apply pending migrations to remote (linked project)\nsupabase db push\n\n# Check migration status (local vs remote)\nsupabase migration list\n\n# Apply SQL to local DB only (no migration file created)\nsupabase db query \"ALTER TABLE ...\"\n\n# Reset local DB and replay all migrations\nsupabase db reset\n```\n\n**Schema cache**: After schema changes, Supabase PostgREST needs to reload its schema cache. If you get `PGRST205 – table not found`, the migration hasn't run on the target environment yet (local vs. remote mismatch). Run `supabase db push` to push to remote.\n\n---\n\n## Key Lessons Learned\n\n| Problem | Cause | Fix |\n|---|---|---|\n| `user_prompts` table not found | Table existed locally only; app was hitting remote via `vercel dev` | `supabase db push` to sync migration to remote |\n| `vercel dev` ignores `.env.local` | Vercel CLI injects remote env vars first | Use `pnpm dev:next` for local Supabase dev |\n| `PGRST205` after migration | Schema cache not refreshed | Supabase auto-refreshes; or restart with `supabase stop && supabase start` |\n| RLS blocking inserts | Missing `WITH CHECK` clause on INSERT policy | Always pair `USING` (SELECT/DELETE) with `WITH CHECK` (INSERT/UPDATE) |\n| Old catch-all `ALL` policy conflicts | Existing `Users manage own prompts` policy overlapped new scoped policies | Drop old policies before creating per-operation ones |\n\n---\n\n## Project Structure\n\n```\napp/\n  api/               # Route handlers (auth, saved-prompts, etc.)\n  dashboard/\n    create/          # Create prompt form\n    my-prompts/\n      [id]/          # Edit prompt + analytics\n    saved/           # Saved prompts\n    settings/\ncomponents/\n  dashboard-create-page-client.tsx   # Create form\n  dashboard-edit-prompt-client.tsx   # Edit form + delete + analytics tabs\n  prompt-card.tsx                    # Reusable prompt card (hideActions prop)\n  prompt-stats-panel.tsx             # Analytics chart panel\nlib/\n  prompts.ts         # Types, model definitions, category labels\n  supabase.ts        # Supabase client (anon key, session-managed auth)\n  auth-context.tsx   # Auth React context\nsupabase/\n  migrations/        # SQL migration files (applied in order)\n```\n\n","readmeFilename":"README.md","_rev":"1-fd6cd8b9bd3092f5bae50b23d6afdcd5"}