Files
Samir Boulahtit 35d1559162
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 47m30s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
feat(monitoring): add Redis exporter + Sentry docs to deployment guide
- Add redis-exporter container to docker-compose (oliver006/redis_exporter, 32MB)
- Add Redis scrape target to Prometheus config
- Add 4 Redis alert rules: RedisDown, HighMemory, HighConnections, RejectedConnections
- Document Step 19b (Sentry Error Tracking) in Hetzner deployment guide
- Document Step 19c (Redis Monitoring) in Hetzner deployment guide
- Update resource budget and port reference tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:30:18 +01:00

361 lines
8.9 KiB
Markdown

# THEME PRESETS USAGE GUIDE
## What Changed in Your Presets
### ✅ What You Had Right
- Good preset structure with colors, fonts, layout
- Clean `apply_preset()` function
- Good preset names (modern, classic, minimal, vibrant)
### 🔧 What We Added
1. **Missing color fields:** `background`, `text`, `border`
2. **Missing layout field:** `product_card` style
3. **"default" preset:** Your platform's default theme
4. **Extra presets:** "elegant" and "nature" themes
5. **Helper functions:** `get_preset()`, `get_available_presets()`, `get_preset_preview()`
6. **Custom preset builder:** `create_custom_preset()`
---
## Usage Examples
### 1. Apply Preset to New Store
```python
from models.database.store_theme import StoreTheme
from app.core.theme_presets import apply_preset
from app.core.database import SessionLocal
# Create theme for store
db = SessionLocal()
store_id = 1
# Create and apply preset
theme = StoreTheme(store_id=store_id)
apply_preset(theme, "modern")
db.add(theme)
db.commit()
```
### 2. Change Store's Theme
```python
from models.database.store_theme import StoreTheme
from app.core.theme_presets import apply_preset
# Get existing theme
theme = db.query(StoreTheme).filter(
StoreTheme.store_id == store_id
).first()
if theme:
# Update to new preset
apply_preset(theme, "classic")
else:
# Create new theme
theme = StoreTheme(store_id=store_id)
apply_preset(theme, "classic")
db.add(theme)
db.commit()
```
### 3. Get Available Presets (For UI Dropdown)
```python
from app.core.theme_presets import get_available_presets, get_preset_preview
# Get list of preset names
presets = get_available_presets()
# Returns: ['default', 'modern', 'classic', 'minimal', 'vibrant', 'elegant', 'nature']
# Get preview info for UI
previews = []
for preset_name in presets:
preview = get_preset_preview(preset_name)
previews.append(preview)
# Returns list of dicts with:
# {
# "name": "modern",
# "description": "Contemporary tech-inspired design...",
# "primary_color": "#6366f1",
# "secondary_color": "#8b5cf6",
# ...
# }
```
### 4. API Endpoint to Apply Preset
```python
# In your API route
from fastapi import APIRouter, Depends
from app.core.theme_presets import apply_preset, get_available_presets
@router.put("/theme/preset")
def apply_theme_preset(
preset_name: str,
store: Store = Depends(require_store_context()),
db: Session = Depends(get_db),
):
"""Apply a theme preset to store."""
# Validate preset name
if preset_name not in get_available_presets():
raise HTTPException(
status_code=400,
detail=f"Invalid preset. Available: {get_available_presets()}"
)
# Get or create store theme
theme = db.query(StoreTheme).filter(
StoreTheme.store_id == store.id
).first()
if not theme:
theme = StoreTheme(store_id=store.id)
db.add(theme)
# Apply preset
apply_preset(theme, preset_name)
db.commit()
db.refresh(theme)
return {
"message": f"Theme preset '{preset_name}' applied successfully",
"theme": theme.to_dict()
}
```
### 5. Get All Presets for Theme Selector
```python
@router.get("/theme/presets")
def get_theme_presets():
"""Get all available theme presets with previews."""
from app.core.theme_presets import get_available_presets, get_preset_preview
presets = []
for preset_name in get_available_presets():
preview = get_preset_preview(preset_name)
presets.append(preview)
return {"presets": presets}
# Returns:
# {
# "presets": [
# {
# "name": "default",
# "description": "Clean and professional...",
# "primary_color": "#6366f1",
# "secondary_color": "#8b5cf6",
# "accent_color": "#ec4899",
# "heading_font": "Inter, sans-serif",
# "body_font": "Inter, sans-serif",
# "layout_style": "grid"
# },
# ...
# ]
# }
```
### 6. Create Custom Theme (Not from Preset)
```python
from app.core.theme_presets import create_custom_preset
# User provides custom colors
custom_preset = create_custom_preset(
colors={
"primary": "#ff0000",
"secondary": "#00ff00",
"accent": "#0000ff",
"background": "#ffffff",
"text": "#000000",
"border": "#cccccc"
},
fonts={
"heading": "Arial, sans-serif",
"body": "Verdana, sans-serif"
},
layout={
"style": "grid",
"header": "fixed",
"product_card": "modern"
},
name="my_custom"
)
# Apply to store theme
theme = StoreTheme(store_id=store_id)
theme.theme_name = "custom"
theme.colors = custom_preset["colors"]
theme.font_family_heading = custom_preset["fonts"]["heading"]
theme.font_family_body = custom_preset["fonts"]["body"]
theme.layout_style = custom_preset["layout"]["style"]
theme.header_style = custom_preset["layout"]["header"]
theme.product_card_style = custom_preset["layout"]["product_card"]
theme.is_active = True
db.add(theme)
db.commit()
```
---
## Available Presets
| Preset | Description | Primary Color | Use Case |
|--------|-------------|---------------|----------|
| `default` | Clean & professional | Indigo (#6366f1) | General purpose |
| `modern` | Tech-inspired | Indigo (#6366f1) | Tech products |
| `classic` | Traditional | Dark Blue (#1e40af) | Established brands |
| `minimal` | Ultra-clean B&W | Black (#000000) | Minimalist brands |
| `vibrant` | Bold & energetic | Orange (#f59e0b) | Creative brands |
| `elegant` | Sophisticated | Gray (#6b7280) | Luxury products |
| `nature` | Eco-friendly | Green (#059669) | Organic/eco brands |
---
## Complete Preset Structure
Each preset includes:
```python
{
"colors": {
"primary": "#6366f1", # Main brand color
"secondary": "#8b5cf6", # Supporting color
"accent": "#ec4899", # Call-to-action color
"background": "#ffffff", # Page background
"text": "#1f2937", # Text color
"border": "#e5e7eb" # Border/divider color
},
"fonts": {
"heading": "Inter, sans-serif", # Headings (h1-h6)
"body": "Inter, sans-serif" # Body text
},
"layout": {
"style": "grid", # grid | list | masonry
"header": "fixed", # fixed | static | transparent
"product_card": "modern" # modern | classic | minimal
}
}
```
---
## Integration with Admin Panel
### Theme Editor UI Flow
1. **Preset Selector**
```javascript
// Fetch available presets
fetch('/api/v1/store/theme/presets')
.then(r => r.json())
.then(data => {
// Display preset cards with previews
data.presets.forEach(preset => {
showPresetCard(preset.name, preset.primary_color, preset.description)
})
})
```
2. **Apply Preset Button**
```javascript
function applyPreset(presetName) {
fetch('/api/v1/store/theme/preset', {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({preset_name: presetName})
})
.then(() => {
alert('Theme updated!')
location.reload() // Refresh to show new theme
})
}
```
3. **Custom Color Picker** (After applying preset)
```javascript
// User can then customize colors
function updateColors(colors) {
fetch('/api/v1/store/theme/colors', {
method: 'PUT',
body: JSON.stringify({colors})
})
}
```
---
## Testing Presets
```python
# Test script
from app.core.theme_presets import apply_preset, get_available_presets
from models.database.store_theme import StoreTheme
def test_all_presets():
"""Test applying all presets"""
presets = get_available_presets()
for preset_name in presets:
theme = StoreTheme(store_id=999) # Test store
apply_preset(theme, preset_name)
assert theme.theme_name == preset_name
assert theme.colors is not None
assert theme.font_family_heading is not None
assert theme.is_active == True
print(f"✅ {preset_name} preset OK")
test_all_presets()
```
---
## CSS Variables Generation
Your middleware already handles this via `StoreTheme.to_dict()`, which includes:
```python
"css_variables": {
"--color-primary": "#6366f1",
"--color-secondary": "#8b5cf6",
"--color-accent": "#ec4899",
"--color-background": "#ffffff",
"--color-text": "#1f2937",
"--color-border": "#e5e7eb",
"--font-heading": "Inter, sans-serif",
"--font-body": "Inter, sans-serif",
}
```
Use in templates:
```html
<style>
:root {
{% for key, value in theme.css_variables.items() %}
{{ key }}: {{ value }};
{% endfor %}
}
</style>
```
---
## Next Steps
1. ✅ Copy `theme_presets.py` to `app/core/theme_presets.py`
2. ✅ Create API endpoints for applying presets
3. ✅ Build theme selector UI in admin panel
4. ✅ Test all presets work correctly
5. ✅ Add custom color picker for fine-tuning
Perfect! Your presets are now complete and production-ready! 🎨