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.

Voir la source

Mode d’emploi

  1. Copiez la commande et examinez le paquet avant de l’installer dans votre environnement agent.
  2. Consultez le document original pour les outils, identifiants et environnements requis.
  3. Décrivez les entrées et le livrable souhaité ; comparez la sortie aux sources.
npx skills add https://github.com/maheshawasare/claude-skills-pro --skill scaffold-fullstack-app

Avant de commencer

  • L’installation n’inclut ni abonnement au modèle, ni quota API, ni accès aux fichiers.
  • Étoiles et installations reflètent l’activité, pas un test indépendant de qualité ou de sécurité.
Document Skill original

Rendu depuis le dépôt source en conservant titres, exemples, code, tableaux, liens et images.

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).

Tâches connexes