redis optimization/improvments
This commit is contained in:
@@ -0,0 +1,645 @@
|
||||
# Developer Onboarding & Project Guide
|
||||
|
||||
**Version:** 1.0
|
||||
**Status:** PRODUCTION
|
||||
**Last Updated:** January 2026
|
||||
|
||||
---
|
||||
|
||||
## Welcome to Job Info
|
||||
|
||||
Job Info is a professional web application for managing construction/project jobs, files, and notes. This guide helps new developers understand and maintain the project.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start (5 minutes)
|
||||
|
||||
### 1. Clone and Setup
|
||||
|
||||
```bash
|
||||
git clone <repo-url>
|
||||
cd Job-Info-Prod
|
||||
bun install
|
||||
```
|
||||
|
||||
### 2. Environment Setup
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your values
|
||||
```
|
||||
|
||||
**Required Variables:**
|
||||
```
|
||||
PORT=3005
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
POCKETBASE_URL=https://pocketbase.ccllc.pro
|
||||
```
|
||||
|
||||
### 3. Start Development
|
||||
|
||||
**Terminal 1 - Backend:**
|
||||
```bash
|
||||
bun run dev
|
||||
# Watches backend/server.ts, auto-reloads on changes
|
||||
```
|
||||
|
||||
**Terminal 2 - CSS:**
|
||||
```bash
|
||||
bun run build:css
|
||||
# Watches Tailwind, auto-compiles output.css
|
||||
```
|
||||
|
||||
### 4. Open in Browser
|
||||
|
||||
```
|
||||
http://localhost:3005
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
Job-Info-Prod/
|
||||
├── auth/ # Authentication & rules
|
||||
│ ├── README.md # Auth module documentation
|
||||
│ ├── RULES.md # Data handling rules (READ THIS!)
|
||||
│ ├── FLOWMAP.md # Application flow diagram
|
||||
│ ├── TECH_STACK.md # Technology versions & usage
|
||||
│ ├── VIEWS.md # UI/View patterns
|
||||
│ └── auth-universal.js # Auth implementation
|
||||
│
|
||||
├── backend/ # Server code (Hono)
|
||||
│ ├── src/
|
||||
│ │ ├── index.ts # Main server entry
|
||||
│ │ ├── config/ # Configuration
|
||||
│ │ ├── middleware/ # Auth, logging, CORS
|
||||
│ │ ├── routes/ # API endpoints
|
||||
│ │ │ ├── jobs.ts # /api/jobs endpoints
|
||||
│ │ │ ├── files.ts # /api/job-files endpoints
|
||||
│ │ │ └── health.ts # /health endpoint
|
||||
│ │ ├── services/ # Business logic
|
||||
│ │ │ ├── cache.ts # Redis cache layer
|
||||
│ │ │ └── pocketbase.ts # PocketBase integration
|
||||
│ │ ├── types/ # TypeScript interfaces
|
||||
│ │ └── utils/ # Helper functions
|
||||
│ ├── tests/ # Unit & integration tests
|
||||
│ └── README.md # Backend documentation
|
||||
│
|
||||
├── frontend/ # Client code (Vanilla JS + Tailwind)
|
||||
│ ├── public/
|
||||
│ │ ├── index.html # Main app page
|
||||
│ │ ├── signin.html # Sign in page
|
||||
│ │ ├── output.css # Generated Tailwind (don't edit!)
|
||||
│ │ └── assets/ # Images, logos
|
||||
│ ├── src/
|
||||
│ │ ├── main.ts # Frontend entry point
|
||||
│ │ ├── auth/
|
||||
│ │ │ └── client.ts # Auth utilities
|
||||
│ │ ├── views/ # View logic
|
||||
│ │ │ ├── landing.ts
|
||||
│ │ │ ├── job-detail.ts
|
||||
│ │ │ └── notes.ts
|
||||
│ │ ├── services/ # API & state
|
||||
│ │ │ ├── api.ts # API client
|
||||
│ │ │ └── state.ts # Global state
|
||||
│ │ └── styles/ # Custom CSS
|
||||
│ ├── tests/
|
||||
│ └── README.md # Frontend documentation
|
||||
│
|
||||
├── shared/ # Shared code
|
||||
│ ├── types/ # Common TypeScript types
|
||||
│ └── constants/ # Shared constants
|
||||
│
|
||||
├── docs/ # Additional documentation
|
||||
│ ├── ARCHITECTURE.md # System design
|
||||
│ ├── API.md # API reference
|
||||
│ └── DEPLOYMENT.md # Production deployment
|
||||
│
|
||||
├── scripts/ # Utility scripts
|
||||
│ ├── setup.sh # Initial setup
|
||||
│ └── deploy.sh # Deploy to production
|
||||
│
|
||||
├── logs/ # Runtime logs (gitignored)
|
||||
├── tests/ # Integration tests
|
||||
│
|
||||
├── .env.example # Environment template
|
||||
├── .gitignore # Git ignore rules
|
||||
├── package.json # Dependencies & scripts
|
||||
├── tsconfig.json # TypeScript config
|
||||
├── tailwind.config.js # Tailwind config
|
||||
├── postcss.config.js # PostCSS config
|
||||
├── README.md # Project README
|
||||
└── CHANGELOG.md # Version history
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation by Role
|
||||
|
||||
### For All Developers
|
||||
|
||||
**Must Read (In Order):**
|
||||
1. [RULES.md](./RULES.md) - Data handling & patterns
|
||||
2. [FLOWMAP.md](./FLOWMAP.md) - How the app works
|
||||
3. [TECH_STACK.md](./TECH_STACK.md) - What tech to use
|
||||
|
||||
**Reference:**
|
||||
- [VIEWS.md](./VIEWS.md) - UI component patterns
|
||||
- [API.md](../docs/API.md) - API endpoints
|
||||
- [ARCHITECTURE.md](../docs/ARCHITECTURE.md) - System design
|
||||
|
||||
---
|
||||
|
||||
### For Backend Developers
|
||||
|
||||
**Focus:**
|
||||
1. Understand [RULES.md](./RULES.md) - Cache patterns & data flow
|
||||
2. Review [backend/README.md](../backend/README.md)
|
||||
3. Follow [TECH_STACK.md](./TECH_STACK.md) - Hono patterns
|
||||
|
||||
**Tasks:**
|
||||
- Create/modify endpoints in `backend/src/routes/`
|
||||
- Implement caching in route handlers
|
||||
- Add proper error handling & logging
|
||||
- Write unit tests in `backend/tests/`
|
||||
|
||||
**Key Rules:**
|
||||
- ✅ Cache all GET requests
|
||||
- ✅ Type all function parameters
|
||||
- ✅ Log errors with context
|
||||
- ❌ Don't share state between requests
|
||||
- ❌ Don't expose secrets
|
||||
|
||||
---
|
||||
|
||||
### For Frontend Developers
|
||||
|
||||
**Focus:**
|
||||
1. Understand [RULES.md](./RULES.md) - State & view patterns
|
||||
2. Review [VIEWS.md](./VIEWS.md) - Component design
|
||||
3. Follow [TECH_STACK.md](./TECH_STACK.md) - Tailwind patterns
|
||||
|
||||
**Tasks:**
|
||||
- Create views in `frontend/src/views/`
|
||||
- Implement UI with Tailwind CSS
|
||||
- Use shared state management
|
||||
- Handle errors gracefully
|
||||
|
||||
**Key Rules:**
|
||||
- ✅ Use Tailwind for all styling
|
||||
- ✅ Keep views modular
|
||||
- ✅ Use single state object per view
|
||||
- ❌ Don't inline styles
|
||||
- ❌ Don't create multiple auth instances
|
||||
|
||||
---
|
||||
|
||||
### For DevOps/Deployment
|
||||
|
||||
**Focus:**
|
||||
1. Review [DEPLOYMENT.md](../docs/DEPLOYMENT.md)
|
||||
2. Understand environment variables
|
||||
3. Set up CI/CD pipeline
|
||||
|
||||
**Key Commands:**
|
||||
```bash
|
||||
bun install # Install dependencies
|
||||
bun run build # Build for production
|
||||
bun run build:css # Compile Tailwind
|
||||
bun start # Run production server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding a New API Endpoint
|
||||
|
||||
**1. Define the endpoint in [API.md](../docs/API.md)**
|
||||
```
|
||||
GET /api/new-resource
|
||||
Returns: { items: [], total: 0 }
|
||||
Cache: 5 minutes
|
||||
Auth: Required
|
||||
```
|
||||
|
||||
**2. Create route in `backend/src/routes/new.ts`**
|
||||
```typescript
|
||||
import { Hono } from 'hono';
|
||||
import { Context } from 'hono';
|
||||
import { getCache, setCache } from '../services/cache';
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
app.get('/api/new-resource', async (c: Context) => {
|
||||
const cacheKey = 'new-resource:all';
|
||||
const ttl = 300;
|
||||
|
||||
try {
|
||||
// Try cache
|
||||
const cached = await getCache(cacheKey);
|
||||
if (cached) return c.json(cached);
|
||||
|
||||
// Fetch data
|
||||
const data = await fetchNewResources();
|
||||
|
||||
// Cache it
|
||||
await setCache(cacheKey, data, ttl);
|
||||
|
||||
return c.json(data);
|
||||
} catch (err) {
|
||||
console.error('[new-resource] Error:', err);
|
||||
return c.json({ error: 'Server error' }, 500);
|
||||
}
|
||||
});
|
||||
|
||||
export default app;
|
||||
```
|
||||
|
||||
**3. Register route in `backend/src/index.ts`**
|
||||
```typescript
|
||||
import newRoutes from './routes/new';
|
||||
app.route('/api', newRoutes);
|
||||
```
|
||||
|
||||
**4. Call from frontend**
|
||||
```javascript
|
||||
const response = await fetch('/api/new-resource');
|
||||
const data = await response.json();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Adding a New View
|
||||
|
||||
**1. Design in [VIEWS.md](./VIEWS.md)**
|
||||
- Define purpose
|
||||
- List components
|
||||
- Sketch HTML structure
|
||||
|
||||
**2. Create `frontend/src/views/new-view.ts`**
|
||||
```typescript
|
||||
export function renderNewView() {
|
||||
const container = document.getElementById('app');
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="new-view-container">
|
||||
<!-- HTML here -->
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add event listeners
|
||||
setupEventListeners();
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
const btn = document.getElementById('myButton');
|
||||
if (btn) {
|
||||
btn.addEventListener('click', handleButtonClick);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleButtonClick() {
|
||||
// Handle click
|
||||
}
|
||||
```
|
||||
|
||||
**3. Call from `frontend/public/index.html`**
|
||||
```html
|
||||
<script>
|
||||
import { renderNewView } from './src/views/new-view.ts';
|
||||
|
||||
window.onNewViewNeeded = () => {
|
||||
renderNewView();
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Modifying Cache Behavior
|
||||
|
||||
**1. Check [RULES.md](./RULES.md) - Cache section**
|
||||
2. **Update cache key format** (must follow `noun:filter:value` pattern)
|
||||
3. **Test cache hit/miss** with browser DevTools → Network
|
||||
4. **Document in [API.md](../docs/API.md)** - Cache TTL
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// OLD: jobs:page:1:10
|
||||
const cacheKey = `jobs:page:${page}:perPage:${perPage}:sort:${sort}`;
|
||||
|
||||
// NEW: jobs:${page}:${perPage}:${sort}
|
||||
const cacheKey = `jobs:${page}-${perPage}-${sort}`;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
# Backend tests
|
||||
bun test backend/tests/**/*.test.ts
|
||||
|
||||
# Frontend tests (if using Vitest)
|
||||
bun test frontend/tests/**/*.test.ts
|
||||
|
||||
# All tests
|
||||
bun test
|
||||
```
|
||||
|
||||
### Write Tests
|
||||
|
||||
**Backend:**
|
||||
```typescript
|
||||
// backend/tests/jobs.test.ts
|
||||
import { expect } from 'bun:test';
|
||||
import { getJobs } from '../src/routes/jobs';
|
||||
|
||||
describe('Jobs API', () => {
|
||||
it('should cache jobs list', async () => {
|
||||
const result = await getJobs(1, 10, '-Job_Number');
|
||||
expect(result).toHaveProperty('items');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
```typescript
|
||||
// frontend/tests/auth.test.ts
|
||||
import { expect } from 'bun:test';
|
||||
import { isUserLoggedIn } from '../src/auth/client';
|
||||
|
||||
describe('Auth', () => {
|
||||
it('should detect logged in user', () => {
|
||||
const loggedIn = isUserLoggedIn();
|
||||
expect(typeof loggedIn).toBe('boolean');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Backend Debugging
|
||||
|
||||
**1. Check logs:**
|
||||
```bash
|
||||
tail -f logs/server.log # Server logs
|
||||
tail -f logs/error.log # Error logs
|
||||
```
|
||||
|
||||
**2. Enable verbose logging:**
|
||||
```typescript
|
||||
console.log('[endpoint] Request received:', c.req.query());
|
||||
console.log('[endpoint] Cache key:', cacheKey);
|
||||
console.log('[endpoint] Cache hit:', cached ? 'YES' : 'NO');
|
||||
```
|
||||
|
||||
**3. Use browser DevTools:**
|
||||
- Network tab → see API requests
|
||||
- Console tab → see client errors
|
||||
- Application tab → check localStorage & cookies
|
||||
|
||||
### Frontend Debugging
|
||||
|
||||
**1. Browser Console:**
|
||||
```javascript
|
||||
// Check auth token
|
||||
console.log(localStorage.getItem('pocketbase_auth'));
|
||||
|
||||
// Check state
|
||||
console.log(window.fileListState);
|
||||
|
||||
// Check cache
|
||||
console.log(window.fileCache);
|
||||
```
|
||||
|
||||
**2. Check network requests:**
|
||||
- DevTools → Network tab
|
||||
- Filter by XHR
|
||||
- Check request/response headers & body
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✅ DO
|
||||
|
||||
```typescript
|
||||
// ✅ Type all functions
|
||||
async function getJob(jobId: string): Promise<Job | null> {
|
||||
// Implementation
|
||||
}
|
||||
|
||||
// ✅ Validate input
|
||||
const page = Math.max(1, parseInt(c.req.query('page') || '1'));
|
||||
|
||||
// ✅ Log important events
|
||||
console.log('[auth] User logged in:', userId);
|
||||
|
||||
// ✅ Use cache
|
||||
const cached = await getCache(key);
|
||||
if (cached) return c.json(cached);
|
||||
|
||||
// ✅ Handle errors gracefully
|
||||
try {
|
||||
// ...
|
||||
} catch (err) {
|
||||
console.error('Operation failed:', err);
|
||||
return c.json({ error: 'Server error' }, 500);
|
||||
}
|
||||
```
|
||||
|
||||
### ❌ DON'T
|
||||
|
||||
```typescript
|
||||
// ❌ Untyped functions
|
||||
function getJob(jobId) { }
|
||||
|
||||
// ❌ Unvalidated input
|
||||
const page = c.req.query('page');
|
||||
|
||||
// ❌ No logging
|
||||
// Just silently fail
|
||||
|
||||
// ❌ No caching
|
||||
fetch('/api/jobs'); // Every time!
|
||||
|
||||
// ❌ Silent failures
|
||||
try {
|
||||
// ...
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Before Asking
|
||||
|
||||
1. **Check documentation** - RULES.md, FLOWMAP.md, VIEWS.md
|
||||
2. **Search existing code** - Find similar patterns
|
||||
3. **Check error logs** - logs/error.log
|
||||
4. **Read the code** - Comments explain the "why"
|
||||
|
||||
### How to Ask
|
||||
|
||||
Provide:
|
||||
1. **What you were trying to do**
|
||||
2. **What happened**
|
||||
3. **What you expected**
|
||||
4. **Relevant code/logs**
|
||||
|
||||
**Example:**
|
||||
```
|
||||
I was trying to add caching to the new /api/jobs-by-manager endpoint.
|
||||
I created the route but the cache never hits (always MISS).
|
||||
I expected the second request to return from cache.
|
||||
|
||||
Cache key: jobs-by-manager:${managerId}
|
||||
TTL: 300 seconds
|
||||
|
||||
[Cache MISS] logs show it's not finding the cached value.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Version Control
|
||||
|
||||
### Commit Messages
|
||||
|
||||
**Format:** `<type>: <description>`
|
||||
|
||||
**Types:**
|
||||
- `feat:` - New feature
|
||||
- `fix:` - Bug fix
|
||||
- `docs:` - Documentation
|
||||
- `refactor:` - Code cleanup
|
||||
- `perf:` - Performance improvement
|
||||
- `test:` - Add/update tests
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
feat: add caching to jobs list
|
||||
fix: incorrect file categorization
|
||||
docs: update API documentation
|
||||
refactor: simplify state management
|
||||
perf: optimize database queries
|
||||
test: add tests for auth flow
|
||||
```
|
||||
|
||||
### Branching
|
||||
|
||||
```bash
|
||||
# Create feature branch
|
||||
git checkout -b feature/new-feature
|
||||
|
||||
# Make changes
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
|
||||
# Push and create PR
|
||||
git push origin feature/new-feature
|
||||
```
|
||||
|
||||
### Before Pushing
|
||||
|
||||
- [ ] Tests pass
|
||||
- [ ] No console errors
|
||||
- [ ] Follows RULES.md
|
||||
- [ ] Code is commented
|
||||
- [ ] Documentation updated
|
||||
|
||||
---
|
||||
|
||||
## Deploying to Production
|
||||
|
||||
**See [DEPLOYMENT.md](../docs/DEPLOYMENT.md) for full instructions.**
|
||||
|
||||
**Quick Summary:**
|
||||
```bash
|
||||
# 1. Test locally
|
||||
bun test
|
||||
|
||||
# 2. Build
|
||||
bun run build
|
||||
bun run build:css
|
||||
|
||||
# 3. Deploy
|
||||
# Use your deployment script
|
||||
# (AWS, Heroku, Docker, etc.)
|
||||
|
||||
# 4. Verify
|
||||
# Check health endpoint
|
||||
curl https://production-url/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Where do I put new code?**
|
||||
A: Follow the folder structure - routes in `backend/src/routes/`, views in `frontend/src/views/`, etc.
|
||||
|
||||
**Q: How do I add a new dependency?**
|
||||
A: `bun add package-name` - it auto-updates package.json
|
||||
|
||||
**Q: Can I use Express instead of Hono?**
|
||||
A: No - see TECH_STACK.md. Stick with Hono for consistency.
|
||||
|
||||
**Q: How do I debug TypeScript errors?**
|
||||
A: Check your `tsconfig.json` and enable all strict checks. VSCode will show errors immediately.
|
||||
|
||||
**Q: Can I skip type annotations?**
|
||||
A: No - RULES.md requires all functions to be typed. Use `as unknown` if necessary, but avoid it.
|
||||
|
||||
**Q: How often should I cache?**
|
||||
A: Cache GET requests always. Use TTL of 5-15 minutes depending on data freshness needs.
|
||||
|
||||
---
|
||||
|
||||
## Staying Updated
|
||||
|
||||
### Read When Updating Docs
|
||||
|
||||
- RULES.md - When adding features
|
||||
- FLOWMAP.md - When changing user flows
|
||||
- VIEWS.md - When adding UI
|
||||
- TECH_STACK.md - When updating dependencies
|
||||
|
||||
### Update Docs When
|
||||
|
||||
- Adding new data patterns
|
||||
- Changing API contracts
|
||||
- Adding new views
|
||||
- Modifying caching strategy
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
You now have everything needed to:
|
||||
|
||||
- ✅ Understand the application
|
||||
- ✅ Set up development environment
|
||||
- ✅ Add new features (backend & frontend)
|
||||
- ✅ Debug issues
|
||||
- ✅ Deploy to production
|
||||
- ✅ Maintain code quality
|
||||
|
||||
**Most important:** Read RULES.md. It covers 90% of development decisions.
|
||||
|
||||
**Questions?** Check the documentation, search the code, or ask senior developers.
|
||||
|
||||
---
|
||||
|
||||
**Welcome to the team! 🚀**
|
||||
Reference in New Issue
Block a user