@prism/core - Foundational infrastructure for Next.js applications built with TypeScript, Tailwind CSS, Drizzle ORM, and AI capabilities.
A Next.js monorepo that can be used as a standalone package by apps in separate repositories. Uses pnpm workspaces (pnpm-workspace.yaml) to manage multiple applications and shared packages.
prism/
βββ packages/
β βββ ui/ # Shared UI components
β βββ database/ # Database layer (Drizzle ORM + Neon PostgreSQL)
β βββ intelligence/ # AI tasks and utilities
β βββ logger/ # Logging infrastructure
β βββ utilities/ # Shared utility functions
β βββ system-sheet/ # System information page
β βββ authentication/ # Authentication utilities
βββ apps/
β βββ web/ # Sample application (generated apps go here)
βββ tools/ # CLI tools and generator
βββ package.json # @prism/core configuration
- Node.js >= 25.0.0 (see
enginesinpackage.jsonand.nvmrc) - pnpm 10.x (
corepack enablethencorepack prepare [email protected] --activate, or install globally)
Install all dependencies for the monorepo:
pnpm installThis will install dependencies for all workspaces (apps and packages).
Run the web app in development mode:
pnpm run devThis will:
- Kill any existing dev servers on port 3000
- Start the web app
- Web app: http://localhost:3000
Or run the web app:
# Web app (http://localhost:3000)
pnpm run dev:webNote: The apps/web directory is kept as a sample. You can generate new apps using prism generate <app-name> (after pnpm run setup) or pnpm run prism generate <app-name>, which will create them in the apps/ directory.
pnpm run dev- Run web app in development mode (kills existing servers first)pnpm run dev:web- Run web app only (port 3000)pnpm run dev:kill- Kill all development servers on port 3000
pnpm run build- Build all appspnpm run build:web- Build web app only
pnpm run start- Start all production serverspnpm run start:web- Start web app (port 3000)
pnpm run typecheck- Run TypeScript type checking across all workspacespnpm run lint- Run ESLint across all workspacespnpm run lint:fix- Run ESLint with auto-fixpnpm run format- Format code with Prettierpnpm run format:check- Check code formattingpnpm run quality- Run typecheck, lint, format, and testspnpm run quality:quick- Run typecheck, lint, and format (no tests)
pnpm run test- Run all testspnpm run test:run- Run all tests oncepnpm run test:ui- Run tests with Vitest UI (web app)pnpm run test:coverage- Generate coverage report (web app)
pnpm run database:generate- Generate database migrationspnpm run database:migrate- Run database migrationspnpm run database:push- Push schema changes to databasepnpm run database:studio- Open Drizzle Studio (database GUI)
pnpm run clean- Clean build artifactspnpm run watch- Watch TypeScript files
- Framework: Next.js 16.0.3 (App Router)
- Language: TypeScript 5.9.3 (target: ES2022)
- Styling: Tailwind CSS 4.1.17
- Monorepo: pnpm workspaces
- apps/web: Sample Next.js application (reference implementation)
- apps/*: Generated apps (created via
prism generate <name>orpnpm run prism generate <name>)
- packages/ui: Shared UI components (Button, Card, Badge, Icon)
- Radix UI primitives
- Class Variance Authority for variants
- Material Symbols Rounded icons (via Google Fonts)
- packages/database: Database layer
- Drizzle ORM 0.44.7
- Neon PostgreSQL with @neondatabase/serverless
- packages/utilities: Shared utility functions
cn()- Tailwind class name merger
- Testing: Vitest 4.0.10 with React Testing Library
- Linting: ESLint 9.39.1 with Next.js config
- Formatting: Prettier 3.6.2
- Git Hooks: Husky 9.1.7 with lint-staged
- Fonts: Satoshi (variable font) via
next/font/local
This project uses Vitest for testing. Tests should be placed in files ending with .test.ts or .test.tsx.
# Run tests
pnpm run test
# Run tests with UI
pnpm run test:ui
# Run tests with coverage
pnpm run test:coverageThis project uses Drizzle ORM with Neon PostgreSQL. The database schema is defined in packages/database/source/schema.ts.
import { db } from "@database";
// Both apps can import from the shared database package
const data = await db.query.users.findMany();# Generate migrations from schema changes
pnpm run database:generate
# Apply migrations
pnpm run database:migrate
# Push schema changes directly (development)
pnpm run database:push
# Open Drizzle Studio GUI
pnpm run database:studioApps in separate repositories can import Prism Core as a dependency. The generator handles this automatically:
Option 1: Git Submodule (Recommended - One Deployable Repo)
# Direct mode (recommended after pnpm run setup)
prism generate my-app --path ../my-app
# Or via package.json script
pnpm run prism generate my-app --path ../my-appThis automatically:
- Adds Prism as a git submodule inside your app at
./prism - Uses
file:./prism/packages/...dependencies for fast iteration - Creates a single deployable repo (your app + Prism submodule)
- Allows committing Prism changes from within your app
After updating the submodule, run pnpm run prism:sync from your app root to align scripts, Cursor commands, and shared dependency ranges. Details: SYNC-Prism.md.
Option 2: Git Dependency (Alternative for Deployment)
# Direct mode (recommended after pnpm run setup)
prism generate my-app --path ../my-app --prism-repo "git+https://github.com/thushana/prism.git"
# Or via package.json script
pnpm run prism generate my-app --path ../my-app --prism-repo "git+https://github.com/thushana/prism.git"This creates a deployable app that Vercel can build. Prism will be cloned from GitHub during the build process. Note: You won't be able to commit Prism changes from within your app with this approach.
Import in your app:
// Import UI components
import { Button, Card } from "@prism/core/ui";
// Import database
import { db } from "@prism/core/database";
// Import AI utilities
import { getAIModel } from "@prism/core/intelligence";
// Import logger
import { logger } from "@prism/core/logger";
// Import utilities
import { cn } from "@prism/core/utilities";
// Import system-sheet (for system information pages)
import { SystemSheetPage } from "@prism/core/system-sheet";
// Import authentication utilities
import { requireApiAuthentication } from "@prism/core/authentication";Apps within this monorepo can use direct package imports:
// Import UI components
import { Button, Card } from "@ui";
// Import database
import { db } from "@database";
// Import utilities
import { cn } from "@utilities";
// Import logger (client-side)
import { logger, logSuccess } from "@logger/client";
// Import logger (server-side)
import { serverLogger as logger, logStart } from "@logger/server";
// Import system-sheet
import { SystemSheetPage } from "@system-sheet";
// Import authentication
import { requireApiAuthentication } from "@authentication";Prism includes a shared development information page that shows environment details, git status, dependencies, and more.
Add to your app:
// app/dev-sheet/page.tsx
import { DevSheetPage } from "@dev-sheet";
import type { DevSheetData } from "@dev-sheet";
import { headers } from "next/headers";
export const dynamic = "force-dynamic";
async function fetchDevSheetData(): Promise<DevSheetData | null> {
try {
// Construct absolute URL for server component fetch
// In server components, relative URLs don't work with fetch()
const headersList = await headers();
const host = headersList.get("host") || "localhost:3001";
const protocol = process.env.VERCEL_URL
? "https"
: host.includes("localhost")
? "http"
: "https";
const baseUrl = `${protocol}://${host}`;
const res = await fetch(`${baseUrl}/api/dev-sheet`, {
cache: "no-store",
});
if (!res.ok) return null;
const json = await res.json();
return json?.success ? json.data : null;
} catch {
return null;
}
}
export default async function Page() {
// Hide in production unless explicitly enabled
if (
process.env.NODE_ENV === "production" &&
process.env.ENABLE_DEV_SHEET !== "true"
) {
return null;
}
const data = await fetchDevSheetData();
return <DevSheetPage data={data} />;
}Note: Your app needs to implement an /api/dev-sheet route that returns development data. See the generator templates for a reference implementation.
Prism Core uses the exports field in package.json to expose packages as subpath imports (e.g., @prism/core/ui).
Important Notes:
-
TypeScript Source Files: The exports point directly to TypeScript source files (
.ts), not compiled JavaScript. This works because:- Next.js/Turbopack handles TypeScript compilation and bundling
- TypeScript path mappings in
tsconfig.jsonresolve these imports - This is designed for monorepo/internal use or apps using TypeScript with proper tooling
-
For External Consumers: If you plan to publish this package or use it in apps without TypeScript tooling:
- Consider adding a build step to compile TypeScript to JavaScript
- Update exports to point to compiled
.jsfiles - Or ensure consuming apps have TypeScript configured with path mapping support
-
Current Exports:
@prism/core/ui- UI components@prism/core/database- Database layer@prism/core/intelligence- AI utilities@prism/core/logger- Logging infrastructure@prism/core/utilities- Utility functions@prism/core/dev-sheet- Development info page
Each package follows the same structure:
packages/[package-name]/
βββ source/ # Source files
β βββ index.ts # Main export file
βββ package.json # Package configuration
βββ tsconfig.json # TypeScript configuration
This monorepo is designed to deploy each app independently on Vercel. See DEPLOYMENT-Prism.md for detailed instructions.
- Web App: Deploy from
apps/webroot directory (sample) - Generated Apps: Deploy from
apps/<app-name>root directory
Each app can be deployed independently from the same GitHub repository by setting different root directories in Vercel.
- Web:
yourdomain.comorwww.yourdomain.com - Generated apps: Configure per app in Vercel
Neon PostgreSQL is used for both development and production:
- Configure via
DATABASE_URLenvironment variable - Use pooled connection for runtime queries
- Use unpooled connection (
DATABASE_URL_UNPOOLED) for migrations - Serverless-friendly with Neon's serverless driver
Copy .env.example to .env.local and fill in your environment variables. Never commit .env.local or any files containing secrets.
Environment variables can be set per-app in Vercel or at the root level for all apps.
Configure log levels using environment variables:
- Server-side:
LOG_LEVEL(default: "info" in production, "debug" in development) - Client-side:
NEXT_PUBLIC_LOG_LEVEL(default: "info" in production, "debug" in development)
Valid log levels: error, warn, info, http, verbose, debug, silly
Example .env.local:
LOG_LEVEL=debug
NEXT_PUBLIC_LOG_LEVEL=debugSee docs/LOGGER-Prism.md for full logger documentation.
- pnpm workspaces
- Turborepo - Consider for larger monorepos
- Make changes in the appropriate workspace
- Run
pnpm run qualityto ensure code quality - Commit with descriptive messages (see
.cursor/commands/COMMITMESSAGE.md) - Pre-commit hooks will automatically format and lint your code
This project is private and not licensed for public use.