docs: add comprehensive CMS documentation
Add complete documentation for the Content Management System: Feature Documentation (docs/features/): - content-management-system.md - Complete CMS overview * Two-tier architecture explanation * Database schema and relationships * API reference for all endpoints * Usage workflows for admin/vendor/customer * Best practices and examples - cms-implementation-guide.md - Step-by-step implementation * Activation checklist * Code integration instructions * Testing procedures * Troubleshooting guide Quick Start Guide (docs/getting-started/): - cms-quick-start.md - Quick reference * Setup commands * Access URLs * Managing content (API, admin panel, vendor dashboard) * Two-tier system explained with examples * Common tasks and troubleshooting Updated Seeder Docs: - Add CMS to enhanced seeder coverage list - Add dedicated CMS section with table of pages - Document integration with db-setup workflow - Update best practices MkDocs Configuration: - Add "Features" section with CMS documentation - Add CMS Quick Start to "Getting Started" - Add CDN Fallback Strategy to "Frontend Development" - Complete navigation structure All documentation builds cleanly with no warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ I've created a comprehensive database seeder for your Wizamart platform that sig
|
|||||||
- ✓ Import jobs
|
- ✓ Import jobs
|
||||||
- ✓ Admin settings (platform configuration)
|
- ✓ Admin settings (platform configuration)
|
||||||
- ✓ Platform alerts (system monitoring)
|
- ✓ Platform alerts (system monitoring)
|
||||||
|
- ✓ **CMS Content Pages** (platform defaults: about, contact, FAQ, shipping, returns, privacy, terms)
|
||||||
|
|
||||||
## Files Created
|
## Files Created
|
||||||
|
|
||||||
@@ -352,12 +353,64 @@ source venv/bin/activate # Linux/Mac
|
|||||||
venv\Scripts\activate # Windows
|
venv\Scripts\activate # Windows
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## CMS Content Pages
|
||||||
|
|
||||||
|
The platform includes a comprehensive CMS (Content Management System) for managing static content pages.
|
||||||
|
|
||||||
|
### Creating Default CMS Pages
|
||||||
|
|
||||||
|
To create platform-level default content pages (About, Contact, FAQ, Shipping, Returns, Privacy, Terms):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make create-cms-defaults
|
||||||
|
# or
|
||||||
|
python scripts/create_default_content_pages.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates 7 platform default pages that all vendors inherit:
|
||||||
|
|
||||||
|
| Slug | Title | Show in Footer | Show in Header |
|
||||||
|
|------|-------|----------------|----------------|
|
||||||
|
| about | About Us | ✓ | ✓ |
|
||||||
|
| contact | Contact Us | ✓ | ✓ |
|
||||||
|
| faq | Frequently Asked Questions | ✓ | ✗ |
|
||||||
|
| shipping | Shipping Policy | ✓ | ✗ |
|
||||||
|
| returns | Return & Refund Policy | ✓ | ✗ |
|
||||||
|
| privacy | Privacy Policy | ✓ | ✗ |
|
||||||
|
| terms | Terms of Service | ✓ | ✗ |
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- **Platform Defaults**: Created with `vendor_id=NULL`, available to all vendors
|
||||||
|
- **Vendor Overrides**: Vendors can create custom versions with the same slug
|
||||||
|
- **Automatic Fallback**: System checks vendor override first, falls back to platform default
|
||||||
|
- **Navigation**: Pages marked with `show_in_footer` appear in shop footer automatically
|
||||||
|
- **Idempotent**: Script skips pages that already exist
|
||||||
|
|
||||||
|
**Access URLs:**
|
||||||
|
- `/about` - About Us page
|
||||||
|
- `/contact` - Contact page
|
||||||
|
- `/faq` - FAQ page
|
||||||
|
- `/shipping` - Shipping Policy
|
||||||
|
- `/returns` - Return Policy
|
||||||
|
- `/privacy` - Privacy Policy
|
||||||
|
- `/terms` - Terms of Service
|
||||||
|
|
||||||
|
### Integration with db-setup
|
||||||
|
|
||||||
|
The `make db-setup` command automatically includes CMS defaults:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make db-setup
|
||||||
|
# Runs: migrate-up → init-prod → create-cms-defaults → seed-demo
|
||||||
|
```
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
1. **Development**: Use `make seed` for full test data
|
1. **Development**: Use `make seed` for full test data
|
||||||
2. **Quick Testing**: Use `make seed-minimal` for fast setup
|
2. **Quick Testing**: Use `make seed-minimal` for fast setup
|
||||||
3. **Fresh Start**: Use `make seed-reset` when testing migrations
|
3. **Fresh Start**: Use `make seed-reset` when testing migrations
|
||||||
4. **Production**: Never run the seeder in production!
|
4. **CMS Pages**: Run `make create-cms-defaults` after migrations
|
||||||
|
5. **Production**: Never run the seeder in production!
|
||||||
|
|
||||||
## Security Notes
|
## Security Notes
|
||||||
|
|
||||||
|
|||||||
414
docs/features/cms-implementation-guide.md
Normal file
414
docs/features/cms-implementation-guide.md
Normal file
@@ -0,0 +1,414 @@
|
|||||||
|
# CMS Implementation Guide
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
This guide shows you how to implement the Content Management System for static pages.
|
||||||
|
|
||||||
|
## What Was Implemented
|
||||||
|
|
||||||
|
✅ **Database Model**: `models/database/content_page.py`
|
||||||
|
✅ **Service Layer**: `app/services/content_page_service.py`
|
||||||
|
✅ **Admin API**: `app/api/v1/admin/content_pages.py`
|
||||||
|
✅ **Vendor API**: `app/api/v1/vendor/content_pages.py`
|
||||||
|
✅ **Shop API**: `app/api/v1/shop/content_pages.py`
|
||||||
|
✅ **Documentation**: Full CMS documentation in `docs/features/content-management-system.md`
|
||||||
|
|
||||||
|
## Next Steps to Activate
|
||||||
|
|
||||||
|
### 1. Create Database Migration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create Alembic migration
|
||||||
|
alembic revision --autogenerate -m "Add content_pages table"
|
||||||
|
|
||||||
|
# Review the generated migration in alembic/versions/
|
||||||
|
|
||||||
|
# Run migration
|
||||||
|
alembic upgrade head
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Add Relationship to Vendor Model
|
||||||
|
|
||||||
|
Edit `models/database/vendor.py` and add this relationship:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Add this import
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
# Add this relationship to Vendor class
|
||||||
|
content_pages = relationship("ContentPage", back_populates="vendor", cascade="all, delete-orphan")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Register API Routers
|
||||||
|
|
||||||
|
Edit the appropriate router files to include the new endpoints:
|
||||||
|
|
||||||
|
**Admin Router** (`app/api/v1/admin/__init__.py`):
|
||||||
|
```python
|
||||||
|
from app.api.v1.admin import content_pages
|
||||||
|
|
||||||
|
api_router.include_router(
|
||||||
|
content_pages.router,
|
||||||
|
prefix="/content-pages",
|
||||||
|
tags=["admin-content-pages"]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Vendor Router** (`app/api/v1/vendor/__init__.py`):
|
||||||
|
```python
|
||||||
|
from app.api.v1.vendor import content_pages
|
||||||
|
|
||||||
|
api_router.include_router(
|
||||||
|
content_pages.router,
|
||||||
|
prefix="/{vendor_code}/content-pages",
|
||||||
|
tags=["vendor-content-pages"]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Shop Router** (`app/api/v1/shop/__init__.py` or create if doesn't exist):
|
||||||
|
```python
|
||||||
|
from app.api.v1.shop import content_pages
|
||||||
|
|
||||||
|
api_router.include_router(
|
||||||
|
content_pages.router,
|
||||||
|
prefix="/content-pages",
|
||||||
|
tags=["shop-content-pages"]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Update Shop Routes to Use CMS
|
||||||
|
|
||||||
|
Edit `app/routes/shop_pages.py` to add a generic content page handler:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from app.services.content_page_service import content_page_service
|
||||||
|
|
||||||
|
@router.get("/{slug}", response_class=HTMLResponse, include_in_schema=False)
|
||||||
|
async def generic_content_page(
|
||||||
|
slug: str,
|
||||||
|
request: Request,
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Generic content page handler.
|
||||||
|
Handles: /about, /faq, /contact, /shipping, /returns, /privacy, /terms, etc.
|
||||||
|
"""
|
||||||
|
vendor = getattr(request.state, 'vendor', None)
|
||||||
|
vendor_id = vendor.id if vendor else None
|
||||||
|
|
||||||
|
page = content_page_service.get_page_for_vendor(
|
||||||
|
db,
|
||||||
|
slug=slug,
|
||||||
|
vendor_id=vendor_id,
|
||||||
|
include_unpublished=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if not page:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Page not found: {slug}")
|
||||||
|
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"shop/content-page.html",
|
||||||
|
get_shop_context(request, page=page)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Create Generic Content Page Template
|
||||||
|
|
||||||
|
Create `app/templates/shop/content-page.html`:
|
||||||
|
|
||||||
|
```jinja2
|
||||||
|
{# app/templates/shop/content-page.html #}
|
||||||
|
{% extends "shop/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ page.title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block meta_description %}
|
||||||
|
{{ page.meta_description or page.title }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
|
|
||||||
|
{# Breadcrumbs #}
|
||||||
|
<nav class="mb-6 text-sm">
|
||||||
|
<a href="{{ base_url }}" class="text-primary hover:underline">Home</a>
|
||||||
|
<span class="mx-2 text-gray-400">/</span>
|
||||||
|
<span class="text-gray-600 dark:text-gray-300">{{ page.title }}</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{# Page Title #}
|
||||||
|
<h1 class="text-4xl font-bold text-gray-900 dark:text-gray-100 mb-8">
|
||||||
|
{{ page.title }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{# Content #}
|
||||||
|
<div class="prose prose-lg dark:prose-invert max-w-none">
|
||||||
|
{{ page.content | safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Last updated #}
|
||||||
|
{% if page.updated_at %}
|
||||||
|
<div class="mt-12 pt-6 border-t border-gray-200 dark:border-gray-700 text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
Last updated: {{ page.updated_at.strftime('%B %d, %Y') }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Update Footer to Load Navigation Dynamically
|
||||||
|
|
||||||
|
Edit `app/templates/shop/base.html` to load navigation from database.
|
||||||
|
|
||||||
|
First, update the context helper to include footer pages:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/routes/shop_pages.py
|
||||||
|
|
||||||
|
def get_shop_context(request: Request, **extra_context) -> dict:
|
||||||
|
# ... existing code ...
|
||||||
|
|
||||||
|
# Load footer navigation pages
|
||||||
|
db = next(get_db())
|
||||||
|
try:
|
||||||
|
footer_pages = content_page_service.list_pages_for_vendor(
|
||||||
|
db,
|
||||||
|
vendor_id=vendor.id if vendor else None,
|
||||||
|
include_unpublished=False,
|
||||||
|
footer_only=True
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"request": request,
|
||||||
|
"vendor": vendor,
|
||||||
|
"theme": theme,
|
||||||
|
"clean_path": clean_path,
|
||||||
|
"access_method": access_method,
|
||||||
|
"base_url": base_url,
|
||||||
|
"footer_pages": footer_pages, # Add this
|
||||||
|
**extra_context
|
||||||
|
}
|
||||||
|
|
||||||
|
return context
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update the footer template:
|
||||||
|
|
||||||
|
```jinja2
|
||||||
|
{# app/templates/shop/base.html - Footer section #}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="font-semibold mb-4">Quick Links</h4>
|
||||||
|
<ul class="space-y-2">
|
||||||
|
{% for page in footer_pages %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ base_url }}{{ page.slug }}"
|
||||||
|
class="text-gray-600 hover:text-primary dark:text-gray-400">
|
||||||
|
{{ page.title }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Create Default Platform Pages (Script)
|
||||||
|
|
||||||
|
Create `scripts/create_default_content_pages.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Create default platform content pages."""
|
||||||
|
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from app.core.database import SessionLocal
|
||||||
|
from app.services.content_page_service import content_page_service
|
||||||
|
|
||||||
|
def create_defaults():
|
||||||
|
db: Session = SessionLocal()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# About Us
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="about",
|
||||||
|
title="About Us",
|
||||||
|
content="""
|
||||||
|
<h2>Welcome to Our Marketplace</h2>
|
||||||
|
<p>We connect quality vendors with customers worldwide.</p>
|
||||||
|
<p>Our mission is to provide a seamless shopping experience...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Shipping Information
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="shipping",
|
||||||
|
title="Shipping Information",
|
||||||
|
content="""
|
||||||
|
<h2>Shipping Policy</h2>
|
||||||
|
<p>We offer fast and reliable shipping...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=2
|
||||||
|
)
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="returns",
|
||||||
|
title="Returns & Refunds",
|
||||||
|
content="""
|
||||||
|
<h2>Return Policy</h2>
|
||||||
|
<p>30-day return policy on all items...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=3
|
||||||
|
)
|
||||||
|
|
||||||
|
# Privacy Policy
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="privacy",
|
||||||
|
title="Privacy Policy",
|
||||||
|
content="""
|
||||||
|
<h2>Privacy Policy</h2>
|
||||||
|
<p>Your privacy is important to us...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=4
|
||||||
|
)
|
||||||
|
|
||||||
|
# Terms of Service
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="terms",
|
||||||
|
title="Terms of Service",
|
||||||
|
content="""
|
||||||
|
<h2>Terms of Service</h2>
|
||||||
|
<p>By using our platform, you agree to...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=5
|
||||||
|
)
|
||||||
|
|
||||||
|
# Contact
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="contact",
|
||||||
|
title="Contact Us",
|
||||||
|
content="""
|
||||||
|
<h2>Get in Touch</h2>
|
||||||
|
<p>Have questions? We'd love to hear from you!</p>
|
||||||
|
<p>Email: support@example.com</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=6
|
||||||
|
)
|
||||||
|
|
||||||
|
# FAQ
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug="faq",
|
||||||
|
title="Frequently Asked Questions",
|
||||||
|
content="""
|
||||||
|
<h2>FAQ</h2>
|
||||||
|
<h3>How do I place an order?</h3>
|
||||||
|
<p>Simply browse our products...</p>
|
||||||
|
""",
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True,
|
||||||
|
display_order=7
|
||||||
|
)
|
||||||
|
|
||||||
|
print("✅ Created default content pages successfully")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
db.rollback()
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
create_defaults()
|
||||||
|
```
|
||||||
|
|
||||||
|
Run it:
|
||||||
|
```bash
|
||||||
|
python scripts/create_default_content_pages.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### 1. Test Platform Defaults
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create platform default
|
||||||
|
curl -X POST http://localhost:8000/api/v1/admin/content-pages/platform \
|
||||||
|
-H "Authorization: Bearer <admin_token>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Our Marketplace",
|
||||||
|
"content": "<h1>About</h1><p>Platform default content</p>",
|
||||||
|
"is_published": true,
|
||||||
|
"show_in_footer": true
|
||||||
|
}'
|
||||||
|
|
||||||
|
# View in shop
|
||||||
|
curl http://localhost:8000/vendor/wizamart/about
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Test Vendor Override
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create vendor override
|
||||||
|
curl -X POST http://localhost:8000/api/v1/vendor/wizamart/content-pages/ \
|
||||||
|
-H "Authorization: Bearer <vendor_token>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Wizamart",
|
||||||
|
"content": "<h1>About Wizamart</h1><p>Custom vendor content</p>",
|
||||||
|
"is_published": true
|
||||||
|
}'
|
||||||
|
|
||||||
|
# View in shop (should show vendor content)
|
||||||
|
curl http://localhost:8000/vendor/wizamart/about
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Test Fallback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Delete vendor override
|
||||||
|
curl -X DELETE http://localhost:8000/api/v1/vendor/wizamart/content-pages/{id} \
|
||||||
|
-H "Authorization: Bearer <vendor_token>"
|
||||||
|
|
||||||
|
# View in shop (should fall back to platform default)
|
||||||
|
curl http://localhost:8000/vendor/wizamart/about
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
You now have a complete CMS system that allows:
|
||||||
|
|
||||||
|
1. **Platform admins** to create default content for all vendors
|
||||||
|
2. **Vendors** to override specific pages with custom content
|
||||||
|
3. **Automatic fallback** to platform defaults when vendor hasn't customized
|
||||||
|
4. **Dynamic navigation** loading from database
|
||||||
|
5. **SEO optimization** with meta tags
|
||||||
|
6. **Draft/Published workflow** for content management
|
||||||
|
|
||||||
|
All pages are accessible via their slug: `/about`, `/faq`, `/contact`, etc. with proper vendor context and routing support!
|
||||||
562
docs/features/content-management-system.md
Normal file
562
docs/features/content-management-system.md
Normal file
@@ -0,0 +1,562 @@
|
|||||||
|
# Content Management System (CMS)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Content Management System allows platform administrators and vendors to manage static content pages like About, FAQ, Contact, Shipping, Returns, Privacy Policy, Terms of Service, etc.
|
||||||
|
|
||||||
|
**Key Features:**
|
||||||
|
- ✅ Platform-level default content
|
||||||
|
- ✅ Vendor-specific overrides
|
||||||
|
- ✅ Fallback system (vendor → platform default)
|
||||||
|
- ✅ Rich text content (HTML/Markdown)
|
||||||
|
- ✅ SEO metadata
|
||||||
|
- ✅ Published/Draft status
|
||||||
|
- ✅ Navigation management (footer/header)
|
||||||
|
- ✅ Display order control
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Two-Tier Content System
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ CONTENT LOOKUP FLOW │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
Request: /about
|
||||||
|
|
||||||
|
1. Check for vendor-specific override
|
||||||
|
↓
|
||||||
|
SELECT * FROM content_pages
|
||||||
|
WHERE vendor_id = 123 AND slug = 'about' AND is_published = true
|
||||||
|
↓
|
||||||
|
Found? ✅ Return vendor content
|
||||||
|
❌ Continue to step 2
|
||||||
|
|
||||||
|
2. Check for platform default
|
||||||
|
↓
|
||||||
|
SELECT * FROM content_pages
|
||||||
|
WHERE vendor_id IS NULL AND slug = 'about' AND is_published = true
|
||||||
|
↓
|
||||||
|
Found? ✅ Return platform content
|
||||||
|
❌ Return 404 or default template
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Schema
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE content_pages (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
|
||||||
|
-- Vendor association (NULL = platform default)
|
||||||
|
vendor_id INTEGER REFERENCES vendors(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
-- Page identification
|
||||||
|
slug VARCHAR(100) NOT NULL, -- about, faq, contact, shipping, returns
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
|
||||||
|
-- Content
|
||||||
|
content TEXT NOT NULL, -- HTML or Markdown
|
||||||
|
content_format VARCHAR(20) DEFAULT 'html', -- html, markdown
|
||||||
|
|
||||||
|
-- SEO
|
||||||
|
meta_description VARCHAR(300),
|
||||||
|
meta_keywords VARCHAR(300),
|
||||||
|
|
||||||
|
-- Publishing
|
||||||
|
is_published BOOLEAN DEFAULT FALSE NOT NULL,
|
||||||
|
published_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
|
||||||
|
-- Navigation
|
||||||
|
display_order INTEGER DEFAULT 0,
|
||||||
|
show_in_footer BOOLEAN DEFAULT TRUE,
|
||||||
|
show_in_header BOOLEAN DEFAULT FALSE,
|
||||||
|
|
||||||
|
-- Timestamps
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
|
||||||
|
|
||||||
|
-- Author tracking
|
||||||
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
updated_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
|
||||||
|
-- Constraints
|
||||||
|
CONSTRAINT uq_vendor_slug UNIQUE (vendor_id, slug)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_vendor_published ON content_pages (vendor_id, is_published);
|
||||||
|
CREATE INDEX idx_slug_published ON content_pages (slug, is_published);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Platform Administrator Workflow
|
||||||
|
|
||||||
|
**1. Create Platform Default Pages**
|
||||||
|
|
||||||
|
Platform admins create default content that all vendors inherit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
POST /api/v1/admin/content-pages/platform
|
||||||
|
{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Us",
|
||||||
|
"content": "<h1>About Us</h1><p>We are a marketplace...</p>",
|
||||||
|
"content_format": "html",
|
||||||
|
"meta_description": "Learn more about our marketplace",
|
||||||
|
"is_published": true,
|
||||||
|
"show_in_footer": true,
|
||||||
|
"display_order": 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common Platform Defaults:**
|
||||||
|
- `about` - About Us
|
||||||
|
- `contact` - Contact Us
|
||||||
|
- `faq` - Frequently Asked Questions
|
||||||
|
- `shipping` - Shipping Information
|
||||||
|
- `returns` - Return Policy
|
||||||
|
- `privacy` - Privacy Policy
|
||||||
|
- `terms` - Terms of Service
|
||||||
|
- `help` - Help Center
|
||||||
|
|
||||||
|
**2. View All Content Pages**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET /api/v1/admin/content-pages/
|
||||||
|
GET /api/v1/admin/content-pages/?vendor_id=123 # Filter by vendor
|
||||||
|
GET /api/v1/admin/content-pages/platform # Only platform defaults
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Update Platform Default**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PUT /api/v1/admin/content-pages/1
|
||||||
|
{
|
||||||
|
"title": "Updated About Us",
|
||||||
|
"content": "<h1>About Our Platform</h1>...",
|
||||||
|
"is_published": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vendor Workflow
|
||||||
|
|
||||||
|
**1. View Available Pages**
|
||||||
|
|
||||||
|
Vendors see their overrides + platform defaults:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET /api/v1/vendor/{code}/content-pages/
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Wizamart", // Vendor override
|
||||||
|
"is_vendor_override": true,
|
||||||
|
"is_platform_default": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"slug": "shipping",
|
||||||
|
"title": "Shipping Information", // Platform default
|
||||||
|
"is_vendor_override": false,
|
||||||
|
"is_platform_default": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Create Vendor Override**
|
||||||
|
|
||||||
|
Vendor creates custom "About" page:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
POST /api/v1/vendor/{code}/content-pages/
|
||||||
|
{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Wizamart",
|
||||||
|
"content": "<h1>About Wizamart</h1><p>We specialize in...</p>",
|
||||||
|
"is_published": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This overrides the platform default for this vendor only.
|
||||||
|
|
||||||
|
**3. View Only Vendor Overrides**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET /api/v1/vendor/{code}/content-pages/overrides
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows what the vendor has customized (excludes platform defaults).
|
||||||
|
|
||||||
|
**4. Delete Override (Revert to Platform Default)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DELETE /api/v1/vendor/{code}/content-pages/15
|
||||||
|
```
|
||||||
|
|
||||||
|
After deletion, platform default will be shown again.
|
||||||
|
|
||||||
|
### Shop Frontend (Public)
|
||||||
|
|
||||||
|
**1. Get Page Content**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET /api/v1/shop/content-pages/about
|
||||||
|
```
|
||||||
|
|
||||||
|
Automatically uses vendor context from middleware:
|
||||||
|
- Returns vendor override if exists
|
||||||
|
- Falls back to platform default
|
||||||
|
- Returns 404 if neither exists
|
||||||
|
|
||||||
|
**2. Get Navigation Links**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GET /api/v1/shop/content-pages/navigation
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all published pages for footer/header navigation.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
├── models/database/
|
||||||
|
│ └── content_page.py ← Database model
|
||||||
|
│
|
||||||
|
├── services/
|
||||||
|
│ └── content_page_service.py ← Business logic
|
||||||
|
│
|
||||||
|
├── api/v1/
|
||||||
|
│ ├── admin/
|
||||||
|
│ │ └── content_pages.py ← Admin API endpoints
|
||||||
|
│ ├── vendor/
|
||||||
|
│ │ └── content_pages.py ← Vendor API endpoints
|
||||||
|
│ └── shop/
|
||||||
|
│ └── content_pages.py ← Public API endpoints
|
||||||
|
│
|
||||||
|
└── templates/shop/
|
||||||
|
├── about.html ← Content page template
|
||||||
|
├── faq.html
|
||||||
|
├── contact.html
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Template Integration
|
||||||
|
|
||||||
|
### Generic Content Page Template
|
||||||
|
|
||||||
|
Create a reusable template for all content pages:
|
||||||
|
|
||||||
|
```jinja2
|
||||||
|
{# app/templates/shop/content-page.html #}
|
||||||
|
{% extends "shop/base.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ page.title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block meta_description %}
|
||||||
|
{{ page.meta_description or page.title }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
|
|
||||||
|
{# Breadcrumbs #}
|
||||||
|
<nav class="mb-6">
|
||||||
|
<a href="{{ base_url }}" class="text-primary hover:underline">Home</a>
|
||||||
|
<span class="mx-2">/</span>
|
||||||
|
<span class="text-gray-600">{{ page.title }}</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{# Page Title #}
|
||||||
|
<h1 class="text-4xl font-bold text-gray-900 dark:text-gray-100 mb-8">
|
||||||
|
{{ page.title }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{# Content #}
|
||||||
|
<div class="prose dark:prose-invert max-w-none">
|
||||||
|
{% if page.content_format == 'markdown' %}
|
||||||
|
{{ page.content | markdown }}
|
||||||
|
{% else %}
|
||||||
|
{{ page.content | safe }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Last updated #}
|
||||||
|
{% if page.updated_at %}
|
||||||
|
<div class="mt-12 pt-6 border-t text-sm text-gray-500">
|
||||||
|
Last updated: {{ page.updated_at }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Route Handler
|
||||||
|
|
||||||
|
```python
|
||||||
|
# app/routes/shop_pages.py
|
||||||
|
|
||||||
|
from app.services.content_page_service import content_page_service
|
||||||
|
|
||||||
|
@router.get("/{slug}", response_class=HTMLResponse)
|
||||||
|
async def content_page(
|
||||||
|
slug: str,
|
||||||
|
request: Request,
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Generic content page handler.
|
||||||
|
|
||||||
|
Loads content from database with vendor override support.
|
||||||
|
"""
|
||||||
|
vendor = getattr(request.state, 'vendor', None)
|
||||||
|
vendor_id = vendor.id if vendor else None
|
||||||
|
|
||||||
|
page = content_page_service.get_page_for_vendor(
|
||||||
|
db,
|
||||||
|
slug=slug,
|
||||||
|
vendor_id=vendor_id,
|
||||||
|
include_unpublished=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if not page:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Page not found: {slug}")
|
||||||
|
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"shop/content-page.html",
|
||||||
|
get_shop_context(request, page=page)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dynamic Footer Navigation
|
||||||
|
|
||||||
|
Update footer to load links from database:
|
||||||
|
|
||||||
|
```jinja2
|
||||||
|
{# app/templates/shop/base.html #}
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="grid grid-cols-3">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>Quick Links</h4>
|
||||||
|
<ul>
|
||||||
|
{% for page in footer_pages %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ base_url }}{{ page.slug }}">
|
||||||
|
{{ page.title }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Content Formatting
|
||||||
|
|
||||||
|
**HTML Content:**
|
||||||
|
```html
|
||||||
|
<h1>About Us</h1>
|
||||||
|
<p>We are a <strong>leading marketplace</strong> for...</p>
|
||||||
|
<ul>
|
||||||
|
<li>Quality products</li>
|
||||||
|
<li>Fast shipping</li>
|
||||||
|
<li>Great support</li>
|
||||||
|
</ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Markdown Content:**
|
||||||
|
```markdown
|
||||||
|
# About Us
|
||||||
|
|
||||||
|
We are a **leading marketplace** for...
|
||||||
|
|
||||||
|
- Quality products
|
||||||
|
- Fast shipping
|
||||||
|
- Great support
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. SEO Optimization
|
||||||
|
|
||||||
|
Always provide meta descriptions:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"meta_description": "Learn about our marketplace, mission, and values. We connect vendors with customers worldwide.",
|
||||||
|
"meta_keywords": "about us, marketplace, e-commerce, mission"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Draft → Published Workflow
|
||||||
|
|
||||||
|
1. Create page with `is_published: false`
|
||||||
|
2. Preview using `include_unpublished=true` parameter
|
||||||
|
3. Review and edit
|
||||||
|
4. Publish with `is_published: true`
|
||||||
|
|
||||||
|
### 4. Navigation Management
|
||||||
|
|
||||||
|
Use `display_order` to control link ordering:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Platform defaults
|
||||||
|
"about": display_order=1
|
||||||
|
"shipping": display_order=2
|
||||||
|
"returns": display_order=3
|
||||||
|
"privacy": display_order=4
|
||||||
|
"terms": display_order=5
|
||||||
|
|
||||||
|
# Result in footer:
|
||||||
|
About | Shipping | Returns | Privacy | Terms
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Content Reversion
|
||||||
|
|
||||||
|
To revert vendor override back to platform default:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vendor deletes their custom page
|
||||||
|
DELETE /api/v1/vendor/{code}/content-pages/15
|
||||||
|
|
||||||
|
# Platform default will now be shown automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Page Slugs
|
||||||
|
|
||||||
|
Standard slugs to implement:
|
||||||
|
|
||||||
|
| Slug | Title | Description | Show in Footer |
|
||||||
|
|------|-------|-------------|----------------|
|
||||||
|
| `about` | About Us | Company/vendor information | Yes |
|
||||||
|
| `contact` | Contact Us | Contact information and form | Yes |
|
||||||
|
| `faq` | FAQ | Frequently asked questions | Yes |
|
||||||
|
| `shipping` | Shipping Info | Shipping policies and rates | Yes |
|
||||||
|
| `returns` | Returns | Return and refund policy | Yes |
|
||||||
|
| `privacy` | Privacy Policy | Privacy and data protection | Yes |
|
||||||
|
| `terms` | Terms of Service | Terms and conditions | Yes |
|
||||||
|
| `help` | Help Center | Support resources | Yes |
|
||||||
|
| `size-guide` | Size Guide | Product sizing information | No |
|
||||||
|
| `careers` | Careers | Job opportunities | No |
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
1. **HTML Sanitization**: If using HTML format, sanitize user input to prevent XSS
|
||||||
|
2. **Authorization**: Vendors can only edit their own pages
|
||||||
|
3. **Published Status**: Only published pages visible to public
|
||||||
|
4. **Vendor Isolation**: Vendors cannot see/edit other vendor's content
|
||||||
|
|
||||||
|
## Migration Strategy
|
||||||
|
|
||||||
|
### Initial Setup
|
||||||
|
|
||||||
|
1. **Create Platform Defaults**:
|
||||||
|
```bash
|
||||||
|
python scripts/create_default_content_pages.py
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Migrate Existing Static Templates**:
|
||||||
|
- Convert existing HTML templates to database content
|
||||||
|
- Preserve existing URLs and SEO
|
||||||
|
|
||||||
|
3. **Update Routes**:
|
||||||
|
- Add generic content page route handler
|
||||||
|
- Remove individual route handlers for each page
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
Possible improvements:
|
||||||
|
|
||||||
|
- **Version History**: Track content changes over time
|
||||||
|
- **Rich Text Editor**: WYSIWYG editor in admin/vendor panel
|
||||||
|
- **Image Management**: Upload and insert images
|
||||||
|
- **Templates**: Pre-built page templates for common pages
|
||||||
|
- **Localization**: Multi-language content support
|
||||||
|
- **Scheduled Publishing**: Publish pages at specific times
|
||||||
|
- **Content Approval**: Admin review before vendor pages go live
|
||||||
|
|
||||||
|
## API Reference Summary
|
||||||
|
|
||||||
|
### Admin Endpoints
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/v1/admin/content-pages/ # List all pages
|
||||||
|
GET /api/v1/admin/content-pages/platform # List platform defaults
|
||||||
|
POST /api/v1/admin/content-pages/platform # Create platform default
|
||||||
|
GET /api/v1/admin/content-pages/{id} # Get specific page
|
||||||
|
PUT /api/v1/admin/content-pages/{id} # Update page
|
||||||
|
DELETE /api/v1/admin/content-pages/{id} # Delete page
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vendor Endpoints
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/v1/vendor/{code}/content-pages/ # List all (vendor + platform)
|
||||||
|
GET /api/v1/vendor/{code}/content-pages/overrides # List vendor overrides only
|
||||||
|
GET /api/v1/vendor/{code}/content-pages/{slug} # Get specific page
|
||||||
|
POST /api/v1/vendor/{code}/content-pages/ # Create vendor override
|
||||||
|
PUT /api/v1/vendor/{code}/content-pages/{id} # Update vendor page
|
||||||
|
DELETE /api/v1/vendor/{code}/content-pages/{id} # Delete vendor page
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shop (Public) Endpoints
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/v1/shop/content-pages/navigation # Get navigation links
|
||||||
|
GET /api/v1/shop/content-pages/{slug} # Get page content
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example: Complete Workflow
|
||||||
|
|
||||||
|
**1. Platform Admin Creates Defaults:**
|
||||||
|
```bash
|
||||||
|
# Create "About" page
|
||||||
|
curl -X POST /api/v1/admin/content-pages/platform \
|
||||||
|
-H "Authorization: Bearer <admin_token>" \
|
||||||
|
-d '{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Our Marketplace",
|
||||||
|
"content": "<h1>About</h1><p>Default content...</p>",
|
||||||
|
"is_published": true
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. All Vendors See Platform Default:**
|
||||||
|
- Vendor A visits: `vendor-a.com/about` → Shows platform default
|
||||||
|
- Vendor B visits: `vendor-b.com/about` → Shows platform default
|
||||||
|
|
||||||
|
**3. Vendor A Creates Override:**
|
||||||
|
```bash
|
||||||
|
curl -X POST /api/v1/vendor/vendor-a/content-pages/ \
|
||||||
|
-H "Authorization: Bearer <vendor_token>" \
|
||||||
|
-d '{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Vendor A",
|
||||||
|
"content": "<h1>About Vendor A</h1><p>Custom content...</p>",
|
||||||
|
"is_published": true
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Now:**
|
||||||
|
- Vendor A visits: `vendor-a.com/about` → Shows Vendor A custom content
|
||||||
|
- Vendor B visits: `vendor-b.com/about` → Still shows platform default
|
||||||
|
|
||||||
|
**5. Vendor A Reverts to Default:**
|
||||||
|
```bash
|
||||||
|
curl -X DELETE /api/v1/vendor/vendor-a/content-pages/15 \
|
||||||
|
-H "Authorization: Bearer <vendor_token>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**6. Result:**
|
||||||
|
- Vendor A visits: `vendor-a.com/about` → Shows platform default again
|
||||||
216
docs/getting-started/cms-quick-start.md
Normal file
216
docs/getting-started/cms-quick-start.md
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
# CMS Quick Start Guide
|
||||||
|
|
||||||
|
A quick reference for setting up and using the Content Management System.
|
||||||
|
|
||||||
|
## What is the CMS?
|
||||||
|
|
||||||
|
The CMS allows you to manage static content pages (About, Contact, FAQ, etc.) with:
|
||||||
|
- **Platform defaults** - Base content for all vendors
|
||||||
|
- **Vendor overrides** - Custom content per vendor
|
||||||
|
- **Automatic fallback** - Vendors inherit platform defaults unless overridden
|
||||||
|
|
||||||
|
## Quick Setup
|
||||||
|
|
||||||
|
### 1. Create Default Content Pages
|
||||||
|
|
||||||
|
After running migrations, create the default CMS pages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make create-cms-defaults
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates 7 platform default pages:
|
||||||
|
- About Us (`/about`)
|
||||||
|
- Contact Us (`/contact`)
|
||||||
|
- FAQ (`/faq`)
|
||||||
|
- Shipping Policy (`/shipping`)
|
||||||
|
- Return & Refund Policy (`/returns`)
|
||||||
|
- Privacy Policy (`/privacy`)
|
||||||
|
- Terms of Service (`/terms`)
|
||||||
|
|
||||||
|
### 2. Full Database Setup
|
||||||
|
|
||||||
|
For a complete setup including CMS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make db-setup
|
||||||
|
# Runs: migrations → admin user → CMS pages → demo data
|
||||||
|
```
|
||||||
|
|
||||||
|
## Accessing Pages
|
||||||
|
|
||||||
|
All CMS pages are accessible on your shop frontend:
|
||||||
|
|
||||||
|
```
|
||||||
|
# For domain/subdomain access
|
||||||
|
https://wizamart.shop/about
|
||||||
|
https://fashionhub.store/contact
|
||||||
|
|
||||||
|
# For path-based access
|
||||||
|
http://localhost:8000/vendor/wizamart/faq
|
||||||
|
http://localhost:8000/vendors/fashionhub/shipping
|
||||||
|
```
|
||||||
|
|
||||||
|
## Managing Content
|
||||||
|
|
||||||
|
### Via Admin Panel
|
||||||
|
|
||||||
|
1. Log in to admin panel: `/admin/login`
|
||||||
|
2. Navigate to **Content Pages** section
|
||||||
|
3. Create/edit platform defaults (visible to all vendors)
|
||||||
|
|
||||||
|
### Via Vendor Dashboard
|
||||||
|
|
||||||
|
1. Log in to vendor dashboard: `/vendor/{code}/login`
|
||||||
|
2. Navigate to **Content Pages** section
|
||||||
|
3. View platform defaults
|
||||||
|
4. Create vendor-specific overrides
|
||||||
|
|
||||||
|
### Via API
|
||||||
|
|
||||||
|
**Admin - Create Platform Default:**
|
||||||
|
```bash
|
||||||
|
POST /api/v1/admin/content-pages/platform
|
||||||
|
{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Us",
|
||||||
|
"content": "<p>...</p>",
|
||||||
|
"is_published": true,
|
||||||
|
"show_in_footer": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Vendor - Create Override:**
|
||||||
|
```bash
|
||||||
|
POST /api/v1/vendor/{vendor_code}/content-pages
|
||||||
|
{
|
||||||
|
"slug": "about",
|
||||||
|
"title": "About Our Store",
|
||||||
|
"content": "<p>Custom content...</p>",
|
||||||
|
"is_published": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Public - Retrieve Page:**
|
||||||
|
```bash
|
||||||
|
GET /api/v1/shop/content-pages/{slug}
|
||||||
|
```
|
||||||
|
|
||||||
|
## How the Two-Tier System Works
|
||||||
|
|
||||||
|
### Lookup Priority
|
||||||
|
|
||||||
|
When a customer visits `/about`:
|
||||||
|
|
||||||
|
1. **Check vendor override** - Does this vendor have a custom "about" page?
|
||||||
|
2. **Fallback to platform** - If not, use the platform default "about" page
|
||||||
|
3. **404 if neither** - Return 404 if no page exists
|
||||||
|
|
||||||
|
### Example Scenario
|
||||||
|
|
||||||
|
**Platform Default:**
|
||||||
|
- Slug: `about`
|
||||||
|
- Title: "About Our Platform"
|
||||||
|
- Content: Generic platform description
|
||||||
|
|
||||||
|
**WizaMart Override:**
|
||||||
|
- Slug: `about`
|
||||||
|
- Title: "About WizaMart"
|
||||||
|
- Content: WizaMart-specific content
|
||||||
|
|
||||||
|
**Result:**
|
||||||
|
- `wizamart.shop/about` → Shows WizaMart custom version
|
||||||
|
- `fashionhub.store/about` → Shows platform default (no override)
|
||||||
|
|
||||||
|
## Footer Navigation
|
||||||
|
|
||||||
|
Pages marked with `show_in_footer: true` automatically appear in the shop footer:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Footer automatically loads from database -->
|
||||||
|
<footer>
|
||||||
|
<div>Quick Links</div>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/products">Products</a></li>
|
||||||
|
<li><a href="/about">About Us</a></li> <!-- From CMS -->
|
||||||
|
<li><a href="/contact">Contact</a></li> <!-- From CMS -->
|
||||||
|
</ul>
|
||||||
|
</footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Add a New Default Page
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -c "
|
||||||
|
from app.core.database import SessionLocal
|
||||||
|
from app.services.content_page_service import content_page_service
|
||||||
|
|
||||||
|
db = SessionLocal()
|
||||||
|
content_page_service.create_page(
|
||||||
|
db,
|
||||||
|
slug='careers',
|
||||||
|
title='Careers',
|
||||||
|
content='<h1>Join Our Team</h1>...',
|
||||||
|
is_published=True,
|
||||||
|
show_in_footer=True
|
||||||
|
)
|
||||||
|
db.close()
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create Vendor Override
|
||||||
|
|
||||||
|
Via vendor API or dashboard - vendors can override any platform default by creating a page with the same slug.
|
||||||
|
|
||||||
|
### Update Platform Default
|
||||||
|
|
||||||
|
Via admin panel or API - updates affect all vendors who haven't created an override.
|
||||||
|
|
||||||
|
## Re-running the Script
|
||||||
|
|
||||||
|
The script is **idempotent** - safe to run multiple times:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make create-cms-defaults
|
||||||
|
# Output: "Skipped: About Us (/about) - already exists"
|
||||||
|
```
|
||||||
|
|
||||||
|
Existing pages are never overwritten.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
For complete CMS documentation, see:
|
||||||
|
- [CMS Feature Documentation](../features/content-management-system.md)
|
||||||
|
- [CMS Implementation Guide](../features/cms-implementation-guide.md)
|
||||||
|
- [Database Seeder Guide](../development/database-seeder/DATABASE_SEEDER_DOCUMENTATION.md)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Pages not showing in footer
|
||||||
|
|
||||||
|
Check `show_in_footer` flag:
|
||||||
|
```sql
|
||||||
|
SELECT slug, title, show_in_footer FROM content_pages WHERE vendor_id IS NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vendor override not working
|
||||||
|
|
||||||
|
Verify slug matches exactly:
|
||||||
|
```sql
|
||||||
|
SELECT vendor_id, slug, title FROM content_pages WHERE slug = 'about';
|
||||||
|
```
|
||||||
|
|
||||||
|
### 404 on content pages
|
||||||
|
|
||||||
|
1. Check page is published: `is_published = true`
|
||||||
|
2. Verify migration was applied: `make migrate-status`
|
||||||
|
3. Run CMS defaults: `make create-cms-defaults`
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- Customize default content via admin panel
|
||||||
|
- Create vendor-specific overrides
|
||||||
|
- Add new custom pages as needed
|
||||||
|
- Update footer navigation preferences
|
||||||
10
mkdocs.yml
10
mkdocs.yml
@@ -20,6 +20,7 @@ nav:
|
|||||||
- Overview: getting-started/database-setup.md
|
- Overview: getting-started/database-setup.md
|
||||||
- Complete Setup Guide: getting-started/DATABASE_SETUP_GUIDE.md
|
- Complete Setup Guide: getting-started/DATABASE_SETUP_GUIDE.md
|
||||||
- Quick Reference: getting-started/DATABASE_QUICK_REFERENCE.md
|
- Quick Reference: getting-started/DATABASE_QUICK_REFERENCE.md
|
||||||
|
- CMS Quick Start: getting-started/cms-quick-start.md
|
||||||
- Configuration: getting-started/configuration.md
|
- Configuration: getting-started/configuration.md
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
@@ -70,6 +71,7 @@ nav:
|
|||||||
# ============================================
|
# ============================================
|
||||||
- Frontend Development:
|
- Frontend Development:
|
||||||
- Overview: frontend/overview.md
|
- Overview: frontend/overview.md
|
||||||
|
- CDN Fallback Strategy: frontend/cdn-fallback-strategy.md
|
||||||
- Shared Components:
|
- Shared Components:
|
||||||
- UI Components: frontend/shared/ui-components.md
|
- UI Components: frontend/shared/ui-components.md
|
||||||
- UI Components Quick Reference: frontend/shared/ui-components-quick-reference.md
|
- UI Components Quick Reference: frontend/shared/ui-components-quick-reference.md
|
||||||
@@ -130,6 +132,14 @@ nav:
|
|||||||
- Environment Variables: deployment/environment.md
|
- Environment Variables: deployment/environment.md
|
||||||
- Stripe Integration: deployment/stripe-integration.md
|
- Stripe Integration: deployment/stripe-integration.md
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# FEATURES
|
||||||
|
# ============================================
|
||||||
|
- Features:
|
||||||
|
- Content Management System:
|
||||||
|
- Overview: features/content-management-system.md
|
||||||
|
- Implementation Guide: features/cms-implementation-guide.md
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# USER GUIDES
|
# USER GUIDES
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|||||||
Reference in New Issue
Block a user