Decision Records
Relevant source files
The following files were used as context for generating this wiki page:
Decision Records in the wrelik-kit repository serve as the authoritative log for architectural choices, vendor selections, and development standards. This system ensures that all Wrelik applications maintain consistency, reduce technical debt, and adhere to a unified infrastructure strategy.
The primary goal is to enforce an adapter-first architecture where applications interact with third-party services exclusively through shared internal packages. This approach isolates vendor-specific SDKs and provides a stable integration boundary that facilitates maintenance and future migrations.
Sources: README.md:3-12, DECISIONS.md:14-18
Architectural Principles
The project's architecture is governed by core principles that dictate how integrations are built and consumed. These principles prioritize reliability, vendor agnosticism, and strict multi-tenant safety.
- Adapter-First Strategy: Direct vendor SDK usage is prohibited in application repositories.
- Infrastructure as Code: The repository is treated as long-lived infrastructure, prioritizing "boring" and stable technology.
- Explicit Boundaries: Every package must define a minimal surface area and avoid mock logic or stubs.
Sources: README.md:14-21, DECISIONS.md:14-18
Vendor Selection Strategy
Vendor choices are made based on developer experience (DX), scalability, and compatibility with the serverless ecosystem. The following table summarizes the current standardized stack:
| Domain | Vendor | Shared Package | Justification |
|---|---|---|---|
| Auth | Clerk | @wrelik/auth | Best-in-class Next.js support and DX. |
| Database | Neon (Prisma) | @wrelik/db | Serverless Postgres scaling and Prisma DX. |
| Storage | Cloudflare R2 | @wrelik/storage | S3 compatibility and zero egress fees. |
| Analytics | PostHog | @wrelik/analytics | Open source and strong product analytics. |
| Errors | Sentry | @wrelik/errors | Industry standard for error tracking. |
| Resend | @wrelik/email | Modern API and React-based templates. | |
| Jobs | Inngest | @wrelik/jobs | Serverless-friendly event-driven queue. |
Sources: DECISIONS.md:3-12
Implementation of Wrappers
The decision to use wrappers instead of direct SDKs is a fundamental architectural requirement. This design pattern provides three primary benefits:
- Lock-in Mitigation: Changing a vendor only requires updates to the specific adapter package in this repo, rather than a full-scale refactor across multiple applications.
- Standardization: Enforces naming conventions (e.g., for analytics events) and centralized error handling logic.
- API Simplification: Only necessary functionality is exposed, reducing the learning curve for application developers.
Sources: DECISIONS.md:14-18, README.md:46-48
Integration Flow Diagram
The following diagram illustrates how applications interact with third-party vendors through the @wrelik/* boundary.
This diagram shows the explicit boundary where applications only communicate with internal adapters, which in turn communicate with external vendors.
Sources: README.md:7-10, README.md:46-48
Governance and Enforcement
Standards are enforced through both configuration and repository governance processes.
ESLint Restrictions
The project uses no-restricted-imports within @wrelik/eslint-config to programmatically prevent developers from bypassing adapters.
// packages/eslint-config/index.js
'no-restricted-imports': [
'error',
{
paths: [
{ name: '@clerk/nextjs', message: 'Please use @wrelik/auth instead.' },
{ name: '@prisma/client', message: 'Please use @wrelik/db instead.' },
{ name: 'resend', message: 'Please use @wrelik/email instead.' },
{ name: 'posthog-node', message: 'Please use @wrelik/analytics instead.' },
{ name: 'inngest', message: 'Please use @wrelik/jobs instead.' },
],
patterns: [
{ group: ['@aws-sdk/*'], message: 'Please use @wrelik/storage instead.' },
],
},
],
Sources: packages/eslint-config/index.js:15-42
Configuration Management
Environment variables are managed using Zod to ensure type safety and validation at the configuration layer.
// packages/config/src/index.ts
export function createEnv<T extends z.ZodRawShape>(schema: T) {
const envSchema = z.object(schema);
const result = envSchema.safeParse(process.env);
if (!result.success) {
throw new Error('Invalid environment variables');
}
return result.data;
}
Sources: packages/config/src/index.ts:8-19
Release and Versioning
The repository utilizes Changesets for managing versions. Any change that affects application behavior must be documented in a changeset, ensuring that downstream applications are aware of breaking changes or updates.
- Changeset Generation: Developers run
pnpm changeset. - Versioning: The "Release" GitHub Action opens a "Version Packages" PR.
- Publishing: Merging the PR triggers the release to NPM.
Sources: CONTRIBUTING.md:18-31, package.json:20-22
Summary
The Decision Records system within wrelik-kit creates a disciplined development environment by mandating the use of vendor-agnostic adapters. Through a combination of architectural rules, automated linting, and strict release management, the project ensures that the Wrelik ecosystem remains flexible, secure, and maintainable.