Fast doesn’t mean sloppy. At Nomey, clean code is the baseline — not a stretch goal. We move fast because our code is predictable, modular, and boring in the best way. Every time someone adds something ugly or clever “just to get it done,” it slows down everyone else. We don’t tolerate that.

🧱 Philosophy

We aren’t breaking new ground. You’re not writing a new framework.
  • Clarity > cleverness
  • Convention > invention
  • Simplicity > premature optimization
We value code that is:
  • Easy to delete
  • Easy to extend
  • Easy to understand at a glance
If it’s hard to name, hard to test, or hard to place — it’s probably the wrong shape.

🧭 Stack & Framework

We use the T3 Stack — Next.js (App Router), TypeScript, tRPC, Prisma — plus Tailwind, Zod, and some custom integrations. The principles:
  • Lean modules with strict boundaries
  • End-to-end types
  • Minimal boilerplate
  • Feature isolation
  • No extra magic, no reinvented wheels

📁 File Structure & Modularity

  • Each feature lives in /features/{feature}
  • Each feature folder has its own package.json to mark it as package-private
  • You cannot import internal files from another module — this is enforced by tooling
  • All public types and functions must be exported through that module’s index.ts
  • Design modules as black boxes with clean public APIs

🏗️ Libraries & Factory Exports

  • Low-level clients and integrations live in /lib as pure factory exports
  • Example: lib/stripe used by both features/payments and features/kyc
  • This avoids re-initialization on Next.js warm starts and keeps features clean

🧰 Existing Utilities & Patterns Before writing new code, check if the functionality already exists: Reuse existing utilities and helpers from /lib and /features/shared Prefer composition over duplication — don’t reinvent what’s already solved Always use our shared systems for standard functionality like Logging, Error handling, Validation, etc. No re-inventing the wheel — if you find yourself writing a utility, check if it already exists in our shared libraries or features.

🧩 Naming & Patterns

  • Hooks: useXyz.ts
  • Main screen components: XyzView.tsx
  • Composables: XyzCard.tsx or XyzRow.tsx
  • Zod models: XyzModel.ts
  • Form inputs: XyzInput.tsx
Keep files short, single-purpose, and names clear and boring.

🌐 API Conventions

  • Use tRPC for internal communication
  • Use REST only for external integrations (NextAuth, webhooks, Mux, etc)
  • Don’t write wrappers around HTTP unless absolutely necessary
  • Calling your own API routes directly from the frontend is wrong

🗺️ Layouts & Pages

  • Layouts live in features/shared
  • Pages live inside their feature modules

📺Assets

  • Image assets are stored in webp format

🧼 Formatting & Type Safety

  • Prettier formats code — don’t fight it
  • ESLint enforces rules — fix violations before PR
  • TypeScript strict mode is mandatory
  • If lint or type checks fail, the PR is a no-go

🧪 Testability

  • Write code that’s easy to test — even if no tests exist yet
  • Keep logic out of components
  • Extract pure functions when possible
  • Decouple views, state, and side-effects
  • 100% test coverage is not required but test-ready design is expected

🚫 What We Avoid

  • Over-abstracted hooks
  • Clever one-liners or unreadable chains
  • Rewriting utilities just to “improve” trivial things
  • Nested ternaries inside JSX
  • Smugness disguised as “cleverness”

✅ Summary

  • Use the stack, don’t fight it
  • Respect module boundaries and encapsulation
  • Write boring, readable, testable code
  • Clean code is the foundation of moving fast