BetaMaShop is in public beta. We improve it continuously, and your feedback shapes what comes next.

Tech stack and conventions

Your generated codeEnglish· 6 min read· Updated July 01, 2026

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:

DependencyVersionRole
next15.5.15App Router framework
react / react-dom19.0.0UI runtime
tailwindcss^4.0.0Styling
@tailwindcss/postcss^4.0.0Tailwind v4 PostCSS plugin
typescript^5.6.3Type checking (strict)
@supabase/ssr^0.5.2Cookie-aware Supabase client
@supabase/supabase-js^2.46.0Supabase JS SDK
eslint9.15.0Linting

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 implicit any, 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/Header or @/lib/supabase instead 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_URL
  • NEXT_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 with createServerClient and the request cookie store, for Server Components and route handlers.
  • createBrowserSupabase() (client), built with createBrowserClient and 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

conventionscodetailwind
Was this page helpful?
Your feedback is anonymous.