646 lines
15 KiB
Markdown
646 lines
15 KiB
Markdown
# 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! 🚀**
|