A web application for managing aquarium society Breeder Awards Programs (BAP), tracking breeding achievements, managing member submissions, and handling species data.
Production: https://bap.basny.org
- Member Management: User registration, authentication, and profile management
- Submission System: Track breeding achievements with photos and detailed information
- Witness Verification: Multi-stage verification process for submissions
- Waiting Period Tracking: Automatic calculation of species-specific waiting periods
- Awards & Standings: Real-time leaderboards and award progression tracking
- Species Database: Comprehensive fish, coral, plant, and invertebrate species catalog
- Admin Tools: Approval queue, witness management, member administration
- Image Processing: Automatic image optimization and multiple size variants
- Activity Feed: Real-time updates on submissions, approvals, and achievements
- Runtime: Node.js with TypeScript
- Framework: Express.js
- Database: SQLite with migrations
- Session Management: Cookie-based sessions
- Authentication: OAuth integration (Google)
- Email: Nodemailer for notifications
- Image Processing: Sharp for image optimization
- Storage: Cloudflare R2 for image storage
- Template Engine: Pug templates
- Interactivity: HTMX for dynamic updates
- Styling: Tailwind CSS with PostCSS
- Build Tools: esbuild for bundling
- Hosting: AWS EC2 (t3.micro)
- Reverse Proxy: nginx with Let's Encrypt SSL
- Deployment: Docker Compose
- IaC: AWS CDK (TypeScript)
- CI/CD: GitHub Actions
- Node.js 20.x or higher
- npm or yarn
- SQLite3
# Clone the repository
git clone https://github.com/jra3/mulm.git
cd mulm
# Install dependencies
npm install
# Create configuration file
cp src/config.sample.json src/config.json
# Edit src/config.json with your settingsCreate src/config.json with the following structure (see src/config.sample.json for complete example):
{
"databaseFile": "db/database.db",
"domain": "localhost:4200",
"disableEmails": true,
"googleClientId": "",
"googleClientSecret": "",
"adminsEmail": "admin@example.com",
"bugReportEmail": "bugs@example.com",
"fromEmail": "noreply@example.com",
"smtpPassword": "",
"smtpHost": "",
"smtpPort": 465,
"smtpSecure": true,
"s3AccessKeyId": "",
"s3Secret": "",
"s3Url": "",
"s3Bucket": "",
"r2PublicUrl": "",
"webauthn": {
"rpName": "BAP Portal",
"rpID": "localhost",
"origin": "http://localhost:4200"
},
"mcp": {
"enabled": false,
"port": 3001,
"host": "127.0.0.1"
}
}The database is automatically initialized with migrations on first run:
npm run devMigrations are located in db/migrations/ and run automatically at startup.
npm run dev # Start development server with hot reload
npm run build # Build TypeScript and PostCSS assets
npm test # Run test suite
npm test -- --watch # Run tests in watch mode
npm run lint # Run ESLint
npm run lint:fix # Fix ESLint issues
npm run script # Run scripts with ts-node (e.g., npm run script scripts/example.ts)
npm start # Start production server (requires build first)npm run devThe server will start on http://localhost:4200 with:
- Hot reload for TypeScript changes (Nodemon)
- Automatic CSS rebuilding (PostCSS watch)
- Source maps for debugging
mulm/
├── db/
│ └── migrations/ # Database migration files
├── infrastructure/ # AWS CDK infrastructure code
├── nginx/ # nginx configuration for production
├── scripts/ # Utility scripts
├── src/
│ ├── __tests__/ # Test files
│ ├── db/ # Database layer (queries, models)
│ ├── forms/ # Zod form validation schemas
│ ├── routes/ # Express route handlers
│ ├── utils/ # Utility functions
│ ├── views/ # Pug templates
│ ├── config.json # Configuration (git-ignored)
│ └── index.ts # Application entry point
├── docker-compose.prod.yml # Production Docker Compose
└── package.json
The project uses Node.js native test runner (migrated from Jest):
# Run all tests
npm test
# Run specific test file
npm test -- src/__tests__/image-processor.test.ts
# Run tests in watch mode
npm test -- --watchTest Coverage:
- Unit tests for image processing, validation, and utilities
- Integration tests for witness workflow and database operations
- Template rendering tests for all Pug templates
- Rate limiter middleware tests
- E2E tests for critical user flows
Current Status: All tests passing. Run npm test and npm run test:e2e to verify.
members- User accounts and profilessubmissions- Breeding achievement recordsspecies_name_group- Species groups with canonical taxonomic namesspecies_common_name- Common name variants for speciesspecies_scientific_name- Scientific name variants for speciestank_presets- User-saved tank configurationsawards- Award definitions and point thresholdssessions- Cookie-based session storageactivity_feed- Activity log for member dashboard
Migrations run automatically on startup. To create a new migration:
# Create migration file in db/migrations/
# Format: NNN-description.sql (where NNN is next sequential 3-digit number)
# Example: 039-add-my-feature.sqlComprehensive documentation is available in the GitHub Wiki:
- Security Overview - Security posture, audits, and active initiatives
- Production Deployment - Deploy code changes, troubleshooting, SSL management
- Infrastructure Guide - AWS resources, critical resource protection, CDK deployment
# Deploy latest code from main branch
ssh BAP "cd /opt/basny && git pull && sudo docker-compose -f docker-compose.prod.yml up -d --build"For detailed deployment procedures, troubleshooting, and infrastructure management, see the Production Deployment and Infrastructure Guide wiki pages.
- Config file:
src/config.json(git-ignored) - Contains database path, OAuth credentials, SMTP settings, R2 storage keys
- Config file:
/mnt/basny-data/app/config/config.production.json - Mounted read-only into container at
/app/src/config.json - Permissions: Must be 600 (owner-only) and owned by UID 1001 (nodejs user)
The application uses RESTful conventions:
GET /submissions/:id- View submission detailsPOST /submissions- Create new submissionPATCH /submissions/:id- Update submissionDELETE /submissions/:id- Delete submission
GET /admin/queue- Approval queueGET /admin/witness-queue- Witness verification queuePOST /admin/submissions/:id/approve- Approve submissionPOST /admin/submissions/:id/deny- Deny submission
See src/routes/README.md for complete route documentation and API reference.
- TypeScript with strict type checking
- ESLint for code quality
- Prettier for formatting (via ESLint)
- Pug templates with specific Tailwind conventions
- Create a feature branch from
main - Make your changes with tests
- Run
npm run lintandnpm test - Push and create a pull request
- CI will automatically run tests and linting
Critical Rules:
- Use double quotes for attributes
- Break long Tailwind class chains across lines
- Use class attribute for modifiers (hover:, md:, focus:)
- Simple utilities only with dot notation
See src/views/README.md for detailed Pug template guidelines and Tailwind best practices.
MIT License - see package.json for details
For issues or questions, please open an issue on GitHub.