Tech stack and conventions
The exact framework versions and code conventions of the project MaShop generates: Next.js 15, React 19, Tailwind v4, strict TypeScript, and the Supabase client.
Reference. This page lists the exact framework versions and code conventions in the project MaShop generates and commits to your GitHub repo. Every version and rule below is read from the scaffold the AI commits on your first prompt and from the backoffice template.
Stack versions
The first time you prompt the AI on a fresh project, it commits a Next.js starter to your repo. The package.json it writes pins these versions:
| Dependency | Version | Role |
|---|---|---|
next | 15.5.15 | App Router framework |
react / react-dom | 19.0.0 | UI runtime |
tailwindcss | ^4.0.0 | Styling |
@tailwindcss/postcss | ^4.0.0 | Tailwind v4 PostCSS plugin |
typescript | ^5.6.3 | Type checking (strict) |
@supabase/ssr | ^0.5.2 | Cookie-aware Supabase client |
@supabase/supabase-js | ^2.46.0 | Supabase JS SDK |
eslint | 9.15.0 | Linting |
The engines field requires Node 20 or newer. The package name is set to your project slug, and the scripts are the Next.js defaults: dev, build, start, lint.
The scaffold versus the backoffice
Two code surfaces ship with the same major versions. The lightweight storefront scaffold (about 23 files) lands on your first prompt. The full backoffice template (orders, customers, payments, analytics, blog) is pushed when you publish. Both run Next.js 15.5.15, React 19.0.0, and Tailwind v4.
TypeScript configuration
The generated tsconfig.json runs in strict mode. The settings that affect how you write code:
strict: true: no implicitany, null checks on.target: ES2022,module: esnext,moduleResolution: bundler.jsx: preserve, so Next.js handles the JSX transform.- Path alias
@/*: import from the project root with@/components/Headeror@/lib/supabaseinstead of long relative paths.
In the storefront scaffold, @/* maps to ./* (repo root). In the backoffice template, @/* maps to ./src/*. Keep imports consistent with the surface you are editing.
Tailwind v4
Styling uses Tailwind CSS v4. There is no large JavaScript theme file to configure first. The global stylesheet imports Tailwind in one line and declares design tokens as CSS custom properties:
@import "tailwindcss";:root {
--brand: 217 100% 50%;
--brand-soft: 220 100% 95%;
}
PostCSS is wired through @tailwindcss/postcss in postcss.config.mjs. A brand color (#0052FF) is registered in tailwind.config.ts, so you write className="bg-brand" in markup. Use Tailwind utility classes for layout and spacing rather than inline styles.
Render mode: storefront is server-rendered
The root layout of the storefront sets the render mode for every page:
export const dynamic = 'force-dynamic';
This is structural, not per page. Pages render on the server at request time, so server-rendered HTML stays indexable for SEO and product data (stock, prices) stays fresh. It also makes the build-time prerender crash impossible: a Server Component that queries Supabase never runs at next build, so you never hit the supabaseUrl is required error during a build. A page with no per-request data can override this with export const revalidate = N for incremental static regeneration.
Client versus server components
Default to Server Components. Add 'use client' at the top of a file only when it needs interactivity (state, event handlers, browser APIs). The backoffice follows the same rule and renders as a client-side app where it needs rich interactivity.
The Supabase client
The generated code talks to your own Supabase project, never to a MaShop server. Two environment variables drive it, read from .env.local:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
The storefront scaffold exports a single browser client from lib/supabase.ts. It does not throw when the env vars are missing at module load, because that would crash every page during a Netlify build where preview env vars are sometimes absent. Instead it warns and lets the runtime surface a clear error on first use:
if (!url || !anonKey) {
console.warn('[supabase] NEXT_PUBLIC_SUPABASE_URL or _ANON_KEY missing.');
}
export const supabase = createClient(url ?? '', anonKey ?? '');
The backoffice template uses the cookie-aware @supabase/ssr helpers instead, with three entry points:
createServerSupabase()(server), built withcreateServerClientand the request cookie store, for Server Components and route handlers.createBrowserSupabase()(client), built withcreateBrowserClientand marked'use client'.- An admin client for service-role operations.
Both clients are typed against a generated Database type, so column names and row shapes are checked at compile time. Row-Level Security on your Supabase project scopes every query.
Where your data goes
Your customers, orders, and credentials live in your Supabase project. Your prompts and generated code are not sent to OpenAI or Anthropic.
Money is always integer cents
Prices and totals are stored and passed as integer counts of the currency minor unit, never as floating-point numbers. The schema uses *_cents columns; the types use price_cents: number. Format for display with the helper, never with manual string math:
export function formatPrice(cents: number, currency = 'USD'): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
}).format(cents / 100);
}
The backoffice template ships a fuller formatPriceCents / formatMoney that handles zero-decimal currencies (JPY, KRW, XOF, XAF and others) and a parsePriceToCents for inputs. Divide by 100 only at the formatting boundary; keep arithmetic in cents.
Icons in the backoffice
The backoffice template imports icons from a single re-export point, @/lib/icons, which proxies lucide-react. A lint rule blocks direct lucide-react imports everywhere except that one file:
"no-restricted-imports": ["error", {
"paths": [
{ "name": "lucide-react", "message": "Import icons from '@/lib/icons' instead." }
]
}]
Import any icon with import { Package } from '@/lib/icons'. The single choke point lets the whole icon set be swapped at once. The lightweight storefront scaffold does not depend on an icon library.
Linting and builds
The storefront next.config.ts sets eslint.ignoreDuringBuilds: true. The scaffold boilerplate carries minor lint warnings (unescaped apostrophes, raw anchor tags) that do not affect runtime, and a first deploy should not fail next build on lint before you have even seen the code. Clean them up at your pace; the rule is off only for the build gate, so next lint still reports them.
The config also whitelists remote image hosts (any **.supabase.co and images.unsplash.com) and enables AVIF and WebP. The backoffice template flags unused function arguments as errors, except argument names prefixed with _.
Deployment target
The generated project ships a netlify.toml wired to deploy on Netlify with the @netlify/plugin-nextjs plugin. Vercel is not a deployment target for the generated code. Set the same env vars from .env.local under Site settings, Environment variables in Netlify. See Netlify deploys and the deploy overview.
Where to go next
- Project structure: the folder and file layout of the generated repo.
- Your Supabase project: how the database is wired and secured.
- Add a page: extend the App Router yourself.
- Customize components: edit the generated UI directly.
