Brain
An independent recommendation product combining semantic search, a server-rendered interface, and feedback across different kinds of content.
From concept to working product
Brain is my full-stack exploration of content discovery through semantic recommendations. I built the Django data layer and background processing alongside an HTMX and Alpine.js interface, connecting vector search, user reactions, and multilingual browsing in one product.
- Python
- Django
- PostgreSQL
- Redis
- HTMX
- Tailwind
- Alpine.js
What I built
Brain continues the idea behind Card Piper: help people discover content worth exploring. I worked across the product concept, data model, recommendation logic, interface, and deployment. This version uses Python and semantic embeddings with a server-rendered interface, letting me explore a different way to build the same kind of experience.
Changing the recommendation model
Card Piper modeled preferences with personality-inspired scores and Euclidean distance. Brain uses 384-dimensional embeddings from all-MiniLM-L6-v2 to compare content descriptions. This removes the need to hand-map every item into personality dimensions and makes cross-category discovery possible. Similarity is still a signal to evaluate, rather than proof that the system understands a person or an item.
One data store for content and similarity
PostgreSQL with pgvector keeps content, user reactions, and similarity queries in one place. I can combine a vector search with category filters and relational constraints without maintaining a separate search database. It is a practical choice for the project’s current needs and keeps the system easier to inspect and change.

The backend and data workflow
Django provides the models, migrations, administration, and request handling; Django REST Framework supports the API. Using Python also keeps embedding experiments close to the application code. The backend decision came from the data and iteration needs of this product, rather than an assumption that one framework is right for every application.
Designing the interface around server-rendered HTML
Django templates, HTMX, Alpine.js, and Tailwind form the interface. HTMX handles interactions such as loading more content and updating reactions; Alpine handles local controls such as dropdowns and toggles. I chose this approach to keep rendering and application state close together. Card Piper used React and Redux; Brain gave me a useful comparison of how different frontend architectures fit a product.
Feedback as part of the experience
The interface offers five reactions: Mind, Heart, Fire, Puzzle, and Void. They distinguish intellectual interest, emotional response, inspiration, questions, and lack of interest. The recommendation logic uses that feedback to refine suggestions. Designing the controls and deciding how the data affects the next feed are parts of the same feature.
Connecting different kinds of content
Books, films, music, people, places, and other entity types share a searchable representation. The product explores whether similarities between their descriptions can lead to useful discoveries across categories. That makes the quality of the source data, the recommendation model, and the way suggestions are presented equally important.

Keeping expensive work off the request path
Celery handles embedding generation and recommendation preparation in the background, with Redis providing the broker and cache. That separates computational work from the requests used to browse the feed. The design also makes it possible to adjust background processing without rebuilding the interface.
English and Polish
The application supports English and Polish through Django’s internationalization tools. I included translation strings, language selection, and locale-aware formatting in the interface work. Treating localization as part of the product early made it easier to keep behavior consistent across both languages.
What the project taught me
Brain brought the data model, recommendation approach, interface, and background processing into one set of decisions. A better similarity model is only useful if people can browse and respond to the results; a clean interface still depends on usable source data. Building both sides made those trade-offs visible and gave me a more practical basis for choosing between React-based and server-rendered applications.
