Architecture
Habits Factory follows a modern API-first architecture with clear separation between the frontend and backend layers.
Design Principles
API-First Approach
The application is built around a RESTful API that serves as the single source of truth:
- Independent Evolution - Frontend and backend can be developed and deployed separately
- Explicit Contracts - API endpoints define clear, versionable data contracts
- Stateless Communication - Each request contains all necessary information
- Testable Logic - Business logic is isolated and easy to test
Data Flow
┌─────────────┐ ┌─────────────────┐ ┌────────────────┐
│ Vue.js │────▶│ Axios Client │────▶│ Django REST │
│ Frontend │ │ HTTP Requests │ │ Framework │
└─────────────┘ └─────────────────┘ └────────────────┘
▲ │
│ ▼
│ ┌─────────────────┐ ┌────────────────┐
└────────────│ JSON Response │◀────│ PostgreSQL │
│ │ │ Database │
└─────────────────┘ └────────────────┘
The flow ensures:
- Clear layer boundaries
- Predictable data movement
- Independent component evolution
Backend Architecture
Technology Stack
| Component | Technology | Purpose |
|---|---|---|
| Framework | Django | High-level Python web framework |
| API Layer | Django REST Framework | Serialization, validation, authentication |
| Database | PostgreSQL (prod) / SQLite (dev) | Data persistence |
| CORS | django-cors-headers | Cross-origin communication |
Layer Structure
backend/
├── api/ # API configuration and routing
│ ├── urls.py # URL patterns
│ └── views.py # API viewsets
├── habits/ # Core domain logic
│ ├── models.py # Data models
│ ├── serializers.py # Data transformation
│ └── views.py # Business logic
├── analytics/ # Correlation engine
│ ├── correlations.py # Algorithm implementations
│ └── services.py # Analytics services
└── core/ # Project settings
└── settings.py # Django configuration
Key Design Decisions
Model-Serializer-View Pattern
# models.py - Data structure
class Habit(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
# serializers.py - Data transformation
class HabitSerializer(serializers.ModelSerializer):
class Meta:
model = Habit
fields = ['id', 'name', 'category', 'created_at']
# views.py - Business logic
class HabitViewSet(viewsets.ModelViewSet):
queryset = Habit.objects.all()
serializer_class = HabitSerializer
Separation of Concerns
- Models define data structure and database schema
- Serializers handle validation and transformation
- Views orchestrate business logic
- Services encapsulate complex operations
Frontend Architecture
Technology Stack
| Component | Technology | Purpose |
|---|---|---|
| Framework | Vue.js 3 | Reactive UI framework |
| Build Tool | Vite | Fast development and bundling |
| Styling | Tailwind CSS v4 | Utility-first CSS |
| HTTP Client | Axios | Promise-based API calls |
| Icons | Lucide Vue Next | Modern icon system |
Component Structure
frontend/src/
├── api/ # API client configuration
│ └── client.js # Axios instance
├── components/ # Reusable UI components
│ ├── common/ # Generic components
│ ├── habits/ # Habit-specific components
│ └── analytics/ # Analytics visualizations
├── views/ # Page-level components
│ ├── Dashboard.vue # Main dashboard
│ ├── Habits.vue # Habit management
│ └── Analytics.vue # Analytics view
├── stores/ # State management
│ └── habits.js # Habit store
└── composables/ # Reusable logic
└── useHabits.js # Habit operations
Composition API Pattern
Vue 3's Composition API with <script setup> provides:
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useHabits } from '@/composables/useHabits'
const { habits, fetchHabits, createHabit } = useHabits()
const newHabitName = ref('')
const activeHabits = computed(() =>
habits.value.filter(h => h.isActive)
)
onMounted(() => {
fetchHabits()
})
</script>
Benefits:
- Better TypeScript support
- Logical code organization
- Reusable composables
- Cleaner component files
Database Schema
Core Entities
┌─────────────┐ ┌─────────────────┐
│ Category │ │ Habit │
├─────────────┤ ├─────────────────┤
│ id │◀──────│ category_id │
│ name │ │ id │
│ color │ │ name │
│ created_at │ │ description │
└─────────────┘ │ created_at │
└─────────────────┘
│
│
┌───────▼───────┐
│ HabitEntry │
├───────────────┤
│ id │
│ habit_id │
│ date │
│ completed │
│ value │
└───────────────┘
Relationships
- A Category contains many Habits
- A Habit has many HabitEntries (daily records)
- HabitEntries store completion status and optional values
Security Considerations
Backend Security
- CSRF protection enabled
- CORS configured for allowed origins only
- Input validation through serializers
- SQL injection prevention via ORM
Frontend Security
- Environment variables for sensitive config
- XSS protection through Vue's template system
- Secure HTTP-only cookies for authentication
Performance Optimizations
Backend
- Database query optimization with
select_relatedandprefetch_related - Pagination for list endpoints
- Efficient correlation calculations
Frontend
- Vite's Hot Module Replacement for fast development
- Component lazy loading
- Reactive state updates (no full page refreshes)
Extensibility
The architecture supports easy extension:
- New Analytics - Add algorithms to the analytics service
- New Features - Create new Django apps and Vue components
- Integrations - Add external services through the API layer
- Themes - Tailwind configuration allows custom styling
See the Roadmap for planned enhancements.