OneApp Docs
PackagesCore

@repo/shared

Shared constants, enums, and configuration values for the monorepo. API routes, validation rules, time durations, feature flags. Single source of truth for magic numbers. Type-safe enums for roles and statuses.

Quick Start

Add shared constants in 2 minutes:

pnpm add @repo/shared

No more magic numbers, consistent validation, type-safe enums. Skip to Quick Start →

Why @repo/shared?

Magic numbers scattered everywhere (10485760 for 10MB file limit). API routes hard-coded differently (/api/auth/login vs /api/authentication/login). Validation rules inconsistent (password min 8 chars in web, 6 in mobile). Enum values differ (ADMIN vs admin). Time durations duplicated (7 * 24 * 60 * 60 * 1000 for a week).

@repo/shared solves this with centralized constants, enums, and config values for the entire monorepo.

Production-ready with type-safe enums, semantic constants, validation rules, and human-readable values for debugging.

Use cases

  • Consistent API routes — Same /api/auth/login path everywhere
  • Validation rules — Same password/email/username rules across apps
  • Time durationsTIME.WEEK instead of calculating milliseconds
  • File size limitsFILE.MAX_SIZE instead of 10485760
  • Type-safe enumsUserRole.ADMIN with autocomplete and type checking

How it works

@repo/shared exports constants and enums from a single package:

import { API_ROUTES, VALIDATION, TIME, UserRole } from "@repo/shared";

// API routes - consistent paths
fetch(API_ROUTES.AUTH.LOGIN, { method: "POST" });

// Validation - consistent rules
if (password.length < VALIDATION.PASSWORD.MIN_LENGTH) {
  throw new Error("Password too short");
}

// Time constants - no more magic numbers
const sessionExpiry = Date.now() + TIME.WEEK;

// Type-safe enums - autocomplete and type checking
function hasAccess(role: UserRole): boolean {
  return role === UserRole.ADMIN; // ✅ Type-safe
}

Uses string enums (human-readable in logs), semantic constants (self-documenting), and configuration objects (structured data).

Key features

API route constants — Centralized /api/* paths for all endpoints

Validation rules — Password, email, username constraints

Time constantsSECOND, MINUTE, HOUR, DAY, WEEK in milliseconds

File constants — Max sizes, allowed MIME types

Type-safe enums — UserRole, Status, Plan, Feature with string values

Error codes — Standardized error codes for all error types

Quick Start

1. Install the package

pnpm add @repo/shared

2. Use API routes for consistency

app/api/auth/login/route.ts
import { API_ROUTES, HTTP_STATUS } from "@repo/shared";

export async function POST(request: Request) {
  // Use constants for API responses
  return Response.json({ message: "Login successful" }, { status: HTTP_STATUS.OK });
}
app/components/LoginForm.tsx
"use client";

import { API_ROUTES } from "@repo/shared";

export function LoginForm() {
  const handleLogin = async () => {
    // Same route constant as the API route
    const response = await fetch(API_ROUTES.AUTH.LOGIN, {
      method: "POST",
      body: JSON.stringify({ email, password }),
    });
  };

  return <form>{/* Form fields */}</form>;
}

3. Apply validation constants

lib/validation.ts
import { VALIDATION, PATTERNS } from "@repo/shared";

export function validatePassword(password: string): boolean {
  return password.length >= VALIDATION.PASSWORD.MIN_LENGTH && password.length <= VALIDATION.PASSWORD.MAX_LENGTH;
}

export function validateEmail(email: string): boolean {
  return email.length <= VALIDATION.EMAIL.MAX_LENGTH && PATTERNS.EMAIL.test(email);
}
app/api/users/route.ts
import { validatePassword, validateEmail } from "#/lib/validation";
import { HTTP_STATUS } from "@repo/shared";

export async function POST(request: Request) {
  const { email, password } = await request.json();

  if (!validateEmail(email) || !validatePassword(password)) {
    return Response.json({ error: "Invalid email or password" }, { status: HTTP_STATUS.BAD_REQUEST });
  }

  // Create user
}

4. Use type-safe enums

types/user.ts
import { UserRole, Status } from "@repo/shared/enums";

export interface User {
  id: string;
  email: string;
  role: UserRole; // Type-safe enum
  status: Status; // Type-safe enum
}
lib/permissions.ts
import { UserRole, Feature } from "@repo/shared/enums";

export function canAccessFeature(role: UserRole, feature: Feature): boolean {
  switch (role) {
    case UserRole.ADMIN:
      return true; // Admins have access to all features
    case UserRole.USER:
      return feature !== Feature.API_ACCESS; // Users can't use API
    case UserRole.GUEST:
      return false; // Guests have no feature access
  }
}

That's it! You now have consistent API routes, validation rules, and type-safe enums across your entire app.

Use time constants for readability

Replace magic numbers with semantic constants:

