12 KiB
Tech Stack & Enforcement Rules
Version: 1.0
Status: PRODUCTION
Last Updated: January 2026
Overview
This document enforces the specific versions and usage patterns for all technologies in Job Info. All developers must follow these rules to ensure consistency and compatibility.
1. Runtime & Build System
Bun
Version: latest (1.0.0+)
Rules:
- ✅ Use
bunfor running TypeScript directly - ✅ Use
bun installto manage dependencies - ✅ Use
bun runfor scripts - ✅ Use
bun run build:cssfor Tailwind compilation - ❌ Do NOT use
npmoryarn - ❌ Do NOT use Node.js for production (Bun is faster, but ensure infrastructure supports it)
Installation:
curl -fsSL https://bun.sh/install | bash
Common Commands:
bun install # Install dependencies
bun add <package> # Add dependency
bun run <script> # Run npm script
bun --watch server.ts # Watch & reload
bun build --target bun # Build for production
package.json Scripts:
{
"scripts": {
"dev": "bun --watch backend/server.ts",
"start": "bun run backend/server.ts",
"build:css": "tailwindcss -i input.css -o frontend/output.css --watch"
}
}
2. Web Framework
Hono
Version: ^4.10.8 (pinned)
Rules:
- ✅ Use Hono for all backend routes
- ✅ Use typed context:
(c: Context) - ✅ Use middleware for auth, logging, CORS
- ✅ Return JSON responses with
c.json() - ❌ Do NOT mix Express or other frameworks
- ❌ Do NOT use un-typed
req/res
Installation:
bun add hono@^4.10.8
Routing Pattern:
import { Hono } from 'hono';
import { Context } from 'hono';
const app = new Hono();
// GET endpoint
app.get('/api/jobs', async (c: Context) => {
try {
const page = c.req.query('page') || '1';
const data = await fetchData();
return c.json({ items: data });
} catch (err) {
console.error('Error:', err);
return c.json({ error: 'Server error' }, 500);
}
});
// POST endpoint
app.post('/api/jobs', async (c: Context) => {
const body = await c.req.json();
// Process
return c.json({ success: true }, 201);
});
export default app;
Middleware Pattern:
// Auth middleware
app.use('*', async (c, next) => {
const token = c.req.header('Authorization');
if (!token) return c.json({ error: 'Unauthorized' }, 401);
await next();
});
// CORS middleware
app.use('*', async (c, next) => {
c.header('Access-Control-Allow-Origin', '*');
await next();
});
3. CSS Framework
PostCSS + Tailwind CSS
Versions:
postcss:^8.5.6(pinned)tailwindcss:^4.1.18(pinned)autoprefixer:^10.4.23(devDependency)
Installation:
bun add -D postcss@^8.5.6 tailwindcss@^4.1.18 autoprefixer@^10.4.23
Configuration Files:
postcss.config.js:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
tailwind.config.js:
export default {
content: [
'./frontend/**/*.html',
'./frontend/**/*.js',
],
theme: {
extend: {
colors: {
// Add custom colors if needed
},
},
},
plugins: [],
};
Build Command:
bun run build:css
CSS Input (input.css):
@tailwind base;
@tailwind components;
@tailwind utilities;
Rules:
- ✅ Use Tailwind utility classes:
bg-blue-600,px-4,rounded-lg - ✅ Use
@applyfor reusable component styles (if needed) - ✅ Custom CSS in separate
.cssfiles (not inline styles) - ❌ Do NOT use Bootstrap, Foundation, or other CSS frameworks
- ❌ Do NOT inline styles:
<div style="..."> - ❌ Do NOT write CSS that conflicts with Tailwind
Component Example:
<!-- ✅ CORRECT -->
<button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
Click Me
</button>
<!-- ❌ WRONG -->
<button style="background: blue; padding: 10px;">Click Me</button>
4. Runtime Type System
TypeScript
Version: ^5 (peer dependency)
Rules:
- ✅ Use strict mode:
"strict": truein tsconfig.json - ✅ Type all function parameters
- ✅ Type all return values
- ✅ Use interfaces for objects
- ✅ Enable
noImplicitAny - ✅ Enable
strictNullChecks - ❌ Do NOT use
anytype - ❌ Do NOT skip type annotations
tsconfig.json (Backend):
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"lib": ["ES2020"],
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true
},
"include": ["backend/**/*.ts"],
"exclude": ["node_modules"]
}
Example:
// ✅ CORRECT
interface Job {
id: string;
name: string;
number: number;
created_at: string;
}
function getJobNumber(job: Job): number {
return job.number;
}
async function fetchJob(id: string): Promise<Job | null> {
try {
const data = await fetch(`/api/jobs/${id}`);
if (!data.ok) return null;
return await data.json();
} catch (err) {
console.error('Error fetching job:', err);
return null;
}
}
// ❌ WRONG
function getJobNumber(job) { // No type
return job.number; // No return type
}
5. Caching & Session Management
ioredis (Redis/Valkey Client)
Version: ^5.x (add to dependencies)
Installation:
bun add ioredis
Usage:
import Redis from 'ioredis';
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT || 6379),
password: process.env.REDIS_PASSWORD,
retryStrategy(times) {
const delay = Math.min(times * 50, 2000);
return delay;
},
maxRetriesPerRequest: 3,
lazyConnect: true,
});
// Cache operations
export async function getCache(key: string): Promise<any | null> {
try {
const value = await redis.get(key);
if (!value) return null;
return JSON.parse(value);
} catch (err) {
console.error(`Cache get error for key "${key}":`, err);
return null;
}
}
export async function setCache(key: string, value: any, ttl: number = 300): Promise<boolean> {
try {
const serialized = JSON.stringify(value);
await redis.setex(key, ttl, serialized);
return true;
} catch (err) {
console.error(`Cache set error for key "${key}":`, err);
return false;
}
}
Rules:
- ✅ Use
setexfor automatic TTL expiration - ✅ Check cache before fetching external data
- ✅ Log cache hits/misses for debugging
- ❌ Do NOT store secrets in cache
- ❌ Do NOT rely on cache for critical data (always have fallback)
6. Authentication & Backend Services
PocketBase SDK
Version: ^0.26.5 (pinned)
Installation:
bun add pocketbase@^0.26.5
Frontend Usage (auth.js):
const PocketBase = window.PocketBase;
const pb = new PocketBase('https://pocketbase.ccllc.pro');
// Login
const authData = await pb.collection('users')
.authWithPassword(email, password);
// Get token
const token = authData.token || pb.authStore.exportSession()?.token;
// Logout
pb.authStore.clear();
Rules:
- ✅ Single PocketBase instance
- ✅ Store token in localStorage
- ✅ Use token in all API requests
- ❌ Do NOT create multiple PocketBase instances
- ❌ Do NOT expose secrets in frontend
7. Dotenv Configuration
dotenv
Version: ^17.2.3 (pinned)
Installation:
bun add dotenv@^17.2.3
Usage (Backend):
import dotenv from 'dotenv';
dotenv.config();
const PORT = process.env.PORT || 3005;
const REDIS_HOST = process.env.REDIS_HOST || 'localhost';
const REDIS_PORT = Number(process.env.REDIS_PORT || 6379);
Environment Variables:
# .env (gitignored)
PORT=3005
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
POCKETBASE_URL=https://pocketbase.ccllc.pro
Rules:
- ✅ Load from
.envfile - ✅ Provide sensible defaults for development
- ✅ Document required variables in
.env.example - ❌ Do NOT commit
.envto git - ❌ Do NOT hardcode secrets
8. Development Server
Watch Mode
Command:
bun --watch backend/server.ts
Features:
- Auto-restart on file changes
- Clear cache on restart
- Logs all requests
Usage:
- Start with
bun run devin one terminal - Start CSS watcher with
bun run build:cssin another - Changes auto-refresh immediately
9. Production Build
Bun Bundler
Command:
bun build --target bun --outdir dist backend/server.ts
Output:
dist/
server.ts (bundled, optimized)
Deployment:
bun run dist/server.ts
Rules:
- ✅ Build before deploying
- ✅ Test built version locally
- ✅ Deploy from
dist/folder - ❌ Do NOT deploy source TypeScript files
- ❌ Do NOT use development server in production
10. Dependency Management
Package.json Structure
Required:
{
"name": "job-info-pb",
"version": "1.0.0",
"type": "module",
"private": true,
"scripts": {
"dev": "bun --watch backend/server.ts",
"start": "bun run backend/server.ts",
"build:css": "tailwindcss -i input.css -o frontend/output.css --watch",
"build": "bun build --target bun --outdir dist backend/server.ts"
},
"dependencies": {
"dotenv": "^17.2.3",
"hono": "^4.10.8",
"ioredis": "^5.x",
"pocketbase": "^0.26.5"
},
"devDependencies": {
"@types/bun": "latest",
"autoprefixer": "^10.4.23",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18"
}
}
Rules:
- ✅ Pin versions for production stability
- ✅ Use
^for compatible versions - ✅ Regularly audit for security updates
- ❌ Do NOT use
*orlatestin production dependencies - ❌ Do NOT add unnecessary dependencies
Update Command:
bun update # Check for updates
bun audit # Security audit
bun install --save-exact # Lock versions
11. Enforcement & Validation
Code Review Checklist
Before committing, verify:
- Uses Hono for all routes (no Express)
- Uses Tailwind for all styles (no inline styles)
- All functions have TypeScript types
- No
anytype annotations - All dependencies pinned in package.json
- Cache implemented for GET endpoints
- Errors logged to file and console
- No hardcoded secrets
- No console.log() in production code (use proper logging)
- Follows naming conventions from RULES.md
ESLint Rules (Optional but Recommended)
.eslintrc.json:
{
"parser": "@typescript-eslint/parser",
"extends": ["eslint:recommended"],
"rules": {
"no-console": ["warn", { "allow": ["error", "warn"] }],
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/explicit-function-return-types": "warn"
}
}
12. Troubleshooting
Bun Issues
- "Command not found": Add Bun to PATH
- "Module not found": Run
bun install - "Permission denied": Run
chmod +xon files
Hono Issues
- Route not found: Check route path spelling
- Middleware not applied: Order matters; add to top of file
Tailwind Issues
- Classes not applying: Run
bun run build:css - Cache issue: Delete output.css and rebuild
Redis Issues
- Connection refused: Ensure Redis/Valkey is running
- Timeout: Check credentials in .env
Summary
| Technology | Version | Rule |
|---|---|---|
| Bun | latest | Runtime & build tool |
| Hono | ^4.10.8 | All web routes |
| PostCSS | ^8.5.6 | CSS processing |
| Tailwind | ^4.1.18 | Utility CSS |
| TypeScript | ^5 | Strict typing required |
| ioredis | ^5.x | Cache client |
| PocketBase | ^0.26.5 | Auth backend |
| dotenv | ^17.2.3 | Config management |
All new code must use these exact versions and patterns.