Complete guide for ShadowCheck development
- Node.js 22+ (LTS recommended)
- PostgreSQL 18+ with PostGIS extension
- Docker (optional, for containerized development)
- Git
git clone https://github.com/cyclonite69/shadowcheck-web.git
cd shadowcheck-webnpm install# Secrets policy: do not create local .env files with credentials; use AWS Secrets Manager or explicit env-var overrides
docker compose up -d# Terminal 1: Backend
npm run dev
# Terminal 2: Frontend
npm run dev:frontend- Docker Desktop
- VS Code with Dev Containers extension
- Open in DevContainer (VS Code will prompt)
- Wait for container build
- Start developing:
npm run dev # Backend (port 3001) npm run dev:frontend # Frontend (port 5173)
To streamline local development, source the included helper aliases:
source ./scripts/local-dev-aliases.shCommon Tasks:
scroot- Repository root navigation.sclocal- Genericdocker composewrapper.scapi- Reset/rebuild API with AWS development defaults.scgrafana- Launch local monitoring stack.scdb- Connect toshadowcheck_userdatabase.scdba- Connect toshadowcheck_admindatabase.
# Development
**Docs version (repo):** [docs/DEVELOPMENT.md](../../docs/DEVELOPMENT.md)
npm run dev # Backend with nodemon
npm run dev:frontend # Frontend with Vite HMR
# Building
npm run build # Build frontend and server
npm run build:frontend # Build React app
npm run build:server # Compile TypeScript
# Testing
npm test # Run all tests
npm run test:cov # Tests with coverage
npm run test:integration # Integration tests only
# Code Quality
npm run lint # ESLint check
npm run lint:fix # Auto-fix issues
npm run format:check # Prettier check
npm run format # Auto-format
# Docker
npm run docker:up # Start containers
npm run docker:down # Stop containers- Create route handler in
server/src/api/routes/v1/:
// server/src/api/routes/v1/my-feature.ts
import { Router } from 'express';
import { container } from '../../../config/container';
const router = Router();
router.get('/', async (req, res, next) => {
try {
const service = container.get('myService');
const data = await service.getData();
res.json({ ok: true, data });
} catch (err) {
next(err);
}
});
export default router;- Add business logic in
server/src/services/:
// server/src/services/myService.ts
export class MyService {
async getData() {
// Business logic here
}
}- Register in container:
// server/src/config/container.ts
container.register('myService', new MyService());- Mount route in server initialization
- Create component:
// client/src/components/MyComponent.tsx
import React from 'react';
export const MyComponent: React.FC = () => {
return <div className="p-4">My Component</div>;
};- Add route in
App.tsx:
import { lazy } from 'react';
const MyComponent = lazy(() => import('./components/MyComponent'));
<Route path="/my-route" element={<MyComponent />} />;- Add navigation link in
Navigation.tsx
# Connect to database
docker exec -it postgres psql -U shadowcheck_user -d shadowcheck_db
# Run migration
docker exec -i postgres psql -U shadowcheck_user -d shadowcheck_db < sql/migrations/your_migration.sql
# Backup database
pg_dump -U shadowcheck_user -d shadowcheck_db -F c -f backup_$(date +%Y%m%d).dump-- Count networks by type
SELECT type, COUNT(*) FROM public.networks GROUP BY type;
-- Recent observations
SELECT * FROM public.observations
WHERE time >= EXTRACT(EPOCH FROM NOW() - INTERVAL '1 day') * 1000
LIMIT 10;
-- Tagged networks
SELECT bssid, tag_type, confidence FROM app.network_tags;# All tests
npm test
# Specific test
npm test -- tests/unit/your-test.test.js
# With coverage
npm run test:cov// tests/api/dashboard-metrics.test.js
const request = require('supertest');
const app = require('../../server');
describe('GET /api/dashboard-metrics', () => {
it('should return dashboard metrics', async () => {
const response = await request(app).get('/api/dashboard-metrics').expect(200);
expect(response.body).toHaveProperty('totalNetworks');
});
});Husky runs automatically for repo checks such as the secret-scan flow.
- ESLint
- Prettier
- Secret scanning
CI also runs secret scanning on push / PR and a scheduled full-history scan, so local hooks are not the only enforcement layer.
Follow Conventional Commits:
feat:New featurefix:Bug fixdocs:Documentation changestest:Test additionsrefactor:Code refactoringchore:Maintenance tasks
# Verify Docker PostgreSQL is running
docker ps | grep postgres
# Test connection
docker exec postgres psql -U shadowcheck_user -d shadowcheck_db# Find process using port
lsof -i :3001
# Kill process
kill -9 <PID># Increase Node.js heap size
NODE_OPTIONS="--max-old-space-size=4096" npm start- Architecture - System design
- API Reference - REST API documentation
- Database - Schema reference
- Troubleshooting - Common issues