csv-to-fullstack-site
Transforms a CSV, Excel or Google Sheet into a deployed full-stack Next.js site on the user's stack (GitHub + Vercel + Supabase + SendGrid). Use this skill whenever the user has tabular data (any domain - real estate, contacts, recipes, alternance, inventory, anything) and wants to turn it into a live web app, a directory site, an internal tool, or a CRM-style interface. Trigger phrases include "j'ai un CSV", "I have a spreadsheet", "build me a site from this Excel", "fais-moi un site avec ces données", "deploy this Google Sheet as an app", or any time the user uploads tabular data and mentions wanting it online. Encodes the user's specific stack conventions (Next.js 14 App Router, shadcn/ui with @base-ui/react, Tailwind, Zod 4 + react-hook-form, Supabase Postgres + RLS + magic link, Vercel auto-deploy, SendGrid in French) and all the gotchas they hit building production apps. Even if the user only says "build me a site for X" without mentioning the data file explicitly, ask them if they have a CSV/Excel/Sheet and use this skill.
Installation & invocation
1. Crée le fichier sur ta machine :
2. Colle le contenu du SKILL.md ci-dessous, et redémarre Claude Code. Tu peux ensuite l'invoquer manuellement avec :
Claude peut aussi la déclencher automatiquement quand le contexte matche.
Transforme un CSV/Excel/Sheet en site Next.js déployé sur ta stack (GitHub + Vercel + Supabase + Resend). Pour pSEO, directories, internal tools.
Contenu de la skill
CSV → Full-stack site
Take a CSV / Excel / Google Sheet and ship it as a live Next.js site on the user's stack. This is the user's daily driver workflow, so we optimize for speed and zero rework.
What you ship at the end
A live URL on Vercel with:
- Next.js 14 App Router, mobile-first
- Supabase Postgres backing the data, with Row Level Security
- shadcn/ui components built on
@base-ui/react(not Radix) - Optional auth via Supabase magic link in French
- SendGrid (or Resend) wired up for transactional email if needed
- GitHub repo with Vercel auto-deploy on push to
main
When this skill triggers
Any time the user has tabular data and wants a website around it. Domain doesn't matter: real estate listings, contact directories, recipe collections, inventory, internal CRMs, student trackers, event boards. If you see a .csv, .xlsx, or a Google Sheets URL together with "site", "app", "déployer", "online", "interface", trigger.
The user may also say "I want a site to manage X" without a file. Ask: "Tu as un CSV ou un Sheet pour démarrer, ou on part de zéro ?" Either path leads here.
Style rules (non-negotiable, from the user's global instructions)
These come from ~/.claude/CLAUDE.md and apply to everything you generate:
- Never use em-dash
—or en-dash–. Replace with:,(...)·|or.depending on context. This applies to code, copy, commits, prompts, anything. - French by default for UI copy, emails, error messages. The user is French and his audience is too.
- Mobile-first Tailwind: assume 375px width baseline, scale up.
- Escape apostrophes in JSX text:
'(the project's ESLint rule blocks raw').
High-level workflow (5 phases)
[CSV/Excel/Sheet]
↓
1. Discover & analyze data → references/data-modeling.md
↓
2. Confirm scope with user
↓
3. Provision infra (Supabase + GitHub + Vercel) → references/supabase-setup.md, references/deploy-pipeline.md
↓
4. Build the site (Next.js + base-ui + Tailwind) → references/stack-conventions.md
↓
5. Deploy + verify → references/deploy-pipeline.md
Don't skip phases. Phase 2 (confirm scope) is the most common shortcut and it always costs more time than it saves.
Phase 1: Discover & analyze the data
Read the source file and produce a one-page brief in your head before talking to the user.
For each column:
- Inferred SQL type (
text,int4,numeric,date,timestamptz,boolean,jsonb) - Cardinality (unique? mostly unique? small enum? free text?)
- Nullability (any blanks?)
- Whether it looks like a foreign key candidate (e.g.,
student_id,company_id)
Detect data shape:
- Single flat table (most CSVs): contacts, listings, products. → 1 Postgres table.
- Multiple sheets/tabs in Excel: probably already-normalized entities (e.g., "Companies" + "Contacts" + "Deals"). → 1 table per sheet, infer FKs.
- Long format with categorical columns: probably needs a JOIN-style schema with a lookup table for the categorical column.
Detect ownership pattern (drives auth decision):
- Per-user data (each row belongs to one user, e.g., a student's contacts, a freelancer's clients): RLS scoped to
auth.uid(), magic link auth required. - Public read, admin write (a directory anyone can browse, only admin edits): public RLS for SELECT, restricted INSERT/UPDATE/DELETE. Optional auth.
- Fully public (read-only listing, no editing): no auth, no RLS beyond a default-deny.
For the inference details and sample SQL, read references/data-modeling.md.
Phase 2: Confirm scope with the user
Before writing a single line of code, surface what you saw and confirm. Use this template:
J'ai analysé [filename]. Voici ce que je vois:
📊 Donnees
- N lignes, M colonnes
- Type principal: [single table / multi-table / lookup]
- Schema propose: [list each table with key columns]
🔐 Auth
- Pattern detecte: [per-user / public-read / fully-public]
- Recommandation: [magic link / pas d'auth]
🎨 UI minimum
- Liste des [entity] avec recherche + filtres sur [columns]
- Detail page par [entity]
- Formulaire create/edit (si auth)
- [autres pages specifiques au domaine]
🚀 Infra
- Nouveau projet Supabase ou existant ?
- Nouveau repo GitHub ou existant ?
- Domaine custom ou auto Vercel (.vercel.app) ?
OK pour partir la-dessus ou tu veux ajuster ?
Wait for confirmation. The user might add: "I also need a public landing page", "the contacts list should be filterable by city", "no auth, just a Google login". Adapt before moving on.
Phase 3: Provision infrastructure
Three things to set up. Try MCP tools first, fall back to CLI if MCP isn't connected.
Supabase
If mcp__supabase__* tools are available: use them to create the project, run migrations, fetch keys.
If not: use the supabase CLI (supabase projects create, supabase link, supabase db push) and ask the user to copy keys from the dashboard.
Always:
- Generate the SQL migration file in
supabase/migrations/<timestamp>_init.sql - Enable RLS on every table from the start (default-deny, then add policies)
- Set up auth providers if needed (magic link is the default)
Detailed SQL patterns and RLS templates: references/supabase-setup.md.
GitHub
If mcp__cab167ba-*__create_repository (GitHub MCP) is available: create the repo there.
Otherwise: use gh repo create. The user has gh installed.
Critical: before the first commit, run scripts/setup_git_noreply.sh <github-username> to set the local git author email to GitHub's noreply format (<id>+<username>@users.noreply.github.com). Without this, Vercel will reject the deploy with "commit email could not be matched to GitHub account". This bit the user before; don't let it bite them again.
Vercel
After the GitHub repo is up:
- Connect the repo in Vercel (the user has Vercel CLI:
vercel link, or via dashboard). - Set environment variables (Supabase URL + anon key + service_role key + SendGrid/Resend key).
- Push to
main. Vercel auto-deploys.
The user prefers Vercel over Netlify (Netlify rate-limited them after ~25 deploys; Vercel doesn't). Don't propose Netlify.
Full pipeline + env vars list: references/deploy-pipeline.md.
Phase 4: Build the site
Bootstrap with scripts/bootstrap.sh <project-name> which runs create-next-app, installs the user's standard dependencies, copies the design-token Tailwind config, and drops in the base-ui-compatible shadcn components.
Then build pages. The conventions matter; the user's project breaks if you mix them up. Read references/stack-conventions.md before generating components. The biggest landmines:
@base-ui/reactis NOT Radix.DialogTriggerdoes not acceptasChild. Userender={<Button />}instead.@base-ui/reactInputdoesn't forward ref to the DOM. Wrap it inReact.forwardRefif you wantreact-hook-formto read its value. Or skip RHF and use plain controlled state for that field.- Zod 4 has breaking changes with react-hook-form's
zodResolver. If validation acts weird, fall back to plain controlled state. The user has done this successfully on the Euridis login form. lucide-reacticon gotchas.Linkedinis NOT exported in some versions. UseUserSquare2or aliasExternalLink as Linkedin.Youtubeis also missing in older versions; useVideo.- Public folder must exist. Next.js doesn't auto-create
public/. If you reference an asset in/public/foo.svg,mkdir -p publicfirst. next/imagewith SVGs needsunoptimizedprop or it errors.- Server Components by default. Use
"use client"only when you need state, effects, or event handlers. For pages that read user data, addexport const dynamic = "force-dynamic". - The
requireStudent()/requireUser()pattern is the user's standard auth wrapper for server components: it returns{ supabase, user, profile }and redirects unauthenticated users. Reuse it.
Build order:
- Layout shell (sidebar nav for desktop, bottom tab bar for mobile)
- List page (table on desktop, cards on mobile)
- Detail page
- Create/Edit form (if auth)
- Auth pages (login + callback) if applicable
- Domain-specific pages (e.g., dashboards, search, filters)
For each page, prefer Server Components. Drop "use client" only for the inner interactive parts.
Phase 5: Deploy and verify
git add . && git commit -m "feat: initial site from <source>"
git push origin main
Then:
- Watch the Vercel deploy log (
vercel logs --followor via dashboard). - Once deployed, hit the URL, run through the critical paths (sign in, create a row, view detail).
- If auth is enabled, send yourself the magic link end-to-end. Check it doesn't land in spam (the user has had spam issues with default Supabase emails; the SendGrid French template in
assets/templates/email-fr.htmlsolves this). - Add the live URL to the user's project notes.
Common gotchas (full list)
These are all the bugs the user hit while building production apps with this stack. Read references/known-gotchas.md for the full debugging notes; the headline list is:
| Symptom | Cause | Fix |
|---|---|---|
| Vercel rejects commit | Git author email doesn't match GitHub | Run scripts/setup_git_noreply.sh |
Form values are undefined in RHF | base-ui Input doesn't forward ref | Wrap with React.forwardRef or use controlled state |
Cannot read property 'asChild' | base-ui Trigger doesn't support asChild | Use render={<Button />} |
Linkedin is not exported from lucide-react | Not in current version | Use UserSquare2 |
| Magic link in spam | Default Supabase email | Use SendGrid + French template in assets/templates/email-fr.html |
ESLint blocks deploy on ' | react/no-unescaped-entities | Replace with ' |
| Image SVG fails to render | next/image SVG opt | Add unoptimized prop |
| RLS lets nothing through | Forgot to add policies after enabling | Add policy per operation, scoped to auth.uid() |
dynamic = "force-dynamic" missing | Server caching stale user data | Add the export at top of page using user data |
What goes in references/, scripts/, assets/
The skill has more depth than fits in this file. Pull from these as needed:
references/stack-conventions.md- Next.js + base-ui + Tailwind code patterns, with do/don't snippets.references/supabase-setup.md- SQL migration templates, RLS policies, magic link config, Auth callback wiring.references/deploy-pipeline.md- Git config, Vercel env vars, GitHub Actions optional CI, custom domains.references/known-gotchas.md- Detailed debugging walk-throughs for every pitfall above.references/data-modeling.md- CSV → Postgres inference rules, when to normalize, examples per domain.assets/templates/- Drop-in files: Tailwind config, globals.css with design tokens, base-ui-compatible Card/Button/Input/Badge/Dialog, lib/supabase wrappers, lib/auth helper, email HTML template.scripts/bootstrap.sh- Bootstraps a fresh project with the user's exact stack.scripts/infer_schema.py- Reads a CSV and prints aCREATE TABLEstatement.scripts/setup_git_noreply.sh- Sets git config to GitHub noreply email format.
How to use this skill
You don't have to follow the 5 phases sequentially in lockstep. If the user pastes a CSV and says "fais-moi un site rapide", you can race through phases 1-2 (analyze + brief them in 30 seconds) and then execute. If they say "I want to plan this carefully first", spend more time on phase 2.
Always end the skill run with:
- The live URL
- A short list of "what's done" + "what's still TODO" so the user knows where to pick up.
Skills proches
better-auth-best-practices
Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables. Use when users mention Better Auth, betterauth, auth.ts, or need to set up TypeScript authentication with email/password, OAuth, or plugin configuration.
finishing-a-development-branch
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
firecrawl
| Search, scrape, and interact with the web via the Firecrawl CLI. Use this skill whenever the user wants to search the web, find articles, research a topic, look something up online, scrape a webpage, grab content from a URL, get data from a website, crawl documentation, download a site, or interact with pages that need clicks or logins. Also use when they say "fetch this page", "pull the content from", "get the page at https://", or reference external websites. This provides real-time web search with full page content and interact capabilities — beyond what Claude can do natively with built-in tools. Do NOT trigger for local file operations, git commands, deployments, or code editing tasks.
notion-api-cli
Piloter l'API Notion en bas niveau et via le CLI ntn : créer/mettre à jour des pages, query des databases, déployer des workers Notion, uploader des fichiers, appeler l'API REST Notion. Charge ce skill quand l'utilisateur veut 'appeler l'API Notion', 'déployer un worker Notion', 'uploader un fichier dans Notion', ou toute opération technique bas niveau sur Notion (≠ conception d'espace Notion = skill notion).
shadcn
Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".
using-git-worktrees
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification