Build a Next.js app with shared packages · Vibefield
Build a Next.js app with shared packages
Start with one working app, add shared packages when you need them, and prepare the right deployment. Steps and copyable prompts based on the Syvon and VibeField stacks.
A Next.js application with TypeScript, a working first feature and repeatable checks. Choose a single app, or a pnpm monorepo with shared packages. Hosting comes after the app works locally.
This guide adapts architecture patterns from Syvon beta-v4 and VibeField. It does not clone Syvon's product, private services or entire dependency tree.
You need a coding agent with access to your project files and permission to run the development commands, plus Git, a supported Node.js version compatible with your Next.js release, and pnpm. VibeField currently uses Node 22 and pnpm 9.15.0; those are reference versions, not a claim that they are the newest. Use the same versions locally and in hosting, and commit the lockfile.
The starter skills
Use these skills to guide your agent through each stage. You can also follow the steps below with your own tools. Each skill has its own listing, requirements, and availability.
One app: use this for a site or product with one deployable and no shared code yet. Keep the app at the repository root.
Monorepo: use this when a second app or a real shared package is part of the work. Put deployable apps in apps/, reusable modules in packages/, and add services/ only for separately running processes.
The package folders are destinations for actual shared code. You do not need to create empty packages to match a diagram.
Prompt — choose the architecture
Prompt
I am building [product] for [audience]. The first working journey is [journey].
I need [one app / a web app and another app]. Inspect this repository first.
Recommend a single Next.js app or a pnpm workspace, explain the tradeoff,
and identify the smallest first feature we can run. Preserve existing files.
Do not add authentication, a database or a separate service without a requirement.
2. Create the app
Start in an empty parent directory. For a single app:
sh
pnpm create next-app@latest my-product --ts --eslint --tailwind --app --use-pnpm --import-alias "@/*"
cd my-product
pnpm dev
Choose no src/ directory if you want the paths in this guide exactly. A src/ layout is also valid; keep it consistent. Review any additional generator questions. Record the generated dependency versions and the local URL printed by the dev server. Stop the server before continuing with file moves.
For a monorepo, create an empty my-product directory, enter it, and create this root package.json first:
This example matches VibeField's toolchain. If you choose a different supported Node/pnpm pair, update these pins together with CI and hosting. Root recursive commands run the scripts packages actually define; they do not create a test suite for you.
Create pnpm-workspace.yaml at the same level:
yaml
packages:
- apps/*
- packages/*
Generate the app without a nested installation or Git repository:
Set the generated app's package name to @acme/web. Keep its generated dependencies. Add a typecheck script appropriate to the installed release, such as next typegen && tsc --noEmit. Keep lint as eslint .; build is not a replacement for lint. Install from the workspace root, then start the selected app:
sh
pnpm install
pnpm dev
Prompt — build the first app
Prompt
Use vibefield-next-app if it is installed; otherwise follow these instructions.
Create [my-product / apps/web] with Next.js App Router, TypeScript and Tailwind.
Implement [first journey], including loading, empty and failure states.
Keep server credentials and database access out of client components.
Add working dev, lint, typecheck and build commands, then run them.
Tell me the local URL, files changed and checks that could not run.
Checkpoint: your own first feature loads, not just the generator welcome screen. Refresh its route directly and try an invalid or empty input.
3. Give each part an owner
In one app, use app/ for routes and layouts, components/ for rendering, and server/ for business operations and data access. Mark interactive leaves as client components; keep private work on the server.
In a monorepo, apps can import shared packages. Packages do not reach into app source. The app-local @/* alias is not a substitute for package exports.
Syvon beta-v4 separates its marketing wrapper and agent application, with reusable UI and foundation packages plus separate services. VibeField is smaller: one Next.js site, an optional services process, and a separate library repository. Adopt the boundary pattern, not every component of the larger system.
4. Add one shared package — optional
Start with a component used by two real surfaces. For an internal source-exported UI package, create packages/ui/package.json:
Match the peer range to your app's React version. Give this package its own matching React type declarations so its source does not depend on an app's incidental dependency layout. Create packages/ui/src/button.tsx:
tsx
import type { ComponentPropsWithoutRef } from 'react';
export function Button(props: ComponentPropsWithoutRef<'button'>) {
return <button type="button" {...props} />;
}
Add "@acme/ui": "workspace:*" to the web app's dependencies. From the root, install and add the type-checking dependencies to the package (the type versions below match the React 19 example):
Merge this into the app's existing Next.js configuration:
ts
transpilePackages: ['@acme/ui']
Import the component through @acme/ui/button. Use it from a client component when passing event handlers. Do not import ../../packages/ui/src/button from the app. Next.js can transpile local packages through transpilePackages.
If the shared component uses Tailwind utilities, configure source detection for its directory. With the shown root-level app/ layout and Tailwind 4, the app stylesheet can include @source "../../../packages/ui/src"; after the Tailwind import. The relative path changes if you use src/app/. Verify a class used only inside the package in a production build.
A plain Node service cannot necessarily execute source TSX exports. For packages consumed outside Next.js, choose a build step with runtime-compatible exports and build them before their consumers.
Prompt — extract a package
Prompt
Use vibefield-monorepo if available. Extract [shared component or domain logic]
into a package with explicit exports. Add workspace dependencies to its consumers.
Keep browser-safe UI separate from server-only code. Choose source exports or
built output based on those consumers. Preserve one root install and lockfile.
Verify a production consumer build and show the dependency direction.
5. Pick the data and service stack deliberately
You can ship a content site without a database. When the first feature needs persistence, choose one data layer and give it an owner.
Syvon-style shared data: beta-v4 has a Prisma database package used by multiple apps. Use that pattern when applications share domain data and migrations.
VibeField-style app data: VibeField uses Drizzle with libSQL and keeps its current server code in the web app. This is a different stack, not an extra layer on top of Prisma.
Separate service: add one for a real process requirement such as a persistent connection, background work or media processing. Add services/* to the workspace only then. Browser clients talk to it over an explicit API; they do not import its server implementation.
Keep each app's .env.local private and commit only a secret-free .env.example. List variable names and owners. Never put a database token in a NEXT_PUBLIC_ variable. Give every local process a distinct port and document which process runs migrations.
Prompt — add persistence only if needed
Prompt
This feature needs to store [data]. Evaluate an app-owned data module versus a
shared package, using our existing stack. Choose one database/ORM combination.
Define the server API, input validation, environment variable owners and a single
migration runner. Implement one read/write flow and test the failure cases.
Do not create or alter a production database as part of this local setup.
6. Check the result
Run your app's lint, typecheck, behavior tests and production build. In the workspace, run the root scripts after ensuring each relevant package defines them. Test one shared component or function through its consuming app.
sh
pnpm lint
pnpm typecheck
pnpm test
pnpm build
Add and configure the test runner for your first feature before using the test command. A skipped or missing test script is not a passing test. Also open the app at phone and desktop sizes, navigate between routes, refresh a nested URL and inspect a deliberate failure. Record any check blocked by the local environment.
7. Prepare hosting
Vercel: create one project per deployable app. For this workspace, the web app root is apps/web; allow access to shared workspace sources outside it and verify the root lockfile is used. See Vercel's monorepo guidance.
Railway: an isolated app can use its subdirectory as the service root. A shared workspace needs the repository build context, with filtered build/start commands selecting the app and its dependencies. For example, build with pnpm --filter @acme/web... build and start with pnpm --filter @acme/web start. Ensure the app listens on Railway's supplied port. See Railway's distinction between isolated and shared monorepos.
Do not copy the same Root Directory setting between providers without checking their build context. Do not deploy the entire beta-v4 stack just to host a Next.js app.
Prompt — prepare deployment
Prompt
Use vibefield-deploy-app if installed. Prepare [Vercel / Railway] for [app].
Inspect its workspace dependencies and choose the correct build context.
Document install, build, start, port, environment and migration ownership.
Run the production checks and identify what needs persistent storage.
Prepare the configuration; do not publish it or change remote settings yet.
What is ready, and what comes next
You should now have a working app, declared package boundaries if you chose a monorepo, reproducible local commands and a hosting plan. The next milestone is one complete product journey with a verified preview deployment, not more empty folders.
The starter skill drafts are a separate deliverable from this guide. Their catalog pages show their availability; do not treat the presence of a guide link as a released download.
Source references: Next.js installation, create-next-app options, and pnpm workspaces. Architecture examples were inspected in the local Syvon beta-v4 and VibeField repositories on 2026-11-13. The guide has not yet been executed end-to-end in a fresh online project.
Try the complete shared-package example
Download the shared-package workspace. It contains a Next.js app, a pure @guide/task-core package, runtime and type exports, a workspace dependency, and a consumer test. React renders the UI; Next.js supplies the application framework and routing; pnpm installs and links the workspace; the shared package owns the task-count formatting rule.
From the extracted examples/shared-packages root, run pnpm install, pnpm test, pnpm typecheck, and pnpm build. Commit the generated lockfile in your project. pnpm dev shows a page with "2 tasks". Change the app's argument to 1 and confirm "1 task" in development and the production build. The package can also be tested without installation using node --test packages/task-core/test.cjs; that checks public export resolution, not the Next.js build.
Inspect [WORKSPACE] and its package-manager conventions. Explain whether sharing
[UTILITY OR COMPONENT] solves a real need. If so, create one package with explicit
public exports and a workspace dependency from its consumer. Keep packages free
of app imports and client code free of secrets. Verify exports, types, development,
and production build, recording any install or service limitation honestly.
If an import fails, check root installation, the package name, export subpath, and dependency declaration before adding aliases. If React is duplicated, inspect peer dependencies and installed versions. If a server-only import reaches a client bundle, move that boundary rather than hiding the error. Keep an app-local @/* alias distinct from public package exports.
Frequently asked questions
What is a next.js app?
It is an application built with the Next.js React framework, with framework conventions for routing, rendering, and server behavior. The folder and scripts above show where those responsibilities live.
Is Next.js basically React?
It uses React for UI, and adds application framework behavior. A shared formatting utility does not need either framework; a reusable React component needs the appropriate React types and peer dependencies.
Is monorepo better for AI?
A shared repository can expose related code, but it is not evidence of better agent performance. Clear instructions, package boundaries, and runnable checks matter. This research contains no benchmark proving a monorepo improves an agent.
Should I use monorepo or not?
Use one when multiple deployables or genuinely shared code benefit from coordinated changes. Keep a single app simple when there is no shared boundary to maintain. Continue to Build a component library when shared UI becomes the actual task.
Start a Next.js app the right way
Get one working feature first, in a layout that can grow into shared packages without imports breaking later.