Welcome to the Jose Madrid Salsa developer docs — explore features, APIs, and deployment guides.
Jose Madrid SalsaJMS Docs

Shared Code Strategy

How the storefront and fundraising apps share code through packages/core and the @/ alias.

Shared Code Strategy

Code that more than one app needs lives in packages/core (@jose-madrid/core). Everything else stays in the app that uses it.

How it resolves

packages/core keeps the same layout the code had in the storefront (lib/, components/, emails/), and each app's @/ alias looks in the app first, then in core:

"paths": {
  "@/*": ["./*", "../../packages/core/*"]
}

So import prisma from '@/lib/prisma' works the same in every app, and moving a file between an app and core needs no import changes. Next.js (Turbopack), tsc and tsx all honour the fallback. Vitest does not read paths, so vitest.config.ts has a small resolver that tries the same two roots in the same order.

Shared pages and API routes

Next.js only serves routes from an app's own app/ folder, so a page or API route that two apps serve (checkout, order confirmation, sign-in, /api/auth/[...nextauth], the checkout APIs) lives in packages/core/routes/, at its URL path. Each app keeps a one-line file at the route that re-exports it:

export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'

export { GET } from '@/routes/api/orders/[orderId]/route'

Route segment config (dynamic, runtime, revalidate, maxDuration, …) must be written in the app's file itself, because Next reads it from the file without running it. Keep it out of the core module.

Rules

  • Core never imports from an app. Its @/ alias points only at itself, and npm run type-check --workspace=@jose-madrid/core fails if a core file reaches for something that only exists in an app. When a core file needs an app module, move that module into core.
  • A file belongs in core when two apps import it. Code only one app uses stays in that app.
  • Don't put a file at the same path in an app and in core. The app's copy would silently win for that app.
  • Declare third-party imports in packages/core/package.json, at the version the apps use. next, react, next-auth and @prisma/client are peer dependencies, so every app shares one copy (the Prisma client is generated once, from apps/storefront/prisma/schema.prisma).
  • Tailwind: each app's tailwind.config.ts lists ../../packages/core/{components,lib} in content, so classes used by core components are generated.
  • Tests for core code still live in the storefront's tests/ folder and import it through @/. The storefront's coverage report includes core (coverage.allowExternal). Tests for fundraising-only code live in apps/fundraising/tests.
  • Next.js config that both apps need (security headers, image hosts, server packages) is in packages/core/next-config.mjs, which each app's next.config.mjs imports.
  • Runtime file paths: code in core must not read files relative to process.cwd() or its own location, because it runs from whichever app imported it.

How is this guide?

Edit on GitHub

Last updated on

On this page