This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Development
pnpm dev # Start dev server with Turbopack
pnpm build # Build all packages
pnpm type-check # Run TypeScript checks
pnpm lint # Run linting
pnpm test # Run tests (validates locales)
# Translation (only modify en/ files, CI auto-generates others)
pnpm --filter @onruntime/web translate # Generate missing translations
pnpm --filter @onruntime/web translate:init # Initialize all translations locally
# Run commands for specific package
pnpm --filter @onruntime/web dev
pnpm --filter @onruntime/translations build/
├── apps/
│ └── web/ # Next.js 16 website (@onruntime/web)
├── packages/
│ ├── translations/ # i18n library (@onruntime/translations)
│ └── next-sitemap/ # Dynamic sitemap generation (@onruntime/next-sitemap)
├── turbo.json # Turborepo configuration
└── pnpm-workspace.yaml # pnpm workspace config
- app/: Next.js App Router pages and API routes (under
[locale]/) - components/: React components (ui/, layout/, marketing/)
- services/: External API clients with lazy initialization
- constants/: Static data (projects, agencies, services, team members)
- content/: MDX content (glossary, legal pages)
- lib/: Utilities and helpers
- locales/: Translation files (see
locales/README.mdfor conventions) - types/: TypeScript type definitions
Services: Use lazy initialization for external API clients to avoid build failures when env vars are missing in CI:
// services/email.ts - Proxy pattern for lazy init
export const resend = new Proxy({} as Resend, {
get(_, prop) {
if (!instance) {
instance = new Resend(env.RESEND_API_KEY);
}
return instance[prop as keyof Resend];
},
});
// services/join.ts - Client pattern
export const joinClient = {
async jobs() { ... },
async job(id) { ... },
};Environment Variables: Managed via @t3-oss/env-nextjs in env.ts. Validation is skipped in CI (skipValidation: !!process.env.CI).
API Routes: Use unstable_cache from Next.js for caching external API responses.
Translations: Uses @onruntime/translations package. Only edit files in locales/en/ - other locales are auto-generated by CI. Namespace path matches file path from locales/{locale}/.
// Server Components
import { getTranslation } from "@/lib/translations.server";
const { t } = await getTranslation("layout/footer");
// Client Components
import { useTranslation } from "@onruntime/translations/react";
const { t } = useTranslation("layout/footer");See apps/web/src/locales/README.md for full naming conventions and usage patterns.
Required for runtime (optional for build due to skipValidation in CI):
RESEND_API_KEY: Email sending via ResendJOIN_API_KEY: Job listings from join.com APINEXT_PUBLIC_APP_URL: App URL (defaults to https://onruntime.com)