kata-context 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +6 -0
- package/.github/dependabot.yml +13 -0
- package/.github/workflows/release.yml +68 -0
- package/.planning/PROJECT.md +103 -0
- package/.planning/REQUIREMENTS.md +61 -0
- package/.planning/ROADMAP.md +59 -0
- package/.planning/STATE.md +45 -0
- package/.planning/config.json +20 -0
- package/.planning/phases/01-foundation/01-01-PLAN.md +158 -0
- package/.planning/phases/01-foundation/01-01-SUMMARY.md +123 -0
- package/.planning/phases/01-foundation/01-02-PLAN.md +262 -0
- package/.planning/phases/01-foundation/01-02-SUMMARY.md +153 -0
- package/.planning/phases/01-foundation/01-RESEARCH.md +380 -0
- package/.planning/phases/01-foundation/01-foundation-VERIFICATION.md +232 -0
- package/.planning/research/ARCHITECTURE.md +601 -0
- package/.planning/research/FEATURES.md +242 -0
- package/.planning/research/PITFALLS.md +436 -0
- package/.planning/research/STACK.md +299 -0
- package/.planning/research/SUMMARY.md +409 -0
- package/README.md +82 -0
- package/biome.json +42 -0
- package/package.json +28 -0
- package/scripts/rescue-main.sh +79 -0
- package/src/index.ts +6 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Feature Landscape: TypeScript/Vercel Project Scaffold
|
|
2
|
+
|
|
3
|
+
**Domain:** TypeScript serverless project scaffolding for Vercel
|
|
4
|
+
**Researched:** 2026-01-29
|
|
5
|
+
**Focus:** v0.1.0 Core Setup milestone
|
|
6
|
+
|
|
7
|
+
## Table Stakes
|
|
8
|
+
|
|
9
|
+
Features users expect. Missing = project feels incomplete or unprofessional.
|
|
10
|
+
|
|
11
|
+
| Feature | Why Expected | Complexity | Scaffolding vs Later | Notes |
|
|
12
|
+
|---------|-------------|------------|---------------------|-------|
|
|
13
|
+
| TypeScript configuration (tsconfig.json) | Modern TS projects require explicit config | Low | **Scaffolding** | Use `strict: true` baseline |
|
|
14
|
+
| ESLint configuration | Code quality enforcement expected | Low | **Scaffolding** | Flat config format (eslint.config.js) |
|
|
15
|
+
| Prettier configuration | Consistent formatting expected | Low | **Scaffolding** | .prettierrc with sensible defaults |
|
|
16
|
+
| .gitignore | Must exclude node_modules, .env, build artifacts | Low | **Scaffolding** | Include Vercel-specific entries |
|
|
17
|
+
| package.json scripts | `dev`, `build`, `test`, `lint` expected | Low | **Scaffolding** | Core developer commands |
|
|
18
|
+
| Vercel serverless structure | `/api` directory with function files | Low | **Scaffolding** | Vercel auto-detects this |
|
|
19
|
+
| Environment variable handling | .env.example documenting required vars | Low | **Scaffolding** | Never commit actual .env files |
|
|
20
|
+
| Node.js version specification | Reproducible builds require pinned version | Low | **Scaffolding** | Use .nvmrc or engines in package.json |
|
|
21
|
+
| README with setup instructions | Developers expect onboarding docs | Low | **Scaffolding** | Basic setup, not full documentation |
|
|
22
|
+
|
|
23
|
+
**Confidence:** HIGH - Based on [Vercel official documentation](https://vercel.com/docs/functions) and [TypeScript best practices](https://www.typescriptlang.org/tsconfig/).
|
|
24
|
+
|
|
25
|
+
## Differentiators
|
|
26
|
+
|
|
27
|
+
Features that set quality projects apart. Not expected, but valued by experienced developers.
|
|
28
|
+
|
|
29
|
+
| Feature | Value Proposition | Complexity | Scaffolding vs Later | Notes |
|
|
30
|
+
|---------|------------------|------------|---------------------|-------|
|
|
31
|
+
| Pre-commit hooks (Husky + lint-staged) | Prevents bad commits from entering repo | Medium | **Scaffolding** | Essential for solo dev maintaining quality |
|
|
32
|
+
| Vitest test configuration | Modern, fast testing with TS support | Medium | **Scaffolding** | Better DX than Jest for Vite/Vercel |
|
|
33
|
+
| Strict TypeScript settings | Catches more bugs at compile time | Low | **Scaffolding** | Enable strictNullChecks, noUncheckedIndexedAccess |
|
|
34
|
+
| Type-checked ESLint rules | TypeScript-specific linting | Low | **Scaffolding** | @typescript-eslint/eslint-plugin |
|
|
35
|
+
| vercel.json configuration | Explicit function memory/duration limits | Low | **Scaffolding** | Avoids surprises in production |
|
|
36
|
+
| GitHub Actions CI workflow | Automated lint/test on PRs | Medium | **Scaffolding** | Simple workflow, not full CD |
|
|
37
|
+
| EditorConfig | Consistent settings across editors | Low | **Scaffolding** | .editorconfig file |
|
|
38
|
+
| VS Code workspace settings | Editor integration for linting/formatting | Low | **Scaffolding** | .vscode/settings.json |
|
|
39
|
+
|
|
40
|
+
**Confidence:** HIGH - Based on [ESLint + Prettier 2026 patterns](https://medium.com/@osmion/prettier-eslint-configuration-that-actually-works-without-the-headaches-a8506b710d21), [Vitest documentation](https://vitest.dev/config/), and [Husky/lint-staged best practices](https://github.com/lint-staged/lint-staged).
|
|
41
|
+
|
|
42
|
+
## Anti-Features
|
|
43
|
+
|
|
44
|
+
Features to explicitly NOT include in scaffolding phase. Common mistakes in project setup.
|
|
45
|
+
|
|
46
|
+
| Anti-Feature | Why Avoid | What to Do Instead |
|
|
47
|
+
|--------------|----------|-------------------|
|
|
48
|
+
| Full GitHub Actions CD pipeline | Premature optimization; Vercel auto-deploys from Git | Use Vercel's built-in Git integration for deployments; CI only for lint/test |
|
|
49
|
+
| Database configuration | Not needed until data layer milestone | Add when implementing storage layer |
|
|
50
|
+
| API routes with business logic | Scaffolding should be empty shell | Create single hello-world health check only |
|
|
51
|
+
| Authentication/authorization | Separate concern, adds complexity | Defer to security milestone |
|
|
52
|
+
| Logging infrastructure | Overengineering for scaffold | Use console.log initially; add structured logging later |
|
|
53
|
+
| Error monitoring (Sentry, etc.) | Not needed until production traffic | Add during production hardening |
|
|
54
|
+
| Complex folder structure | Premature architecture; let structure emerge | Minimal: `/api`, `/src`, `/tests` |
|
|
55
|
+
| Monorepo setup | Single package until proven need | Start simple; refactor if SDKs require |
|
|
56
|
+
| Docker/containerization | Vercel handles deployment; Docker adds complexity | Skip unless local development requires it |
|
|
57
|
+
| Documentation beyond README | Writing docs for unwritten code | Create docs as features ship |
|
|
58
|
+
| Multiple environment configs | One environment (development) is enough to start | Add staging/production configs when needed |
|
|
59
|
+
| Custom build tooling (webpack, rollup) | Vercel handles bundling | Trust Vercel's build system |
|
|
60
|
+
| API versioning | No API to version yet | Add `/v1/` prefix when API stabilizes |
|
|
61
|
+
| Rate limiting | No traffic to limit | Add during production hardening |
|
|
62
|
+
|
|
63
|
+
**Confidence:** HIGH - Based on [Vercel's zero-config philosophy](https://vercel.com/docs/project-configuration) and common scaffolding anti-patterns observed in ecosystem research.
|
|
64
|
+
|
|
65
|
+
## Feature Dependencies
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
tsconfig.json
|
|
69
|
+
|
|
|
70
|
+
v
|
|
71
|
+
ESLint config (depends on TS types)
|
|
72
|
+
|
|
|
73
|
+
v
|
|
74
|
+
Prettier (must be last in ESLint extends)
|
|
75
|
+
|
|
|
76
|
+
v
|
|
77
|
+
lint-staged (runs ESLint + Prettier)
|
|
78
|
+
|
|
|
79
|
+
v
|
|
80
|
+
Husky (triggers lint-staged on commit)
|
|
81
|
+
|
|
|
82
|
+
v
|
|
83
|
+
CI workflow (runs same lint/test commands)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
package.json scripts
|
|
88
|
+
|
|
|
89
|
+
+-- dev (vercel dev)
|
|
90
|
+
|
|
|
91
|
+
+-- build (type check)
|
|
92
|
+
|
|
|
93
|
+
+-- test (vitest)
|
|
94
|
+
|
|
|
95
|
+
+-- lint (eslint + prettier check)
|
|
96
|
+
|
|
|
97
|
+
+-- format (prettier write)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Scaffolding Checklist
|
|
101
|
+
|
|
102
|
+
For v0.1.0 Core Setup, include these files:
|
|
103
|
+
|
|
104
|
+
### Configuration Files
|
|
105
|
+
- [ ] `tsconfig.json` - Strict TypeScript configuration
|
|
106
|
+
- [ ] `eslint.config.js` - Flat ESLint config with TypeScript and Prettier
|
|
107
|
+
- [ ] `.prettierrc` - Formatter settings
|
|
108
|
+
- [ ] `.prettierignore` - Exclude build artifacts
|
|
109
|
+
- [ ] `vercel.json` - Function configuration
|
|
110
|
+
- [ ] `.gitignore` - Standard Node + Vercel ignores
|
|
111
|
+
- [ ] `.nvmrc` - Node version (20 LTS recommended)
|
|
112
|
+
- [ ] `.editorconfig` - Cross-editor settings
|
|
113
|
+
|
|
114
|
+
### Developer Experience
|
|
115
|
+
- [ ] `.vscode/settings.json` - Format on save, ESLint integration
|
|
116
|
+
- [ ] `.vscode/extensions.json` - Recommended extensions
|
|
117
|
+
- [ ] `.husky/pre-commit` - Run lint-staged
|
|
118
|
+
- [ ] `lint-staged` config in package.json
|
|
119
|
+
|
|
120
|
+
### CI/CD
|
|
121
|
+
- [ ] `.github/workflows/ci.yml` - Lint and test on PR
|
|
122
|
+
|
|
123
|
+
### Documentation
|
|
124
|
+
- [ ] `README.md` - Setup instructions, available scripts
|
|
125
|
+
- [ ] `.env.example` - Document required environment variables
|
|
126
|
+
|
|
127
|
+
### Source Structure
|
|
128
|
+
- [ ] `/api/health.ts` - Health check endpoint (hello world)
|
|
129
|
+
- [ ] `/src/` - Empty directory for shared code (placeholder)
|
|
130
|
+
- [ ] `/tests/` - Empty directory for tests (placeholder)
|
|
131
|
+
- [ ] `/tests/health.test.ts` - Smoke test for health endpoint
|
|
132
|
+
|
|
133
|
+
## Recommended Configuration Details
|
|
134
|
+
|
|
135
|
+
### tsconfig.json (Strict)
|
|
136
|
+
|
|
137
|
+
Key settings for production TypeScript:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"compilerOptions": {
|
|
142
|
+
"target": "ES2022",
|
|
143
|
+
"module": "NodeNext",
|
|
144
|
+
"moduleResolution": "NodeNext",
|
|
145
|
+
"strict": true,
|
|
146
|
+
"noUncheckedIndexedAccess": true,
|
|
147
|
+
"noImplicitReturns": true,
|
|
148
|
+
"noFallthroughCasesInSwitch": true,
|
|
149
|
+
"forceConsistentCasingInFileNames": true,
|
|
150
|
+
"skipLibCheck": true,
|
|
151
|
+
"esModuleInterop": true,
|
|
152
|
+
"isolatedModules": true,
|
|
153
|
+
"outDir": "./dist",
|
|
154
|
+
"rootDir": "."
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Confidence:** HIGH - Based on [TypeScript TSConfig reference](https://www.typescriptlang.org/tsconfig/) and [strict mode recommendations](https://www.typescriptlang.org/tsconfig/strict.html).
|
|
160
|
+
|
|
161
|
+
### ESLint Flat Config
|
|
162
|
+
|
|
163
|
+
Modern ESLint 9+ configuration:
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
import js from "@eslint/js";
|
|
167
|
+
import tseslint from "typescript-eslint";
|
|
168
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
169
|
+
|
|
170
|
+
export default [
|
|
171
|
+
js.configs.recommended,
|
|
172
|
+
...tseslint.configs.strict,
|
|
173
|
+
eslintConfigPrettier,
|
|
174
|
+
{
|
|
175
|
+
files: ["**/*.ts"],
|
|
176
|
+
rules: {
|
|
177
|
+
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
178
|
+
"@typescript-eslint/no-explicit-any": "error"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
];
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Confidence:** HIGH - Based on [ESLint + Prettier 2026 integration patterns](https://www.joshuakgoldberg.com/blog/configuring-eslint-prettier-and-typescript-together/).
|
|
185
|
+
|
|
186
|
+
### Vitest Configuration
|
|
187
|
+
|
|
188
|
+
Minimal vitest.config.ts:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { defineConfig } from 'vitest/config';
|
|
192
|
+
|
|
193
|
+
export default defineConfig({
|
|
194
|
+
test: {
|
|
195
|
+
globals: true,
|
|
196
|
+
environment: 'node',
|
|
197
|
+
include: ['tests/**/*.test.ts']
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Confidence:** HIGH - Based on [Vitest official documentation](https://vitest.dev/config/) and [2026 testing recommendations](https://dev.to/dataformathub/vitest-vs-jest-30-why-2026-is-the-year-of-browser-native-testing-2fgb).
|
|
203
|
+
|
|
204
|
+
## MVP Recommendation
|
|
205
|
+
|
|
206
|
+
For v0.1.0 Core Setup milestone:
|
|
207
|
+
|
|
208
|
+
**Must Include (Ship-blocking):**
|
|
209
|
+
1. TypeScript configuration with strict mode
|
|
210
|
+
2. ESLint + Prettier with working integration
|
|
211
|
+
3. Vitest with at least one passing test
|
|
212
|
+
4. Pre-commit hooks preventing bad commits
|
|
213
|
+
5. Basic CI workflow (lint + test)
|
|
214
|
+
6. Health check endpoint proving serverless works
|
|
215
|
+
|
|
216
|
+
**Nice to Have (If Time Allows):**
|
|
217
|
+
1. VS Code workspace settings
|
|
218
|
+
2. EditorConfig
|
|
219
|
+
3. Comprehensive .gitignore
|
|
220
|
+
|
|
221
|
+
**Defer to Later Milestones:**
|
|
222
|
+
- Database configuration (v0.2.0 Storage)
|
|
223
|
+
- API routes beyond health check (v0.3.0 Core Engine)
|
|
224
|
+
- Deployment pipeline (when ready for production)
|
|
225
|
+
- Documentation beyond README (as features ship)
|
|
226
|
+
|
|
227
|
+
## Sources
|
|
228
|
+
|
|
229
|
+
### High Confidence (Official/Context7)
|
|
230
|
+
- [Vercel Functions Documentation](https://vercel.com/docs/functions)
|
|
231
|
+
- [Vercel Project Configuration](https://vercel.com/docs/project-configuration)
|
|
232
|
+
- [TypeScript TSConfig Reference](https://www.typescriptlang.org/tsconfig/)
|
|
233
|
+
- [Vitest Configuration Guide](https://vitest.dev/config/)
|
|
234
|
+
|
|
235
|
+
### Medium Confidence (Verified WebSearch)
|
|
236
|
+
- [ESLint + Prettier Configuration (2026)](https://medium.com/@osmion/prettier-eslint-configuration-that-actually-works-without-the-headaches-a8506b710d21)
|
|
237
|
+
- [Husky + lint-staged Setup](https://github.com/lint-staged/lint-staged)
|
|
238
|
+
- [TypeScript Best Practices for Large-Scale Apps](https://johal.in/typescript-best-practices-for-large-scale-web-applications-in-2026/)
|
|
239
|
+
- [GitHub Actions + Vercel CI/CD](https://vercel.com/kb/guide/how-can-i-use-github-actions-with-vercel)
|
|
240
|
+
|
|
241
|
+
### Low Confidence (Single Source)
|
|
242
|
+
- Specific version recommendations may shift; verify against current LTS when implementing
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# Domain Pitfalls: TypeScript/Vercel Serverless Project Scaffolding
|
|
2
|
+
|
|
3
|
+
**Domain:** TypeScript/Vercel serverless project setup
|
|
4
|
+
**Researched:** 2026-01-29
|
|
5
|
+
**Confidence:** HIGH (verified via official docs, community issues, multiple sources)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Critical Pitfalls
|
|
10
|
+
|
|
11
|
+
Mistakes that cause rewrites, deployment failures, or major rework.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### Pitfall 1: Path Aliases Not Resolved in Compiled Output
|
|
16
|
+
|
|
17
|
+
**What goes wrong:** You configure TypeScript path aliases (`@/` or `@components/`) in `tsconfig.json`, and everything works in your IDE and local development. Then deployment fails with "Cannot find module '@/utils'" errors.
|
|
18
|
+
|
|
19
|
+
**Why it happens:** TypeScript's `paths` option is for **type checking only**. The TypeScript compiler (`tsc`) does NOT rewrite import paths in emitted JavaScript. Your bundler or runtime has no idea what `@/` means.
|
|
20
|
+
|
|
21
|
+
**Consequences:**
|
|
22
|
+
- Builds fail on Vercel with cryptic module resolution errors
|
|
23
|
+
- Works locally (because bundler handles it) but fails in production
|
|
24
|
+
- Refactoring to fix requires updating every import in the project
|
|
25
|
+
|
|
26
|
+
**Prevention:**
|
|
27
|
+
1. **Decide early:** Either use a bundler that handles path aliases (Vite, webpack, tsup) OR avoid path aliases entirely
|
|
28
|
+
2. **If using aliases:** Configure BOTH tsconfig.json AND your bundler's alias config to match exactly
|
|
29
|
+
3. **For Vercel serverless functions:** Consider avoiding path aliases entirely since functions may bundle differently than your app
|
|
30
|
+
4. **Alternative:** Use package.json `"imports"` field (Node.js subpath imports) which works universally
|
|
31
|
+
|
|
32
|
+
**Detection:**
|
|
33
|
+
- Build locally with `tsc` (not your bundler) and check output for unresolved aliases
|
|
34
|
+
- Test `vercel build` locally before first deployment
|
|
35
|
+
- Search compiled `.js` files for `@/` strings
|
|
36
|
+
|
|
37
|
+
**Phase to address:** Phase 1 (Initial Setup) - Lock this decision before writing any imports
|
|
38
|
+
|
|
39
|
+
**Sources:**
|
|
40
|
+
- [TypeScript Modules Reference](https://www.typescriptlang.org/docs/handbook/modules/reference.html)
|
|
41
|
+
- [Path Aliases in TypeScript](https://dev.to/shane/path-aliases-in-typescript-with-vite-or-webpack-bundlers-3nmb)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### Pitfall 2: Wrong Module Resolution Strategy for Target Environment
|
|
46
|
+
|
|
47
|
+
**What goes wrong:** You set `moduleResolution: "bundler"` but deploy to Node.js serverless, or use `moduleResolution: "node16"` with a bundler, causing import resolution failures.
|
|
48
|
+
|
|
49
|
+
**Why it happens:** TypeScript has multiple module resolution strategies that make different assumptions:
|
|
50
|
+
- `node16`/`nodenext`: Requires explicit `.js` file extensions, follows Node.js ESM rules
|
|
51
|
+
- `bundler`: Assumes a bundler will resolve imports, no extensions required
|
|
52
|
+
- These are **incompatible** with each other
|
|
53
|
+
|
|
54
|
+
**Consequences:**
|
|
55
|
+
- "Relative import paths need explicit file extensions" errors everywhere
|
|
56
|
+
- Works in development, fails in production (or vice versa)
|
|
57
|
+
- Framework conflicts (Next.js has known issues with `node16`/`nodenext`)
|
|
58
|
+
|
|
59
|
+
**Prevention:**
|
|
60
|
+
1. **For Vercel with Next.js:** Use the tsconfig.json that Next.js generates - don't override module settings
|
|
61
|
+
2. **For Vercel serverless functions (non-Next.js):**
|
|
62
|
+
- If bundling with Vite/esbuild: `moduleResolution: "bundler"` + `module: "ESNext"`
|
|
63
|
+
- If running directly on Node.js: `moduleResolution: "node16"` + `module: "node16"` + explicit `.js` extensions
|
|
64
|
+
3. **Rule of thumb:** Match `module` and `moduleResolution` values (both `node16`, or both bundler-compatible)
|
|
65
|
+
|
|
66
|
+
**Detection:**
|
|
67
|
+
- TypeScript errors about file extensions
|
|
68
|
+
- "Cannot find module" errors that only appear after build
|
|
69
|
+
- Different behavior between `vercel dev` and production
|
|
70
|
+
|
|
71
|
+
**Phase to address:** Phase 1 (Initial Setup) - Must be correct before writing any code
|
|
72
|
+
|
|
73
|
+
**Sources:**
|
|
74
|
+
- [TypeScript moduleResolution docs](https://www.typescriptlang.org/tsconfig/moduleResolution.html)
|
|
75
|
+
- [Next.js Discussion #41189](https://github.com/vercel/next.js/discussions/41189)
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### Pitfall 3: Environment Variables Baked at Build Time vs Runtime
|
|
80
|
+
|
|
81
|
+
**What goes wrong:** Secrets or environment-specific config get embedded into your build artifacts. You deploy the same build to staging and production, but it uses staging secrets in production.
|
|
82
|
+
|
|
83
|
+
**Why it happens:**
|
|
84
|
+
- Next.js replaces `process.env.VARIABLE` at build time for client code
|
|
85
|
+
- `NEXT_PUBLIC_*` variables are **always** embedded at build time
|
|
86
|
+
- Server-side code behavior varies by context (API routes read at runtime, but static generation reads at build time)
|
|
87
|
+
|
|
88
|
+
**Consequences:**
|
|
89
|
+
- Secrets visible in client-side JavaScript bundles
|
|
90
|
+
- Cannot use same build artifact across environments (breaks 12-factor app principles)
|
|
91
|
+
- Accidental secret exposure in Docker images
|
|
92
|
+
- Confusing behavior where same code works differently in different contexts
|
|
93
|
+
|
|
94
|
+
**Prevention:**
|
|
95
|
+
1. **Never prefix secrets with `NEXT_PUBLIC_`** - This exposes them to clients
|
|
96
|
+
2. **Use Vercel's environment variable scoping:** Set different values per environment (Production, Preview, Development)
|
|
97
|
+
3. **For true runtime env vars:** Use `publicRuntimeConfig` or fetch config from an API
|
|
98
|
+
4. **Document which variables are build-time vs runtime** in your project
|
|
99
|
+
|
|
100
|
+
**Detection:**
|
|
101
|
+
- Search build output (`.next` folder) for secret values
|
|
102
|
+
- Check Network tab in browser for exposed env vars
|
|
103
|
+
- Verify different Preview deployments have different values
|
|
104
|
+
|
|
105
|
+
**Phase to address:** Phase 1 (Initial Setup) - Establish env var conventions before adding any secrets
|
|
106
|
+
|
|
107
|
+
**Sources:**
|
|
108
|
+
- [Vercel Environment Variables docs](https://vercel.com/docs/projects/environment-variables)
|
|
109
|
+
- [Next.js Issue #39299](https://github.com/vercel/next.js/issues/39299)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Pitfall 4: ESM/CJS Module Format Mismatch
|
|
114
|
+
|
|
115
|
+
**What goes wrong:** Your project mixes ESM (`import/export`) and CommonJS (`require/module.exports`) in incompatible ways, causing "Cannot use import statement outside a module" or "require is not defined" errors.
|
|
116
|
+
|
|
117
|
+
**Why it happens:**
|
|
118
|
+
- `"type": "module"` in package.json makes all `.js` files ESM
|
|
119
|
+
- Without it, all `.js` files are CommonJS
|
|
120
|
+
- TypeScript output format (`module` setting) must match what Node.js expects
|
|
121
|
+
- Dependencies may be ESM-only or CJS-only
|
|
122
|
+
|
|
123
|
+
**Consequences:**
|
|
124
|
+
- Works locally but fails on Vercel (or vice versa)
|
|
125
|
+
- Some dependencies refuse to load
|
|
126
|
+
- Confusing errors that seem unrelated to module format
|
|
127
|
+
|
|
128
|
+
**Prevention:**
|
|
129
|
+
1. **Pick ESM for new projects:** Add `"type": "module"` to package.json
|
|
130
|
+
2. **Match TypeScript config:** If using ESM, set `module: "ESNext"` or `module: "Node16"`
|
|
131
|
+
3. **Check dependency compatibility:** Use [publint](https://publint.dev/) or check package.json exports
|
|
132
|
+
4. **For Vercel serverless:** Verify tsconfig has ESM settings that match Vercel's runtime expectations
|
|
133
|
+
|
|
134
|
+
**Detection:**
|
|
135
|
+
- Errors mentioning "ERR_REQUIRE_ESM" or "import statement outside a module"
|
|
136
|
+
- Check package.json for `"type"` field
|
|
137
|
+
- Verify `tsconfig.json` `module` setting
|
|
138
|
+
|
|
139
|
+
**Phase to address:** Phase 1 (Initial Setup) - Set module format before adding dependencies
|
|
140
|
+
|
|
141
|
+
**Sources:**
|
|
142
|
+
- [Vercel Community: TypeScript serverless functions](https://community.vercel.com/t/deploying-typescript-serverless-functions/4029)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Moderate Pitfalls
|
|
147
|
+
|
|
148
|
+
Mistakes that cause delays, debugging sessions, or technical debt.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
### Pitfall 5: ESLint/Prettier Configuration Conflicts
|
|
153
|
+
|
|
154
|
+
**What goes wrong:** ESLint and Prettier fight over formatting, causing:
|
|
155
|
+
- Lint errors on save that Prettier then "fixes" back
|
|
156
|
+
- Infinite format loops in IDE
|
|
157
|
+
- Different results between CLI and editor
|
|
158
|
+
|
|
159
|
+
**Why it happens:**
|
|
160
|
+
- ESLint has formatting rules that conflict with Prettier's opinions
|
|
161
|
+
- Old guides recommend outdated extends like `"prettier/react"` (deprecated since v8.0.0)
|
|
162
|
+
- Plugin naming (`@typescript-eslint/indent` vs `ts/indent`) can bypass conflict resolution
|
|
163
|
+
|
|
164
|
+
**Prevention:**
|
|
165
|
+
1. **Use `eslint-config-prettier`:** Disables all ESLint formatting rules that conflict
|
|
166
|
+
2. **Modern setup (2025+):** Use ESLint flat config (`eslint.config.js`) with `eslint-plugin-prettier/recommended`
|
|
167
|
+
3. **Let Prettier own formatting:** ESLint for code quality only
|
|
168
|
+
4. **Consider Biome:** Single tool replaces both ESLint and Prettier, eliminates conflicts entirely
|
|
169
|
+
|
|
170
|
+
**Detection:**
|
|
171
|
+
- Format-on-save causes different results than CLI lint
|
|
172
|
+
- Lint errors that keep reappearing after fixes
|
|
173
|
+
- `npx eslint-config-prettier path/to/file.ts` to check for conflicts
|
|
174
|
+
|
|
175
|
+
**Phase to address:** Phase 1 (Initial Setup) - Configure before writing code
|
|
176
|
+
|
|
177
|
+
**Sources:**
|
|
178
|
+
- [eslint-config-prettier GitHub](https://github.com/prettier/eslint-config-prettier)
|
|
179
|
+
- [Modern Linting 2025](https://advancedfrontends.com/eslint-flat-config-typescript-javascript/)
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### Pitfall 6: Testing Setup Not Matching Runtime Environment
|
|
184
|
+
|
|
185
|
+
**What goes wrong:** Tests pass locally but code fails in production because:
|
|
186
|
+
- Test environment doesn't match Vercel's Node.js version
|
|
187
|
+
- Mocks don't reflect actual API behavior
|
|
188
|
+
- Environment variables differ between test and runtime
|
|
189
|
+
|
|
190
|
+
**Why it happens:**
|
|
191
|
+
- Vitest/Jest run in different environment than Vercel functions
|
|
192
|
+
- `happy-dom` or `jsdom` don't perfectly match real browser
|
|
193
|
+
- Missing async handling (`no-floating-promises` not enabled)
|
|
194
|
+
|
|
195
|
+
**Prevention:**
|
|
196
|
+
1. **Pin Node.js version:** Use `.nvmrc` or `engines` field, match Vercel's runtime
|
|
197
|
+
2. **Enable TypeScript strict async:** Add `"no-floating-promises": "error"` to catch missing awaits
|
|
198
|
+
3. **Test against real environment:** Use `vercel dev` for integration tests
|
|
199
|
+
4. **Mock sparingly:** Over-mocking hides real integration issues
|
|
200
|
+
|
|
201
|
+
**Detection:**
|
|
202
|
+
- Tests pass but production fails
|
|
203
|
+
- Flaky tests (usually async timing issues)
|
|
204
|
+
- "Cannot find module" errors only in CI
|
|
205
|
+
|
|
206
|
+
**Phase to address:** Phase 1 (Initial Setup) - Set up testing before writing tests
|
|
207
|
+
|
|
208
|
+
**Sources:**
|
|
209
|
+
- [React Testing Library + Vitest Mistakes](https://medium.com/@samueldeveloper/react-testing-library-vitest-the-mistakes-that-haunt-developers-and-how-to-fight-them-like-ca0a0cda2ef8)
|
|
210
|
+
- [SST Unit Tests guide](https://guide.sst.dev/chapters/unit-tests-in-serverless.html)
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
### Pitfall 7: Choosing Edge Functions When Serverless is Required
|
|
215
|
+
|
|
216
|
+
**What goes wrong:** You use Vercel Edge Functions for their speed, but then discover you need:
|
|
217
|
+
- Native Node.js APIs (`fs`, `path`, `process`)
|
|
218
|
+
- TCP/UDP connections (databases)
|
|
219
|
+
- Bundles larger than 4MB
|
|
220
|
+
- Execution longer than 30 seconds
|
|
221
|
+
|
|
222
|
+
**Why it happens:**
|
|
223
|
+
- Edge Functions use V8 runtime, NOT Node.js
|
|
224
|
+
- Marketing emphasizes speed benefits without highlighting limitations
|
|
225
|
+
- Easy to start with Edge and hit walls later
|
|
226
|
+
|
|
227
|
+
**Consequences:**
|
|
228
|
+
- Rewriting functions to use serverless instead
|
|
229
|
+
- Architecture changes to work around Edge limitations
|
|
230
|
+
- Unexpected costs from function invocations vs compute time
|
|
231
|
+
|
|
232
|
+
**Prevention:**
|
|
233
|
+
1. **Default to Serverless Functions** unless you have a specific Edge use case
|
|
234
|
+
2. **Edge is best for:** Auth checks, redirects, A/B testing, geolocation-based routing
|
|
235
|
+
3. **Serverless is best for:** Database queries, file operations, heavy computation, long-running tasks
|
|
236
|
+
4. **Hybrid approach:** Edge for request routing, Serverless for data operations
|
|
237
|
+
|
|
238
|
+
**Detection:**
|
|
239
|
+
- "X is not defined" errors for Node.js APIs
|
|
240
|
+
- Bundle size errors during deployment
|
|
241
|
+
- Timeout errors on Pro plan (30s Edge vs 60s Serverless)
|
|
242
|
+
|
|
243
|
+
**Phase to address:** Phase 1 (Architecture Decision) - Decide function runtime strategy before implementation
|
|
244
|
+
|
|
245
|
+
**Sources:**
|
|
246
|
+
- [Vercel Edge Functions docs](https://vercel.com/docs/functions/runtimes/edge/edge-functions.rsc)
|
|
247
|
+
- [Edge vs Serverless Performance 2025](https://byteiota.com/edge-functions-vs-serverless-the-2025-performance-battle/)
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### Pitfall 8: Large Bundle Sizes Causing Cold Start Timeouts
|
|
252
|
+
|
|
253
|
+
**What goes wrong:** Serverless functions take 2-5+ seconds on cold start because the bundle includes unnecessary dependencies.
|
|
254
|
+
|
|
255
|
+
**Why it happens:**
|
|
256
|
+
- Importing entire libraries when you need one function
|
|
257
|
+
- ORM clients (Prisma) adding 40MB+ to bundles
|
|
258
|
+
- Not tree-shaking dependencies properly
|
|
259
|
+
- Font files, icon libraries included in server bundles
|
|
260
|
+
|
|
261
|
+
**Consequences:**
|
|
262
|
+
- Poor user experience on first request
|
|
263
|
+
- Timeout errors on free tier (10s limit)
|
|
264
|
+
- Higher costs from longer execution times
|
|
265
|
+
|
|
266
|
+
**Prevention:**
|
|
267
|
+
1. **Analyze bundles:** Use `@next/bundle-analyzer` or `bundlephobia.com` before adding dependencies
|
|
268
|
+
2. **Use lightweight alternatives:** `date-fns` instead of `moment`, native fetch instead of axios
|
|
269
|
+
3. **For Prisma:** Use `bundlePagesExternals: true` in Next.js config
|
|
270
|
+
4. **Consider Vercel's Fluid compute:** Automatic cold start optimization on Pro plan
|
|
271
|
+
5. **Lazy load:** Dynamic imports for heavy dependencies
|
|
272
|
+
|
|
273
|
+
**Detection:**
|
|
274
|
+
- Check Vercel Observability tab for cold start metrics
|
|
275
|
+
- Function deploy output shows bundle sizes
|
|
276
|
+
- First requests consistently slower than subsequent ones
|
|
277
|
+
|
|
278
|
+
**Phase to address:** Phase 1 (Dependency Selection) - Choose lightweight dependencies from the start
|
|
279
|
+
|
|
280
|
+
**Sources:**
|
|
281
|
+
- [Vercel Cold Start Performance guide](https://vercel.com/kb/guide/how-can-i-improve-serverless-function-lambda-cold-start-performance-on-vercel)
|
|
282
|
+
- [Vercel Discussion #7961](https://github.com/vercel/vercel/discussions/7961)
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
### Pitfall 9: Not Enabling TypeScript Strict Mode (or Enabling It Too Late)
|
|
287
|
+
|
|
288
|
+
**What goes wrong:**
|
|
289
|
+
- **If disabled:** Runtime errors from null/undefined that TypeScript could have caught
|
|
290
|
+
- **If enabled late:** Thousands of errors appear, overwhelming refactoring effort
|
|
291
|
+
|
|
292
|
+
**Why it happens:**
|
|
293
|
+
- Default `strict: false` is permissive, hides real bugs
|
|
294
|
+
- Enabling `strict: true` on existing codebase is painful
|
|
295
|
+
- Developers delay strictness "until later" (later never comes)
|
|
296
|
+
|
|
297
|
+
**Consequences:**
|
|
298
|
+
- Runtime `TypeError: Cannot read property 'x' of undefined`
|
|
299
|
+
- Technical debt accumulates
|
|
300
|
+
- Refactoring to strict mode becomes major project
|
|
301
|
+
|
|
302
|
+
**Prevention:**
|
|
303
|
+
1. **Enable `strict: true` on day one** for new projects
|
|
304
|
+
2. **For existing projects:** Enable strict flags incrementally:
|
|
305
|
+
- Start with `noImplicitAny: true`
|
|
306
|
+
- Then `strictNullChecks: true`
|
|
307
|
+
- Then remaining flags one at a time
|
|
308
|
+
3. **Add extra strictness:** `noUncheckedIndexedAccess: true` catches array/object access bugs
|
|
309
|
+
|
|
310
|
+
**Detection:**
|
|
311
|
+
- Check tsconfig.json for `strict` setting
|
|
312
|
+
- Run `tsc --noEmit` to see current error count
|
|
313
|
+
- Search codebase for `any` type usage
|
|
314
|
+
|
|
315
|
+
**Phase to address:** Phase 1 (Initial Setup) - Enable before writing any code
|
|
316
|
+
|
|
317
|
+
**Sources:**
|
|
318
|
+
- [Why strict: true isn't enough](https://itnext.io/why-typescripts-strict-true-isn-t-enough-missing-compiler-flags-for-production-code-a3877b81142c)
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Minor Pitfalls
|
|
323
|
+
|
|
324
|
+
Mistakes that cause annoyance but are quickly fixable.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### Pitfall 10: Utility Files in `/api` Directory Become Functions
|
|
329
|
+
|
|
330
|
+
**What goes wrong:** Helper files placed in `/api` directory get deployed as serverless functions, causing 404s or unexpected behavior.
|
|
331
|
+
|
|
332
|
+
**Why it happens:** Vercel's convention turns every file in `/api` into an endpoint.
|
|
333
|
+
|
|
334
|
+
**Prevention:**
|
|
335
|
+
- Prefix utility files with underscore: `_utils.ts`, `_helpers.ts`
|
|
336
|
+
- Or place utilities outside `/api` in `/lib` or `/utils`
|
|
337
|
+
|
|
338
|
+
**Detection:** Unexpected endpoints appearing in production
|
|
339
|
+
|
|
340
|
+
**Phase to address:** Phase 1 (Project Structure) - Establish conventions early
|
|
341
|
+
|
|
342
|
+
**Sources:**
|
|
343
|
+
- [Vercel Discussion #4983](https://github.com/vercel/vercel/discussions/4983)
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
### Pitfall 11: vercel.json Overrides Build Settings Silently
|
|
348
|
+
|
|
349
|
+
**What goes wrong:** You configure build settings in Vercel dashboard, but `vercel.json` in repo takes precedence without warning.
|
|
350
|
+
|
|
351
|
+
**Why it happens:** Vercel prioritizes file-based config over dashboard settings.
|
|
352
|
+
|
|
353
|
+
**Prevention:**
|
|
354
|
+
- Pick one source of truth: either `vercel.json` OR dashboard settings
|
|
355
|
+
- Check for `vercel.json` when debugging unexpected build behavior
|
|
356
|
+
- Use `vercel.ts` for type-safe configuration
|
|
357
|
+
|
|
358
|
+
**Detection:** Build warning: "Due to builds existing in your configuration file, the Build and Development Settings... will not apply"
|
|
359
|
+
|
|
360
|
+
**Phase to address:** Phase 1 (CI/CD Setup)
|
|
361
|
+
|
|
362
|
+
**Sources:**
|
|
363
|
+
- [Vercel Project Configuration docs](https://vercel.com/docs/project-configuration)
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### Pitfall 12: Forgetting to Pin Dependency Versions
|
|
368
|
+
|
|
369
|
+
**What goes wrong:** A patch release of a dependency breaks your build, but works fine locally because you have older cached version.
|
|
370
|
+
|
|
371
|
+
**Why it happens:**
|
|
372
|
+
- `^` prefix allows minor/patch updates
|
|
373
|
+
- CI installs fresh, gets newer version
|
|
374
|
+
- "Works on my machine" syndrome
|
|
375
|
+
|
|
376
|
+
**Prevention:**
|
|
377
|
+
- Use lockfile (`pnpm-lock.yaml`, `package-lock.json`)
|
|
378
|
+
- Commit lockfile to git
|
|
379
|
+
- Consider `npm ci` instead of `npm install` in CI
|
|
380
|
+
|
|
381
|
+
**Detection:** Builds failing with errors not reproducible locally
|
|
382
|
+
|
|
383
|
+
**Phase to address:** Phase 1 (Initial Setup)
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Phase-Specific Warnings
|
|
388
|
+
|
|
389
|
+
| Phase Topic | Likely Pitfall | Mitigation |
|
|
390
|
+
|-------------|----------------|------------|
|
|
391
|
+
| Initial tsconfig.json | Wrong moduleResolution | Use framework default, don't override module settings |
|
|
392
|
+
| Adding path aliases | Aliases not resolved | Configure bundler to match, or avoid aliases |
|
|
393
|
+
| First Vercel deploy | Works locally, fails prod | Run `vercel build` locally first |
|
|
394
|
+
| Adding database | Cold start timeouts | Use connection pooling, lightweight clients |
|
|
395
|
+
| Adding auth | Secrets in client bundle | Never use NEXT_PUBLIC_ for secrets |
|
|
396
|
+
| Testing setup | Tests don't match runtime | Pin Node version, test with `vercel dev` |
|
|
397
|
+
| Linting setup | ESLint/Prettier conflicts | Use eslint-config-prettier or Biome |
|
|
398
|
+
| Edge functions | Missing Node.js APIs | Default to serverless, Edge only for specific cases |
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Quick Reference Checklist
|
|
403
|
+
|
|
404
|
+
Before considering setup complete:
|
|
405
|
+
|
|
406
|
+
- [ ] `strict: true` enabled in tsconfig.json
|
|
407
|
+
- [ ] Module resolution matches target environment
|
|
408
|
+
- [ ] Path aliases configured in BOTH tsconfig AND bundler (or avoided entirely)
|
|
409
|
+
- [ ] ESLint/Prettier conflicts resolved (or using Biome)
|
|
410
|
+
- [ ] Environment variables documented (build-time vs runtime)
|
|
411
|
+
- [ ] `vercel build` tested locally
|
|
412
|
+
- [ ] Node.js version pinned
|
|
413
|
+
- [ ] Lockfile committed
|
|
414
|
+
- [ ] Utility files prefixed with `_` or outside `/api`
|
|
415
|
+
- [ ] Bundle size checked for serverless functions
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Sources Summary
|
|
420
|
+
|
|
421
|
+
**Official Documentation:**
|
|
422
|
+
- [Vercel Environment Variables](https://vercel.com/docs/projects/environment-variables)
|
|
423
|
+
- [Vercel Functions docs](https://vercel.com/docs/functions)
|
|
424
|
+
- [TypeScript moduleResolution](https://www.typescriptlang.org/tsconfig/moduleResolution.html)
|
|
425
|
+
- [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)
|
|
426
|
+
|
|
427
|
+
**Community Issues & Discussions:**
|
|
428
|
+
- [Vercel TypeScript serverless functions](https://community.vercel.com/t/deploying-typescript-serverless-functions/4029)
|
|
429
|
+
- [Next.js moduleResolution issues](https://github.com/vercel/next.js/discussions/41189)
|
|
430
|
+
- [Vercel cold start discussion](https://github.com/vercel/vercel/discussions/7961)
|
|
431
|
+
- [Vercel API directory structure](https://github.com/vercel/vercel/discussions/4983)
|
|
432
|
+
|
|
433
|
+
**Guides & Best Practices:**
|
|
434
|
+
- [Modern ESLint 2025](https://advancedfrontends.com/eslint-flat-config-typescript-javascript/)
|
|
435
|
+
- [Path Aliases in TypeScript](https://dev.to/shane/path-aliases-in-typescript-with-vite-or-webpack-bundlers-3nmb)
|
|
436
|
+
- [Edge vs Serverless 2025](https://byteiota.com/edge-functions-vs-serverless-the-2025-performance-battle/)
|