Skip to content

Architecture

System Overview

┌─────────────────────────────────────────────────────────────┐
│                        Nginx                                 │
│                   (Reverse Proxy)                            │
└─────────────────────────────────────────────────────────────┘
         │              │              │              │
         ▼              ▼              ▼              ▼
    ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐
    │ Landing │   │  Odoo   │   │   PWA   │   │  Docs   │
    │  :8001  │   │  :8069  │   │  :8000  │   │  :8080  │
    └─────────┘   └─────────┘   └─────────┘   └─────────┘
         │              │
         │              ▼
         │        ┌──────────┐
         └───────►│ REST API │
                  │/restapi/ │
                  └──────────┘
              ┌────────────────┐
              │   PostgreSQL   │
              │    (Odoo DB)   │
              └────────────────┘

Request Flow

Estimate Form Submission

1. User fills estimate form
2. Alpine.js validates client-side
3. reCAPTCHA v3 generates token
4. POST /api/estimate with form data + token
5. Flask verifies reCAPTCHA with Google
6. Flask calls Odoo REST API to create crm.lead
7. Success/error response returned to user

Helpdesk Form Submission

1. User fills helpdesk form
2. Alpine.js validates client-side
3. reCAPTCHA v3 generates token
4. POST /api/helpdesk with form data + token
5. Flask verifies reCAPTCHA with Google
6. Flask calls Odoo REST API to create helpdesk.ticket
7. Success/error response returned to user

Component Architecture

Flask Application

# App Factory Pattern
app/
├── __init__.py      # create_app() factory
├── config.py        # Config from environment
├── routes/          # Blueprints
   ├── main.py      # MainBlueprint: /, /services, /about
   ├── estimate.py  # EstimateBlueprint: /free-estimate, /api/estimate
   └── helpdesk.py  # HelpdeskBlueprint: /helpdesk, /api/helpdesk
└── services/        # Business logic
    ├── recaptcha.py # verify_recaptcha(token)
    └── odoo_api.py  # OdooAPI.create(), OdooAPI.search()

Template Inheritance

base.html
├── index.html
├── services.html
├── about.html
├── estimate.html
└── helpdesk.html

components/
├── header.html    # Navigation
├── footer.html    # Footer with contact info
├── hero.html      # Hero section
└── forms.html     # Form macros (input, textarea, etc.)

CSS Architecture

static/css/
├── style.css           # Compiled Tailwind output
└── themes/
    ├── blue.css        # --color-primary: #1e40af
    ├── slate.css       # --color-primary: #334155
    └── earth.css       # --color-primary: #78350f

Theme is selected via THEME environment variable and loaded in base.html.

Docker Integration

The landing page runs as a Docker container in the main stack:

# docker-compose.yml
landing:
  build:
    context: ./landing-page
    dockerfile: Dockerfile
  environment:
    - THEME=${LANDING_THEME:-slate}
    - ODOO_BASE_URL=http://odoo:8069
    - RECAPTCHA_SITE_KEY=${RECAPTCHA_SITE_KEY}
    # ... other env vars
  depends_on:
    - odoo
  healthcheck:
    test: ["CMD", "python", "-c", "...urlopen('http://localhost:8001/health')"]

Security

  1. reCAPTCHA v3: Invisible bot protection on all forms
  2. HTTPS: SSL termination at Nginx
  3. No Direct DB Access: All data goes through Odoo REST API
  4. API Key Auth: Odoo API key for authenticated requests
  5. Input Validation: Client-side (Alpine.js) + Server-side (Flask)