{"slug": "build-a-directory-listing-website-that-earns-online", "title": "Build a directory listing website that earns online", "summary": "A developer released ToolDir, a directory listing website template built with Next.js 15, Supabase, and Stripe. The boilerplate enables creators to quickly launch a public directory site that accepts tool submissions, sells launch slots, publishes a blog, and manages everything from an admin panel. The template uses a Pages Router architecture with TanStack React Query, Redux Toolkit, TipTap, and Framer Motion.", "body_md": "A starter kit to quickly make your own directory listing website using Nextjs, Supabase and Stripe\n\nThis blog tells the story about [ToolDir](https://tooldir.buildsaas.dev/), the directory listing website template built using Nextjs, Supabase and Stripe, a full-stack template to quickly build your directory listing website platform that can earn online.\n\nDirectory listing websites are boring, but in 2026, we got tonnes of SaaS submission websites, AI tool listing websites, prompt directories, Design md directories, and even React frontend UI directories.\n\nEach directory has almost the same pattern of building, and every time we do the same process as defined\n\nBelow is our ToolDir LLM.txt for the directory template. Copy the text and paste it into Claude to get more details about our listing directory template, its features, and how to create one on your own.\n\n```\n# ToolDir — LLM context file\n# Purpose: help coding agents understand this repo quickly without exploratory scanning.\n# Last cleaned for launch template readiness.\n\n## Product\n\nToolDir is a Next.js 15 (Pages Router) AI tool directory boilerplate.\nBuyers launch a public directory site, accept tool submissions, sell launch slots,\npublish a blog, and manage everything from `/admin`.\n\nThis is NOT a generic multi-tenant SaaS CMS. Older SaaS modules (email campaigns,\nwaitlist, kanban, products catalog, forms builder, cron, codegen) were removed.\n\n## Tech stack\n\n- Next.js 15 Pages Router (`pages/`), React 18, Tailwind, shadcn/ui\n- Supabase (Auth + Postgres + Storage)\n- TanStack React Query for server state\n- Redux Toolkit only for subscription/customer client state\n- TipTap for blog CMS\n- Stripe **one-time** Checkout for launch slots (server builds `price_data`; no Price ID catalog required)\n- Set `STRIPE_TEST_ZERO=true` (+ `NEXT_PUBLIC_STRIPE_TEST_ZERO`) to force $0 checkout while wiring webhooks/admin\n- Resend for optional slot-payment receipt (`sendSlotPaymentEmail`)\n- Framer Motion for marketing motion\n\n## Critical architecture note\n\n`app/` is NOT the App Router.\n- `pages/` = real Next.js routes and API handlers\n- `app/admin/` = admin UI components\n- `app/frontend/` = marketing site components (Navbar, Footer, directory UI)\n- `components/ui/` = shadcn primitives\n- `lib/` = APIs, hooks, config, data seeds, store, utils\n\n## Public routes (keep)\n\n| Route | File | Role |\n|-------|------|------|\n| `/` | `pages/index.js` | Directory home |\n| `/tool/[slug]` | `pages/tool/[slug].js` | Tool detail |\n| `/categories/[slug]` | `pages/categories/[slug].js` | Category filter |\n| `/submit` | `pages/submit.js` | Multi-step submission |\n| `/pricing` | `pages/pricing.js` | Launch slot calendar |\n| `/dashboard` | `pages/dashboard.js` | User submissions |\n| `/blog`, `/blog/[slug]` | `pages/blog*.js` | Public blog |\n| `/contact`, `/privacy`, `/terms-and-conditions` | legal |\n| `/auth/callback` | Supabase OAuth |\n| `/robots.txt`, `/sitemap.xml` | SEO |\n\n## Admin routes (keep)\n\n| Route | Role |\n|-------|------|\n| `/admin` | Shell + tabs |\n| `/admin/blogs/new`, `/admin/blogs/[id]` | Nested blog editor |\n| `/admin/editor/blog` | Legacy redirect into nested editor |\n\nAdmin tabs (sidebar): analytics, users, submissions, payments, invoices, pricing-slots, blogs.\nTab id `forms` was renamed to `submissions` (legacy `forms` still opens SubmissionsTab).\n\n## API routes (keep)\n\n- `/api/directory-tools/publish` — approve submission → listing\n- `/api/directory-tools/seed` — seed from `lib/data/tools.js`\n- `/api/tool-submissions/create` — public submit\n- `/api/pricing-slots/upsert` — admin slot CRUD\n- `/api/storage/upload-image` — Supabase Storage uploads\n- `/api/messages/create` — contact form\n- `/api/stripe/checkout` — one-time Checkout for launch slot (`price_data`, optional `$0` via `STRIPE_TEST_ZERO`)\n- `/api/stripe/webhook` — marks submission paid, upserts `payments` / `customers` / `users`, sends Resend receipt\n\nRemoved: `/api/stripe/cancel-subscription` (no SaaS subscriptions).\n\n## Core modules (do not delete)\n```\n\nlib/api/directoryTools.js\n\nlib/api/toolSubmissions.js\n\nlib/api/pricingSlots.js\n\nlib/api/blog.js\n\nlib/api/storage.js\n\nlib/api/auth.js\n\nlib/hooks/useDirectoryTools.js\n\nlib/hooks/useBlogs.js\n\nlib/hooks/usePricingSlots.js\n\nlib/data/tools.js\n\nlib/data/pricing-slots.js\n\nlib/data/testimonials.js\n\napp/frontend/marketing/*\n\napp/admin/components/SubmissionsTab.jsx\n\napp/admin/components/PricingSlotsTab.jsx\n\napp/admin/components/BlogTab.jsx\n\napp/admin/components/BlogTiptapEditor.jsx\n\napp/admin/views/BlogEditorView.jsx\n\n```\n## Data model (Supabase)\n\nPrimary tables: `directory_tools`, `tool_submissions`, `pricing_slots`, `blogs`\nBilling/admin: `users`, `customers`, `payments`, `checkouts`, `invoices`, `messages`, `app_analytics`\nStorage bucket: `saas-starter-storage` (name kept for compatibility)\n\nSee `supabase-migrations.sql` (single file: tables + payment columns + Storage bucket).\n\nWhen Supabase is empty / unset, directory listing can fall back to mock data in `lib/data/tools.js`.\n\n## Supabase Storage\n\nBucket name: **`saas-starter-storage`** (constant `STORAGE_BUCKET` in `lib/api/storage.js`).\nTipTap editors call `uploadBlogEditorImage` → direct Storage upload, fallback `POST /api/storage/upload-image`.\nPaths: `blogs/content/`, `blogs/{id}/content/`, `blogs/banners/`, `blogs/{id}/banner-*`.\nSQL: run `supabase-migrations.sql` once (includes Storage bucket `saas-starter-storage`).\n\n## Environment variables\n\nRequired for core:\n- `NEXT_PUBLIC_SITE_URL`\n- `NEXT_PUBLIC_SUPABASE_URL`\n- `NEXT_PUBLIC_SUPABASE_KEY`\n\nPayments:\n- `STRIPE_SECRET_KEY`\n- `STRIPE_WEBHOOK_SECRET`\n- `NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY` (optional if you only start checkout server-side)\n- `STRIPE_TEST_ZERO=true` — charge $0 in Checkout for local testing\n- `NEXT_PUBLIC_STRIPE_TEST_ZERO=true` — show $0 copy on submit UI\n\nOptional:\n- `RESEND_API_KEY`, `RESEND_FROM_EMAIL`\n- `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST`\n- `NEXT_PUBLIC_APP_URL` (legacy Stripe fallback; prefer SITE_URL)\n\nUse `.env.local` locally. `.env*` is gitignored.\n\n## Intentional dual editors\n\n- `BlogTiptapEditor.jsx` — canonical nested route editor (`/admin/blogs/*`)\n- `TiptapEditor.jsx` — still used by BlogTab modal list workflow\n\nDo not delete either without consolidating BlogTab first.\n\n## What was removed for launch\n\nDo not reintroduce these without a product need:\n- Forms builder (`FormsTab`, `/api/forms/*`, `forms` / `form_submissions` tables)\n- Email campaigns, subscribers, waitlist, kanban/tasks, idea DB, changelog, cron, assets CMS\n- Builder zip/AST APIs, roles-config codegen (`modules-config`, generate-*)\n- Unused deps: octokit, archiver, simple-git, nginx, react-toastify, @vercel/analytics, @stripe/stripe-js, unused Radix accordion/checkbox/avatar/tabs/tooltip/switch/scroll-area\n\n## Conventions for agents\n\n1. Prefer Pages Router for new pages under `pages/`.\n2. Put reusable marketing UI in `app/frontend/marketing/`.\n3. Put Supabase access in `lib/api/*`; use React Query hooks in `lib/hooks/*`.\n4. Do not change visual theme / CSS / layout unless the task is design work.\n5. Do not commit `.env` files.\n6. Keep packaging lean — delete orphan modules instead of leaving stubs.\n7. Brand copy is ToolDir, not \"SAAS Starter\".\n\n## Local commands\n```\n\nbash\n\nnpm install\n\nnpm run dev # [http://localhost:3002](http://localhost:3002)\n\nnpm run build\n\nnpm run lint\n\nnpm run pack # clean buyer zip → dist/tooldir.zip\n\nWhen I was building this boilerplate, I wrote the LLM text to help everyone ask questions related to the boilerplate on Claude or chatgpt.\n\nOnce done, [check the demo](https://tooldir.buildsaas.dev/)\n\nOnce checked, [buy the template 😃](https://shreyvijayvargiya.gumroad.com/l/nextjs-supabase-directory-boilerplate?layout=profile)\n\nLet me explain what this template contains\n\n7 steps and your directory website is ready with database, authentication and payment integrated.\n\nThat is not enough\n\nInside the zip folder, you can find app/admin folder, this contains the admin panel to write blog, review submissions, check payments and website analytics and update pricing for each slot, all reflects directly on the website within the admin panel.\n\n[https://tooldir.buildsaas.dev/admin](https://tooldir.buildsaas.dev/admin)\n\nThis makes it easy for you to run the entire directory website content, manage users and view analytics without touching code.\n\nThe template is built using the latest technology stack\n\nAll tech stacks are universally accepted and open-source, making it robust by nature.\n\nDirectory listing websites are in trend, and making one is a good way for you to earn money online. ToolDir ease the pain in making the entire website and saved almost $2k as a developer's costs; it works well with AI agents like Cursor, v0 or Lovable or Bolt.\n\nCheers\n\nShrey\n\nIf needed, custom template, shoot me an email at [shreyvijayvargiya26@gmail.com](mailto:shreyvijayvargiya26@gmail.com)", "url": "https://wpnews.pro/news/build-a-directory-listing-website-that-earns-online", "canonical_source": "https://dev.to/shreyvijayvargiya/build-a-directory-listing-website-that-earns-online-4o78", "published_at": "2026-07-10 05:44:29+00:00", "updated_at": "2026-07-10 06:05:38.110505+00:00", "lang": "en", "topics": ["developer-tools", "ai-startups"], "entities": ["ToolDir", "Next.js", "Supabase", "Stripe", "TanStack React Query", "Redux Toolkit", "TipTap", "Framer Motion"], "alternates": {"html": "https://wpnews.pro/news/build-a-directory-listing-website-that-earns-online", "markdown": "https://wpnews.pro/news/build-a-directory-listing-website-that-earns-online.md", "text": "https://wpnews.pro/news/build-a-directory-listing-website-that-earns-online.txt", "jsonld": "https://wpnews.pro/news/build-a-directory-listing-website-that-earns-online.jsonld"}}