# Principles

Decision-making constraints that drive stack choices. Every technology decision should trace back to one or more of these principles.

---

## Core Principles

### 1. Libraries over services

Own your auth, data, and logic. Prefer libraries over managed services where practical.

- No per-user or per-request pricing surprises
- Full control over data and behavior
- Minimize vendor lock-in
- Can run locally without external dependencies

**Exceptions:** Accept managed services when they meet these criteria:

| Criterion | Requirement |
|-----------|-------------|
| **Affordable** | Generous free tier, predictable scaling costs |
| **Practical** | Self-hosting is complex or impractical |
| **Swappable** | Uses standard protocols (S3, PostgreSQL, SMTP) OR has clear migration path |
| **Essential** | Provides capability hard to replicate (serverless DB, edge hosting, graph DB) |

Services meeting 3+ criteria are acceptable. Document the trade-off in stack docs.

---

### 2. Lightweight over feature-rich

Smaller bundles, faster loads, less complexity. Only pay for what you use.

- Bundle size matters for user experience
- Fewer dependencies = fewer vulnerabilities
- Simpler tools are easier to understand and debug
- Avoid "kitchen sink" libraries

---

### 3. Standard protocols

Use industry-standard protocols and APIs. Swap vendors without rewriting code.

- S3 API for object storage
- OAuth 2.0 for social auth
- PostgreSQL for relational data
- HTTP caching semantics
- SMTP/REST for email

---

### 4. Free tier friendly

Start at $0/month. Scale costs with actual usage.

- Development must work without paid accounts
- Free tier must be sufficient for MVP/testing
- Pricing should scale linearly with usage
- No upfront commitments required

---

### 5. Svelte-native first

Prefer tools built for Svelte over adapted React libraries.

- Better integration with Svelte's reactivity model
- Smaller bundles (no React compatibility layer)
- Better developer experience
- Maintained by Svelte community

---

### 6. No code generation

Runtime-only tooling. Avoid build-step dependencies.

- No generated files to maintain or commit
- No "regenerate after schema change" workflows
- Simpler CI/CD pipelines
- Easier to understand what code does

> **Note on Better Auth:** Better Auth offers both CLI schema generation (`bunx @better-auth/cli generate`) and manual schema definition. This project uses **manual schemas** to maintain this principle. See [stack/data/drizzle.md](../stack/data/drizzle.md) for the hand-written schema approach.

---

### 7. Speed is a feature

Fast runtime, fast builds, fast DX. Performance is non-negotiable.

- User-facing performance affects conversion
- Developer experience affects productivity
- Fast feedback loops improve code quality
- Benchmark before adopting

---

## Evaluating New Tools

When considering a new dependency:

| Question | Principle |
|----------|-----------|
| Does it require a service account? | Libraries over services |
| What's the bundle/install size? | Lightweight over feature-rich |
| Does it use standard protocols? | Standard protocols |
| Is there a free tier for dev? | Free tier friendly |
| Is there a Svelte-native option? | Svelte-native first |
| Does it require code generation? | No code generation |
| Is it fast? | Speed is a feature |

If a tool fails multiple checks, look for alternatives. If no alternative exists, document the exception.

---

## Documenting Exceptions

When a principle must be violated, document it in the relevant stack file:

```markdown
> **Exception to [Principle Name]:** [Tool/choice] violates this principle because [reasoning]. No viable alternative exists that satisfies [requirement].
```

If exceptions accumulate for a principle, reconsider the principle.