import { TIME } from "@repo/shared";

// ❌ Before: Magic number
const cacheExpiry = Date.now() + 604800000;

// ✅ After: Self-documenting
const cacheExpiry = Date.now() + TIME.WEEK;

Technical Details

For Developers: Technical implementation details

Overview

PropertyValue
Locationpackages/shared
PurposeConstants, enums, config values

Export Paths

PathDescription
@repo/sharedAll exports
@repo/shared/constantsConstant values
@repo/shared/enumsEnum definitions

Constants

API Constants

import { API_ROUTES, HTTP_STATUS } from "@repo/shared/constants";

// API routes
API_ROUTES.AUTH.LOGIN; // "/api/auth/login"
API_ROUTES.AUTH.REGISTER; // "/api/auth/register"
API_ROUTES.USERS.LIST; // "/api/users"
API_ROUTES.USERS.GET; // "/api/users/:id"

// HTTP status codes
HTTP_STATUS.OK; // 200
HTTP_STATUS.CREATED; // 201
HTTP_STATUS.NOT_FOUND; // 404
HTTP_STATUS.INTERNAL_ERROR; // 500

Validation Constants

Security Best Practice

Use these validation constants consistently to enforce the same rules across client and server.

import { VALIDATION } from "@repo/shared/constants";

// highlight-start
VALIDATION.PASSWORD.MIN_LENGTH; // 8
VALIDATION.PASSWORD.MAX_LENGTH; // 128
// highlight-end
VALIDATION.USERNAME.MIN_LENGTH; // 3
VALIDATION.USERNAME.MAX_LENGTH; // 30
VALIDATION.EMAIL.MAX_LENGTH; // 254

Time Constants

import { TIME } from "@repo/shared/constants";

TIME.SECOND; // 1000
TIME.MINUTE; // 60000
TIME.HOUR; // 3600000
TIME.DAY; // 86400000
TIME.WEEK; // 604800000

// Common durations
TIME.SESSION_DURATION; // 7 * DAY
TIME.TOKEN_EXPIRY; // 15 * MINUTE
TIME.CACHE_TTL; // 5 * MINUTE

File Constants

import { FILE } from "@repo/shared/constants";

FILE.MAX_SIZE; // 10 * 1024 * 1024 (10MB)
FILE.ALLOWED_IMAGE_TYPES; // ["image/jpeg", "image/png", "image/webp"]
FILE.ALLOWED_DOCUMENT_TYPES; // ["application/pdf", "text/plain", ...]

Enums

Type-Safe Enums

Use string enums for better debugging and serialization. Values are human-readable in logs and databases.

User Role

import { UserRole } from "@repo/shared/enums";

// highlight-start
enum UserRole {
  ADMIN = "admin",
  USER = "user",
  GUEST = "guest"
}
// highlight-end

function hasAccess(role: UserRole): boolean {
  return role === UserRole.ADMIN;
}

Status

import { Status } from "@repo/shared/enums";

enum Status {
  PENDING = "pending",
  ACTIVE = "active",
  INACTIVE = "inactive",
  DELETED = "deleted"
}

Plan

import { Plan } from "@repo/shared/enums";

enum Plan {
  FREE = "free",
  PRO = "pro",
  ENTERPRISE = "enterprise"
}

Feature

import { Feature } from "@repo/shared/enums";

enum Feature {
  AI_CHAT = "ai_chat",
  DOCUMENT_EDITOR = "document_editor",
  COLLABORATION = "collaboration",
  API_ACCESS = "api_access"
}

Configuration

Default Config

import { DEFAULT_CONFIG } from "@repo/shared";

DEFAULT_CONFIG.pagination.pageSize; // 10
DEFAULT_CONFIG.pagination.maxPageSize; // 100
DEFAULT_CONFIG.rateLimit.requests; // 100
DEFAULT_CONFIG.rateLimit.windowMs; // 60000

Feature Flags Defaults

import { DEFAULT_FEATURES } from "@repo/shared";

DEFAULT_FEATURES[Plan.FREE]; // { ai_chat: false, ... }
DEFAULT_FEATURES[Plan.PRO]; // { ai_chat: true, ... }

Error Codes

import { ERROR_CODES } from "@repo/shared";

ERROR_CODES.AUTH.INVALID_CREDENTIALS; // "AUTH_001"
ERROR_CODES.AUTH.SESSION_EXPIRED; // "AUTH_002"
ERROR_CODES.USER.NOT_FOUND; // "USER_001"
ERROR_CODES.API.RATE_LIMITED; // "API_001"

Regex Patterns

import { PATTERNS } from "@repo/shared";

PATTERNS.EMAIL; // Email validation regex
PATTERNS.URL; // URL validation regex
PATTERNS.SLUG; // Slug validation regex
PATTERNS.UUID; // UUID validation regex
PATTERNS.PHONE; // Phone number regex

On this page