maheshawasare/claude-skills-pro

scaffold-fullstack-app

Scaffold a single-tenant full-stack app — Next.js (App Router) + Postgres + Auth.js + Brevo email + Razorpay/Stripe + observability.

查看源码

使用方法

  1. 复制安装命令,在自己的智能体环境安装前先检查源码包。
  2. 从原始文档核对所需工具、凭据和支持的宿主。
  3. 说明输入材料与期望交付物,并对照来源检查输出。
npx skills add https://github.com/maheshawasare/claude-skills-pro --skill scaffold-fullstack-app

开始前需了解

  • 安装不包含模型订阅、API 额度或访问文件的权限。
  • 仓库星数和安装量反映活跃情况,不等于独立质量或安全测试。
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

Scaffold a Single-Tenant Full-Stack App

The lighter cousin of scaffold-saas-starter. For apps where the tenancy boundary is the user, not an organization — internal tools, indie SaaS, side projects, B2C consumer apps. No row-level security ceremony, no Clerk billing, just enough structure to ship.

When to use

  • Indie SaaS / side project — you want production-quality but not enterprise scaffolding.
  • Internal tool — small team, single org effectively.
  • B2C consumer app where each user owns their own data.
  • Pre-PMF, want to ship in days.

When NOT to use

  • B2B with teams/orgs/invites → scaffold-saas-starter.
  • Need shared workspaces / collaboration → scaffold-saas-starter.
  • Multi-region or compliance constraints (HIPAA, regulated) — needs more than this scaffold.

Decisions made for you

DecisionChoiceWhy
AuthAuth.js (NextAuth v5)Free, no vendor lock-in, magic-link + OAuth out of box
DBPostgres + DrizzleSame as SaaS scaffold, less the RLS overhead
Tenancyuser_id column on owned rowsNo RLS needed; single-tenant boundary
WebNext.js 16 App RouterMatches SaaS scaffold for muscle memory
EmailBrevoFree tier covers most indie launches
PaymentsRazorpay or Stripe (skip if not needed)Don't wire until you charge
Background jobspg-boss on same DBAvoid Redis until needed
DeployVercel + Neon (free tiers)$0 to first user

File structure

my-app/
  src/
    app/
      (marketing)/page.tsx              # public landing
      (auth)/sign-in/page.tsx
      (app)/                            # authenticated
        dashboard/page.tsx
        settings/page.tsx
      api/
        auth/[...nextauth]/route.ts
        webhooks/
          razorpay/route.ts             # only if billing
          brevo/route.ts
    lib/
      auth.ts                           # auth() helper
      db.ts                              # Drizzle client
      email.ts                           # Brevo wrapper
      billing.ts                         # only if billing
    db/
      schema.ts
      migrations/
  .env.example
  drizzle.config.ts
  next.config.ts
  package.json
  README.md
  docker-compose.yml                    # local Postgres

Note: no apps/ monorepo split. One Next.js project, one DB package. If you outgrow it, lift to apps/web later — 30 min refactor.

Auth.js v5 minimal setup

ts
// src/lib/auth.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { db } from "./db";

export const { auth, handlers, signIn, signOut } = NextAuth({
  adapter: DrizzleAdapter(db),
  providers: [GitHub],
  pages: { signIn: "/sign-in" },
  callbacks: {
    session: async ({ session, user }) => {
      session.user.id = user.id;
      return session;
    },
  },
});
ts
// src/middleware.ts
export { auth as middleware } from "@/lib/auth";

export const config = {
  matcher: ["/((?!api/auth|_next/static|_next/image|favicon.ico|sign-in).*)"],
};

That's it for auth. No Clerk dashboard, no org UI to build, no per-tenant config.

Schema rule: every owned row has user_id

ts
// src/db/schema.ts
import { pgTable, uuid, text, timestamp, integer } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: text("id").primaryKey(),                  // from Auth.js
  email: text("email").notNull().unique(),
  name: text("name"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

export const projects = pgTable("projects", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
});

Discipline (no RLS net): every query against projects MUST filter by userId. Bake this into a helper:

ts
// src/lib/db-helpers.ts
export async function listMyProjects() {
  const session = await auth();
  if (!session?.user?.id) throw new Error("unauthenticated");
  return db.select().from(projects).where(eq(projects.userId, session.user.id));
}

Don't expose raw db to route handlers — only helpers that have already filtered by user. This is the poor person's RLS.

What the scaffold emits

  1. The directory tree above.
  2. Auth.js v5 with GitHub + Google + Email magic-link providers configured (env-toggle).
  3. Drizzle schema with users, accounts, sessions (Auth.js tables) + example projects table with user_id.
  4. Brevo email helper with magic-link template.
  5. Optional Razorpay/Stripe billing (asks at scaffold time; skips if "not yet").
  6. .env.example with every var.
  7. docker-compose.yml for local Postgres.
  8. GitHub Actions: typecheck, lint, build, migration dry-run.

Anti-patterns

  • No `userId` filter on a query — single bug = full leak. Helper-only access pattern catches it at code review.
  • Storing user data without `onDelete: "cascade"` — GDPR/DPDP "right to delete" requires the cascade work. Setting it later requires backfill.
  • Auth.js Email provider without configuring Brevo — magic links fail silently. Wire email at the same time as auth, not later.
  • Building auth UI from scratch — Auth.js gives you sane defaults. Don't.
  • Wiring billing before you charge — adds maintenance load with no revenue. Skip until you have a real plan to sell.
  • No `.env.example` — same problem as in SaaS scaffold; ship it day 1.
  • Vercel + Vercel Postgres — Vercel Postgres is expensive for small apps. Use Neon free tier; switch later if needed.
  • No background jobs at all, "we'll cron it" — first delayed task you need (welcome email after signup, retention campaign) becomes a hack. pg-boss is 50 lines.

Verify it worked

  • [ ] pnpm dev starts Next.js with Postgres connected.
  • [ ] GitHub sign-in completes round-trip; user row appears in users table.
  • [ ] listMyProjects() returns 0 rows when called as a different user.
  • [ ] Magic link email arrives via Brevo (check spam in test).
  • [ ] pnpm build && pnpm start succeeds — no dev-only imports leak.
  • [ ] First Vercel deploy: < 15 minutes from git init to https://*.vercel.app/sign-in working.
  • [ ] CI passes on a fresh push.
  • [ ] DELETE FROM users WHERE id='xxx' cascades and removes their projects (no orphans).

按任务相关推荐