BCF
There are no high-quality resources for perfumers to avail of on the Internet. Disparate opinions, niche treasures, badly-built websites. I needed an app that would let perfumers find perfume ingredients, bring system to their huge collections of compounds, and write formulas anywhere on this earth.
See for yourself View the code
Main Page
1 / 4
BCF – The Perfumers' Digital Lab
Overview
BCF (Browse, Collect, Formulate) is an open-source, self-hosted platform that serves as a comprehensive digital laboratory for perfumers. It combines a robust Rust backend with a responsive Svelte frontend to deliver a Wikipedia-style collaborative environment for perfume formulation and knowledge sharing.
Architecture
Backend (Rust)
- Framework: Axum for high-performance, async web services
- Database Access: SQLx for type-safe SQL queries without an ORM
- API Design: RESTful endpoints with JSON payloads
- Performance Optimization: Redis caching layer for frequently accessed data
- Authentication: JWT-based auth flow with separate access and refresh tokens
Frontend (Svelte)
- Server-Side Features: Leverages Svelte's native SSR capabilities
- State Management: Built-in Svelte stores
- Form Handling: Custom Svelte form actions with client-side validation
Database Schema
- Primary Store: PostgreSQL with optimized indexes for ingredient searches
- Caching Layer: Redis for frequent queries and unsplash data caching
- Data Models:
- Ingredients (3100+ entries)
- User Profiles
- Formulations
- Contributions
- Collection Ingredients
Infrastructure
- Containerization: Multi-stage Docker builds for optimal image sizes
- Container Registry: GitHub Packages for version control
- Deployment: VPS with Docker Compose orchestration
- SSL/TLS: Automated certificate management
- Backup Strategy: Automated PostgreSQL dumps with retention policies
Core Functionalities
1. Database Operations
-- Example of raw SQL usage with SQLx
WITH descriptor_info AS (
SELECT
i.*,
array_remove(array_agg (DISTINCT d.name), NULL) as descriptors,
array_remove(array_agg (DISTINCT d.colour), NULL) as colours
FROM ingredients i
LEFT JOIN ingredient_descriptors id ON i.id = id.ingredient_id
LEFT JOIN descriptors d ON id.descriptor_id = d.id
WHERE i.slug = $1
GROUP BY i.id
)
SELECT * FROM descriptor_info
2. Security Implementation
- Authentication Flow:
- JWT token generation and validation
- Refresh token rotation
- Server-side session validation
- Access Control:
- Role-based authorization
- Resource-level permissions
- Rate limiting with Redis
3. API Integration
- External Services:
- Unsplash API for dynamic imagery
- IFRA database synchronization
- Captcha verification
- Error Handling:
- Structured error responses
- Automatic retry mechanisms
- Rate limit compliance
4. Performance Optimizations
- Caching Strategy:
- Redis for session data
- Application-level caching for static content
- Database query optimization
- Load Management:
- Connection pooling
- Query batching
- Async operations
Development Workflow
Local Development
# Development environment setup
docker-compose -f docker-compose.dev.yml up
# Database migrations (should be run inside of the axum container)
sqlx migrate run
# Frontend development
npm run dev
Deployment Pipeline
- GitHub Actions workflow triggers on push to main
- Runs tests and builds Docker images
- Pushes to GitHub Packages
- Deploys to VPS via webhook
- Performs health checks and rollback if necessary
Technical Roadmap
Short-term Goals
- Enhance search with full-text capabilities
Long-term Vision
- Distributed caching with Redis Cluster
- API marketplace for third-party integrations