# 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` ✅ **Store API**: `app/api/v1/store/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 Store Model Edit `models/database/store.py` and add this relationship: ```python # Add this import from sqlalchemy.orm import relationship # Add this relationship to Store class content_pages = relationship("ContentPage", back_populates="store", 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"] ) ``` **Store Router** (`app/api/v1/store/__init__.py`): ```python from app.api.v1.store import content_pages api_router.include_router( content_pages.router, prefix="/{store_code}/content-pages", tags=["store-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. """ store = getattr(request.state, 'store', None) store_id = store.id if store else None page = content_page_service.get_page_for_store( db, slug=slug, store_id=store_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 %}
{# Breadcrumbs #} {# Page Title #}

{{ page.title }}

{# Content #}
{{ page.content | safe }}
{# Last updated #} {% if page.updated_at %}
Last updated: {{ page.updated_at.strftime('%B %d, %Y') }}
{% endif %}
{% 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_store( db, store_id=store.id if store else None, include_unpublished=False, footer_only=True ) finally: db.close() context = { "request": request, "store": store, "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 #}

Quick Links

``` ### 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="""

Welcome to Our Marketplace

We connect quality stores with customers worldwide.

Our mission is to provide a seamless shopping experience...

""", is_published=True, show_in_footer=True, display_order=1 ) # Shipping Information content_page_service.create_page( db, slug="shipping", title="Shipping Information", content="""

Shipping Policy

We offer fast and reliable shipping...

""", is_published=True, show_in_footer=True, display_order=2 ) # Returns content_page_service.create_page( db, slug="returns", title="Returns & Refunds", content="""

Return Policy

30-day return policy on all items...

""", is_published=True, show_in_footer=True, display_order=3 ) # Privacy Policy content_page_service.create_page( db, slug="privacy", title="Privacy Policy", content="""

Privacy Policy

Your privacy is important to us...

""", 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="""

Terms of Service

By using our platform, you agree to...

""", is_published=True, show_in_footer=True, display_order=5 ) # Contact content_page_service.create_page( db, slug="contact", title="Contact Us", content="""

Get in Touch

Have questions? We'd love to hear from you!

Email: support@example.com

""", is_published=True, show_in_footer=True, display_order=6 ) # FAQ content_page_service.create_page( db, slug="faq", title="Frequently Asked Questions", content="""

FAQ

How do I place an order?

Simply browse our products...

""", 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 " \ -H "Content-Type: application/json" \ -d '{ "slug": "about", "title": "About Our Marketplace", "content": "

About

Platform default content

", "is_published": true, "show_in_footer": true }' # View in shop curl http://localhost:8000/store/wizamart/about ``` ### 2. Test Store Override ```bash # Create store override curl -X POST http://localhost:8000/api/v1/store/wizamart/content-pages/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "slug": "about", "title": "About Wizamart", "content": "

About Wizamart

Custom store content

", "is_published": true }' # View in shop (should show store content) curl http://localhost:8000/store/wizamart/about ``` ### 3. Test Fallback ```bash # Delete store override curl -X DELETE http://localhost:8000/api/v1/store/wizamart/content-pages/{id} \ -H "Authorization: Bearer " # View in shop (should fall back to platform default) curl http://localhost:8000/store/wizamart/about ``` ## Summary You now have a complete CMS system that allows: 1. **Platform admins** to create default content for all stores 2. **Stores** to override specific pages with custom content 3. **Automatic fallback** to platform defaults when store 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 store context and routing support!