From 03829a38b2cebd32fe0e0b85f85573279f683998 Mon Sep 17 00:00:00 2001 From: Atlas Developer Date: Tue, 23 Jun 2026 00:48:45 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Atlas=20Academy=20=E2=80=94=20Odoo=20eL?= =?UTF-8?q?earning=20platform,=20full=20fusion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 9-course Dutch e-learning platform fused onto atlasacademy.nl via Caddy reverse proxy. Odoo 19 Community as course engine (website_slides), static HTML for marketing front. Single Odoo account system. - static/: 8 marketing pages (index, pricing, coaching, leerpad, over, shop, bisl, esf) - backend/odoo_relay.py: lead relay Flask service (POST /academy-lead → Odoo CRM) - caddy/academy.caddyfile: full Caddy config with Odoo proxy + auth rewrites - docs/: ARCHITECTURE, USERFLOW, COURSES, DEPLOYMENT, SECURITY, ODOO Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 38 ++ README.md | 207 ++++++ backend/odoo_relay.py | 234 +++++++ caddy/academy.caddyfile | 68 ++ docs/ARCHITECTURE.md | 124 ++++ docs/COURSES.md | 169 +++++ docs/DEPLOYMENT.md | 181 ++++++ docs/ODOO.md | 160 +++++ docs/SECURITY.md | 108 +++ docs/USERFLOW.md | 197 ++++++ static/bisl.html | 1191 ++++++++++++++++++++++++++++++++++ static/coaching.html | 997 ++++++++++++++++++++++++++++ static/esf.html | 201 ++++++ static/index.html | 245 +++++++ static/leerpad.html | 1371 +++++++++++++++++++++++++++++++++++++++ static/over.html | 487 ++++++++++++++ static/pricing.html | 964 +++++++++++++++++++++++++++ static/shop.html | 204 ++++++ 18 files changed, 7146 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 backend/odoo_relay.py create mode 100644 caddy/academy.caddyfile create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/COURSES.md create mode 100644 docs/DEPLOYMENT.md create mode 100644 docs/ODOO.md create mode 100644 docs/SECURITY.md create mode 100644 docs/USERFLOW.md create mode 100644 static/bisl.html create mode 100644 static/coaching.html create mode 100644 static/esf.html create mode 100644 static/index.html create mode 100644 static/leerpad.html create mode 100644 static/over.html create mode 100644 static/pricing.html create mode 100644 static/shop.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5adbc21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Secrets — never commit +*.env +secrets/ +*.key +*.pem +*.p12 + +# Backups +*.bak +*.bak.* +*.pre-* + +# Python +__pycache__/ +*.pyc +*.pyo +.venv/ +venv/ + +# Editor +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# Database +*.sqlite +*.db +users.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb731c4 --- /dev/null +++ b/README.md @@ -0,0 +1,207 @@ +
+ +Atlas Academy + +# Atlas Academy + +**Online leerplatform voor ondernemers die bouwen** + +[![Live](https://img.shields.io/badge/status-live-brightgreen?style=flat-square)](https://atlasacademy.nl) +[![Courses](https://img.shields.io/badge/cursussen-9-2E80FF?style=flat-square)](https://atlasacademy.nl/slides) +[![Platform](https://img.shields.io/badge/engine-Odoo%2019%20eLearning-714B67?style=flat-square)](https://www.odoo.com) +[![Host](https://img.shields.io/badge/host-Hetzner%20CPX32-D44000?style=flat-square)](https://hetzner.com) +[![License](https://img.shields.io/badge/license-proprietary-lightgrey?style=flat-square)](#) + +[**atlasacademy.nl**](https://atlasacademy.nl)  ·  [Cursussen](https://atlasacademy.nl/slides)  ·  [Coaching](https://atlasacademy.nl/coaching.html)  ·  [Prijzen](https://atlasacademy.nl/pricing.html) + +
+ +--- + +## Wat is dit? + +Atlas Academy is een **Odoo eLearning-platform** volledig gefused met een statische marketingsite onder één domein. Geen aparte subdomains, geen dubbele login — één URL, één account, één cursusengine. + +**Kernidee:** statische marketingpagina's voor branding + Odoo `/slides` als volledige cursusmotor, getranspareerd via Caddy reverse proxy op `atlasacademy.nl`. + +``` +Browser → atlasacademy.nl (Caddy) + ├── / → static index.html (marketing homepage) + ├── /pricing → static pricing.html + ├── /coaching → static coaching.html + ├── /slides → Odoo 19 eLearning (9 cursussen) + ├── /web/login → Odoo auth (single login) + └── /web/signup → Odoo signup (open, b2c) +``` + +--- + +## Architectuur + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ atlasacademy.nl │ +│ Caddy (atlas-01 Hetzner) │ +│ │ +│ ┌──────────────────────┐ ┌──────────────────────────────────┐ │ +│ │ Static Marketing │ │ Odoo 19 Community (eLearning) │ │ +│ │ /var/www/academy/ │ │ http://100.93.16.81:8069 │ │ +│ │ │ │ │ │ +│ │ index.html │ │ /slides → cursuscatalog │ │ +│ │ pricing.html │ │ /slides/ → cursuspagina │ │ +│ │ coaching.html │ │ /web/login → inloggen │ │ +│ │ leerpad.html │ │ /web/signup → registreren │ │ +│ │ over.html │ │ /web/assets/* → JS/CSS │ │ +│ │ shop.html │ │ │ │ +│ │ bisl.html │ │ Website 3: "Atlas Academy" │ │ +│ │ esf.html │ │ domain = atlasacademy.nl │ │ +│ └──────────────────────┘ └──────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ Lead Relay /academy-lead → 127.0.0.1:7793 (odoo_relay.py) │ │ +│ │ (POST JSON → Odoo CRM lead + email fallback) │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Cursuscatalogus + +| # | Cursus | URL | Lessen | Quizvragen | +|---|--------|-----|--------|------------| +| 1 | Praktijktraining Lean | `/slides/praktijktraining-lean-1` | 7 | 21 | +| 2 | Sales vanaf Nul | `/slides/sales-vanaf-nul-2` | 10 | 30 | +| 3 | Netwerken & Relaties | `/slides/netwerken-relaties-3` | 5 | 12 | +| 4 | Strategisch Denken | `/slides/strategisch-denken-4` | 9 | 26 | +| 5 | Alles Automatiseren met AI | `/slides/alles-automatiseren-met-ai-5` | 5 | 15 | +| 6 | IT-Basis & Manier van Denken | `/slides/it-basis-manier-van-denken-6` | 3 | 9 | +| 7 | Business & Juridisch | `/slides/business-juridisch-7` | 3 | 9 | +| 8 | Marketing & Funnels | `/slides/marketing-funnels-8` | 4 | 12 | +| 9 | Startup & Groei | `/slides/startup-groei-9` | 7 | 19 | + +**Totaal:** 53 lessen · 153 quizvragen + +Elke cursus = theorie per les → kennischeck (multiple choice, 1 correct, met uitleg). + +--- + +## Tech stack + +| Laag | Technologie | Rol | +|------|------------|-----| +| Domein | Caddy 2 | TLS, routing, static serve, reverse proxy | +| Frontend | Vanilla HTML/CSS/JS | Marketingpagina's | +| eLearning | Odoo 19 Community (`website_slides`) | Cursussen, accounts, voortgang | +| Database | PostgreSQL (Odoo intern) | Users, cursussen, leads | +| CRM | Odoo CRM (`crm.lead`) | Leads van lead-relay | +| Lead relay | Python Flask (`odoo_relay.py`) | `POST /academy-lead` → Odoo + email | +| VPS | Hetzner CPX32 (atlas-01) | Alle services | +| Tailscale | Tailnet `100.93.16.81` | Interne Odoo bereikbaarheid | + +--- + +## User journey + +``` +[Bezoeker] → atlasacademy.nl + │ + ├── leest marketingpagina's (pricing, coaching, over) + │ + ├── klikt "Bekijk de cursussen →" + │ → /slides (Odoo cursuscatalogus) + │ + ├── opent cursuspagina → lees les → maak quiz + │ (anoniem: preview mogelijk) + │ + ├── wil voortgang opslaan → "Aanmelden" + │ → /web/signup (Odoo, b2c open registratie) + │ → account aangemaakt (email bevestiging via atlasacademy.nl) + │ + └── ingelogd → cursus volgen → voortgang opgeslagen +``` + +--- + +## Deployment + +### Vereisten +- `atlas-01` Hetzner VPS (SSH alias in `~/.ssh/config`) +- Odoo 19 Community draait in Docker (`atlas-odoo` container) +- Caddy draait met Caddyfile in `/etc/caddy/Caddyfile` + +### Static marketingpagina aanpassen + +```bash +scp coaching.html atlas-01:/var/www/atlasacademy.nl/coaching.html +curl -so /dev/null -w '%{http_code}' https://atlasacademy.nl/coaching.html +``` + +### Cursus bouwen in Odoo + +```bash +# Upload script naar atlas-01, run in Odoo ORM shell +scp my_course.py atlas-01:/tmp/ +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http < /tmp/my_course.py" +``` + +Zie [`docs/COURSES.md`](docs/COURSES.md) voor het volledige cursusformaat. + +### Caddy herladen + +```bash +ssh atlas-01 "caddy reload --config /etc/caddy/Caddyfile" +``` + +### Lead relay herstarten + +```bash +ssh atlas-01 "systemctl restart atlas-academy-relay && systemctl status atlas-academy-relay" +``` + +--- + +## Security + +- **Secrets:** alle credentials in `/etc/atlas/academy-relay.env` (root 600), niet in source +- **Odoo backend:** `/web` niet geproxied → admin-panel enkel via tailnet/SSO +- **Signup:** `website.auth_signup_uninvited = 'b2c'` alleen op website 3 (academy). Corp website 1 = `b2b` (gesloten) +- **Headers:** `X-Frame-Options DENY`, `X-Content-Type-Options nosniff`, `Strict-Transport-Security` +- **ESF tracker:** `X-Robots-Tag: noindex, nofollow` (persoonlijk ITMG-studieoverzicht) + +Zie [`docs/SECURITY.md`](docs/SECURITY.md) voor het volledige security-model. + +--- + +## Projectstructuur + +``` +atlas-academy/ +├── README.md +├── docs/ +│ ├── ARCHITECTURE.md # Volledige systeemarchitectuur +│ ├── USERFLOW.md # User journeys & swimlane diagrammen +│ ├── COURSES.md # Cursusstructuur & ERD +│ ├── DEPLOYMENT.md # Deployment runbook +│ ├── SECURITY.md # Security model +│ └── ODOO.md # Odoo eLearning setup & gotcha's +├── static/ # Marketingpagina's (index, pricing, coaching…) +├── backend/ +│ └── odoo_relay.py # Lead relay service (Flask) +└── caddy/ + └── academy.caddyfile # Caddy-configuratie voor atlasacademy.nl +``` + +--- + +## Licentie & eigendom + +Proprietary — Atlas Corporation, Tilburg NL. Alle rechten voorbehouden. + +**Operator:** Chaib Aarab — [info@atlascorporation.nl](mailto:info@atlascorporation.nl) + +--- + +
+ Built with Odoo 19 Community · Caddy · Hetzner · Atlas Corporation 2026 +
diff --git a/backend/odoo_relay.py b/backend/odoo_relay.py new file mode 100644 index 0000000..6021eb8 --- /dev/null +++ b/backend/odoo_relay.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 +""" +Atlas Academy — Odoo Lead Relay +Listens on 127.0.0.1:7793, accepts POST /lead, creates crm.lead in Odoo. +Also handles admin actions via _action field for the admin portal. +""" +import datetime +import json +import logging +import os +import smtplib +import xmlrpc.client +from email.mime.text import MIMEText +from http.server import BaseHTTPRequestHandler, HTTPServer + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s [relay] %(levelname)s %(message)s' +) +log = logging.getLogger('academy-relay') + +ODOO_URL = "http://100.93.16.81:8069" +ODOO_DB = 'atlas' +ODOO_CREDS = [(os.environ['ODOO_RELAY_LOGIN'], os.environ['ODOO_RELAY_PASS'])] +UID_FILE = '/opt/atlas/academy/.odoo_uid' + +# Admin config +ADMIN_PASS = os.environ.get('ACADEMY_ADMIN_PASS') + +# Notification config +NOTIFY_SMTP_HOST = os.environ.get('LEAD_SMTP_HOST', 'smtp.gmail.com') +NOTIFY_SMTP_PORT = int(os.environ.get('LEAD_SMTP_PORT', '587')) +NOTIFY_SMTP_USER = os.environ.get('LEAD_SMTP_USER', 'chaibaarab98@gmail.com') +NOTIFY_SMTP_PASS = os.environ.get('LEAD_SMTP_PASS') +NOTIFY_SMTP_FROM = os.environ.get('LEAD_SMTP_FROM', 'chaibaarab98@gmail.com') +NOTIFY_TO = os.environ.get('LEAD_NOTIFY_TO', 'chaib@atlascorporation.nl') + + +def _notify_operator(name, email, interest, source, lead_id): + body = ( + f"Nieuwe Academy aanmelding!\n\n" + f"Naam: {name}\n" + f"E-mail: {email}\n" + f"Interesse: {interest or '-'}\n" + f"Bron: {source or '-'}\n" + f"Lead ID: {lead_id or '-'}\n\n" + f"-- Atlas Academy Lead Relay" + ) + try: + msg = MIMEText(body) + msg['Subject'] = f'Academy: {name} heeft zich aangemeld' + msg['From'] = NOTIFY_SMTP_FROM + msg['To'] = NOTIFY_TO + s = smtplib.SMTP(NOTIFY_SMTP_HOST, NOTIFY_SMTP_PORT, timeout=10) + s.starttls() + s.login(NOTIFY_SMTP_USER, NOTIFY_SMTP_PASS) + s.send_message(msg) + s.quit() + log.info('Notification sent to %s for lead %s', NOTIFY_TO, lead_id) + except Exception as e: + log.warning('Notification email failed: %s', e) + + +def _load_uid(): + if os.path.exists(UID_FILE): + try: + with open(UID_FILE) as f: + data = json.load(f) + return data.get('uid'), data.get('password') + except Exception: + pass + return None, None + + +def _save_uid(uid, password): + with open(UID_FILE, 'w') as f: + json.dump({'uid': uid, 'password': password}, f) + + +def _get_odoo_uid(): + uid, pw = _load_uid() + if uid: + return uid, pw + common = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/common', allow_none=True) + for login, password in ODOO_CREDS: + try: + uid = common.authenticate(ODOO_DB, login, password, {}) + if uid: + log.info('Odoo auth OK with %s (uid=%s)', login, uid) + _save_uid(uid, password) + return uid, password + except Exception as e: + log.warning('Odoo auth failed for %s: %s', login, e) + return None, None + + +def create_lead(name, email, interest, source): + uid, pw = _get_odoo_uid() + if not uid: + log.error('Odoo auth failed for all credentials -- lead not created') + return None, 'Odoo authentication failed' + try: + models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object', allow_none=True) + lead_id = models.execute_kw( + ODOO_DB, uid, pw, + 'crm.lead', 'create', + [{ + 'name': f'Academy Lead: {name}', + 'contact_name': name, + 'email_from': email, + 'description': f'Interesse: {interest} | Bron: {source}', + }] + ) + log.info('Created crm.lead id=%s for %s (%s)', lead_id, name, email) + _notify_operator(name, email, interest, source, lead_id) + return lead_id, None + except Exception as e: + if os.path.exists(UID_FILE): + os.remove(UID_FILE) + log.error('Odoo create_lead error: %s', e) + return None, str(e) + + +def _query_leads(limit=100, offset=0): + uid, pw = _get_odoo_uid() + if not uid: + return None, 'Odoo auth failed' + try: + models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object', allow_none=True) + ids = models.execute_kw(ODOO_DB, uid, pw, 'crm.lead', 'search', + [[('name', 'ilike', 'Academy Lead%')]], {'limit': limit, 'offset': offset}) + if not ids: + return [], None + fields = ['id', 'name', 'contact_name', 'email_from', 'description', 'create_date'] + leads = models.execute_kw(ODOO_DB, uid, pw, 'crm.lead', 'read', [ids], {'fields': fields}) + return sorted(leads, key=lambda l: l.get('id', 0), reverse=True), None + except Exception as e: + return None, str(e) + + +def _count_leads(): + uid, pw = _get_odoo_uid() + if not uid: + return None, None, 'Odoo auth failed' + try: + models = xmlrpc.client.ServerProxy(f'{ODOO_URL}/xmlrpc/2/object', allow_none=True) + total = models.execute_kw(ODOO_DB, uid, pw, 'crm.lead', 'search_count', + [[('name', 'ilike', 'Academy Lead%')]]) + today_start = datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%d 00:00:00') + today = models.execute_kw(ODOO_DB, uid, pw, 'crm.lead', 'search_count', + [[('name', 'ilike', 'Academy Lead%'), + ('create_date', '>=', today_start)]]) + return total, today, None + except Exception as e: + return None, None, str(e) + + +class Handler(BaseHTTPRequestHandler): + def log_message(self, fmt, *args): + log.info(fmt, *args) + + def _send_json(self, code, body): + data = json.dumps(body).encode() + self.send_response(code) + self.send_header('Content-Type', 'application/json') + self.send_header('Content-Length', str(len(data))) + self.send_header('Access-Control-Allow-Origin', 'https://atlasacademy.nl') + self.end_headers() + self.wfile.write(data) + + def do_OPTIONS(self): + self.send_response(204) + self.send_header('Access-Control-Allow-Origin', 'https://atlasacademy.nl') + self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS') + self.send_header('Access-Control-Allow-Headers', 'Content-Type') + self.end_headers() + + def _read_body(self, max_size=8192): + length = int(self.headers.get('Content-Length', 0)) + if length > max_size: + return None, 'payload too large' + try: + return json.loads(self.rfile.read(length)), None + except Exception: + return None, 'invalid JSON' + + def do_GET(self): + if self.path == '/health': + self._send_json(200, {'ok': True, 'service': 'academy-relay'}) + else: + self._send_json(404, {'ok': False, 'err': 'not found'}) + + def do_POST(self): + path = self.path.rstrip('/') + if path not in ('/lead', '/academy-lead'): + self._send_json(404, {'ok': False, 'err': 'not found'}) + return + + body, err = self._read_body() + if err: + self._send_json(400, {'ok': False, 'err': err}) + return + + # Admin DATA actions are DISABLED on the public endpoint (PII protection). + # The gated admin portal (academy_admin.py, behind basic_auth on the atlas-01 hub) + # reads Odoo directly via XML-RPC and does NOT use this endpoint for lead data. + action = body.get('_action', '') + if action: + self._send_json(403, {'ok': False, 'err': 'admin actions are not available on the public endpoint'}) + return + + # Default: create lead + name = str(body.get('name', '')).strip()[:120] + email = str(body.get('email', '')).strip()[:200] + interest = str(body.get('interest', '')).strip()[:200] + source = str(body.get('source', '')).strip()[:200] + + if not name or not email: + self._send_json(400, {'ok': False, 'err': 'name and email required'}) + return + + lead_id, err = create_lead(name, email, interest, source) + if lead_id: + self._send_json(200, {'ok': True, 'lead_id': lead_id}) + else: + log.warning('Returning ok:true despite error (email fallback active): %s', err) + self._send_json(200, {'ok': True, 'lead_id': None, 'note': 'queued'}) + + +if __name__ == '__main__': + host, port = '127.0.0.1', 7793 + server = HTTPServer((host, port), Handler) + log.info('Atlas Academy Relay listening on %s:%d', host, port) + server.serve_forever() diff --git a/caddy/academy.caddyfile b/caddy/academy.caddyfile new file mode 100644 index 0000000..f55d26d --- /dev/null +++ b/caddy/academy.caddyfile @@ -0,0 +1,68 @@ +# Caddy configuration snippet — atlasacademy.nl +# Full config lives on atlas-01 at /etc/caddy/Caddyfile +# Reload: ssh atlas-01 "caddy reload --config /etc/caddy/Caddyfile" + +atlasacademy.nl, www.atlasacademy.nl { + root * /var/www/atlasacademy.nl + encode gzip + + # Odoo eLearning — proxy course engine + auth paths to Odoo + # CRITICAL: X-Forwarded-Host required for Odoo multi-website routing (proxy_mode=True) + @odoo_elearning path /slides /slides/* /web/assets/* /web/image/* /web/static/* \ + /website_slides/* /website/static/* /web/session/* \ + /web/dataset/call_kw* /web/webclient/locale* \ + /web/login* /web/signup* /web/reset_password* + route @odoo_elearning { + reverse_proxy 100.93.16.81:8069 { + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto https + header_up X-Real-IP {remote_host} + } + } + + # Identity = Odoo (static auth retired) + redir /login /web/login?redirect=%2Fslides 302 + redir /login/ /web/login?redirect=%2Fslides 302 + redir /login.html /web/login?redirect=%2Fslides 302 + redir /register /web/signup?redirect=%2Fslides 302 + redir /register/ /web/signup?redirect=%2Fslides 302 + redir /register.html /web/signup?redirect=%2Fslides 302 + + # Catalog cutover — old static URLs → Odoo eLearning + redir /cursussen /slides 302 + redir /cursussen/ /slides 302 + redir /cursussen.html /slides 302 + redir /cursussen/sales.html /slides/sales-vanaf-nul-2 302 + redir /cursussen/netwerken.html /slides/netwerken-relaties-3 302 + redir /cursussen/strategie.html /slides/strategisch-denken-4 302 + redir /cursussen/ai.html /slides/alles-automatiseren-met-ai-5 302 + redir /cursussen/it-basis.html /slides/it-basis-manier-van-denken-6 302 + redir /cursussen/business.html /slides/business-juridisch-7 302 + redir /cursussen/marketing.html /slides/marketing-funnels-8 302 + redir /cursussen/startup.html /slides/startup-groei-9 302 + + # ESF tracker — personal ITMG log, keep out of search engines + @esf_priv path /esf /esf.html + header @esf_priv X-Robots-Tag "noindex, nofollow" + + # Clean URL rewrites for static pages + @bisl path /bisl /bisl/ + rewrite @bisl /bisl.html + @esf path /esf /esf/ + rewrite @esf /esf.html + + # Lead relay (Odoo CRM + email fallback) + route /academy-lead { + reverse_proxy 127.0.0.1:7793 + } + + file_server + + header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + Referrer-Policy strict-origin-when-cross-origin + Strict-Transport-Security max-age=31536000 + } +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..4b6c2cb --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,124 @@ +# Architectuur — Atlas Academy + +## Overzicht + +Atlas Academy is een **gefused platform**: één domein (`atlasacademy.nl`), twee lagen — statische HTML voor marketing, Odoo eLearning voor de cursusengine. Caddy verbindt beide transparant. + +## Componenten + +### 1. Caddy (reverse proxy + static server) +- Host: `atlas-01` (Hetzner CPX32, 178.105.85.200) +- Config: `/etc/caddy/Caddyfile` +- Rol: TLS terminatie, static files serveren, Odoo proxyen + +``` +atlasacademy.nl, www.atlasacademy.nl { + root * /var/www/atlasacademy.nl + encode gzip + + @odoo_elearning path /slides /slides/* /web/assets/* /web/image/* + /web/static/* /website_slides/* /web/session/* + /web/dataset/call_kw* /web/login* /web/signup* + /web/reset_password* + route @odoo_elearning { + reverse_proxy 100.93.16.81:8069 { + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto https + } + } + + redir /cursussen /slides 302 + redir /login /web/login?redirect=%2Fslides 302 + redir /register /web/signup?redirect=%2Fslides 302 + + file_server +} +``` + +**Kritisch:** `header_up X-Forwarded-Host {host}` is verplicht. Odoo (`proxy_mode=True`) leest de website-routing uit `X-Forwarded-Host`. Zonder dit serveert Odoo altijd website 1 (corp) in plaats van website 3 (academy). + +### 2. Statische marketinglaag +- Pad: `/var/www/atlasacademy.nl/` +- Pagina's: `index.html`, `pricing.html`, `coaching.html`, `leerpad.html`, `over.html`, `shop.html`, `bisl.html`, `esf.html` +- Stijl: dark theme (`--bg: hsl(222,48%,8%)`), Atlas blue (`#2E80FF`), gold (`#D4A24C`) +- GA4: `G-JBWZWZMKBC` + rollup `GT-MR2TH3RQ` in `` van alle pagina's + +### 3. Odoo 19 Community (eLearning) +- Container: `atlas-odoo` (Docker op atlas-01) +- Database: `atlas` +- Interne URL: `http://localhost:8069` (op atlas-01) / `http://100.93.16.81:8069` (tailnet) +- Modules: `website_slides`, `website`, `crm`, `auth_signup` +- Website 3: "Atlas Academy", `domain='https://atlasacademy.nl'` +- Website 1: "Atlas Corporation", `domain=False` (default fallback) + +**Multi-website routing:** Odoo leest `X-Forwarded-Host` en matcht op `website.domain`. `_get_current_website_id` is ORM-gecached — na website-aanmaken altijd `docker restart atlas-odoo`. + +### 4. Lead Relay (`odoo_relay.py`) +- Service: `atlas-academy-relay` (systemd) +- Bindt op: `127.0.0.1:7793` +- Caddy proxiet: `/academy-lead → 127.0.0.1:7793` +- Input: `POST {name, email, interest, source}` +- Actie: maakt `crm.lead` aan in Odoo + email-fallback via SMTP +- Secrets: `/etc/atlas/academy-relay.env` (root 600) + +## Datamodel (ERD) + +``` +┌─────────────┐ ┌──────────────────┐ ┌───────────────┐ +│ res.users │────<│ slide.channel │────<│ slide.slide │ +│ (Odoo) │ │ (cursus) │ │ (les/sectie) │ +│ │ │ │ │ │ +│ name │ │ name │ │ name │ +│ email │ │ website_id = 3 │ │ html_content │ +│ password │ │ website_slug │ │ slide_categ. │ +│ partner_id │ │ cover_properties│ │ is_category │ +└─────────────┘ │ auth_signup_inv.│ │ sequence │ + └──────────────────┘ └───────┬───────┘ + │ + ┌───────▼───────┐ + │ slide.question │ + │ (quizvraag) │ + │ question │ + │ slide_id │ + └───────┬───────┘ + │ + ┌───────▼───────┐ + │ slide.answer │ + │ text_value │ + │ is_correct │ + │ comment │ + └───────────────┘ + +┌──────────────┐ +│ crm.lead │ ← aangemaakt via odoo_relay.py +│ name │ +│ email_from │ +│ description │ +│ source │ +└──────────────┘ +``` + +## Omgevingsvariabelen + +| Bestand | Variabele | Gebruik | +|---------|-----------|---------| +| `/etc/atlas/academy-relay.env` | `ODOO_RELAY_LOGIN` | XML-RPC login voor lead-relay | +| `/etc/atlas/academy-relay.env` | `ODOO_RELAY_PASS` | XML-RPC wachtwoord | +| `/etc/atlas/academy-relay.env` | `ACADEMY_ADMIN_PASS` | Beheerder-endpoint authenticatie | +| `/etc/atlas/academy-relay.env` | `LEAD_SMTP_PASS` | Gmail app-wachtwoord voor email-fallback | + +Alle bestanden: `root:root 600`. Nooit in source committen. + +## Deployment diagram + +``` +[Dev/Operator] + │ + ├── scp *.html → atlas-01:/var/www/atlasacademy.nl/ + │ + ├── scp script.py → atlas-01:/tmp/ + │ ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http < /tmp/script.py" + │ + └── caddy reload --config /etc/caddy/Caddyfile (na Caddyfile-wijziging) +``` diff --git a/docs/COURSES.md b/docs/COURSES.md new file mode 100644 index 0000000..433c7c6 --- /dev/null +++ b/docs/COURSES.md @@ -0,0 +1,169 @@ +# Cursusstructuur — Atlas Academy + +## Catalogus + +| ID | Naam | Slug | Secties | Lessen | Quizvragen | Cover kleur | +|----|------|------|---------|--------|------------|-------------| +| 1 | Praktijktraining Lean | `praktijktraining-lean-1` | 2 | 7 | 21 | `#1a4fa0` | +| 2 | Sales vanaf Nul | `sales-vanaf-nul-2` | 2 | 10 | 30 | `#0f7a3d` | +| 3 | Netwerken & Relaties | `netwerken-relaties-3` | 1 | 5 | 12 | `#7b2d8b` | +| 4 | Strategisch Denken | `strategisch-denken-4` | 2 | 9 | 26 | `#c47a1e` | +| 5 | Alles Automatiseren met AI | `alles-automatiseren-met-ai-5` | 1 | 5 | 15 | `#1a8a8a` | +| 6 | IT-Basis & Manier van Denken | `it-basis-manier-van-denken-6` | 1 | 3 | 9 | `#8a3a1a` | +| 7 | Business & Juridisch | `business-juridisch-7` | 1 | 3 | 9 | `#2a6a8a` | +| 8 | Marketing & Funnels | `marketing-funnels-8` | 1 | 4 | 12 | `#8a1a4a` | +| 9 | Startup & Groei | `startup-groei-9` | 2 | 7 | 19 | `#3a7a1a` | + +**Totaal:** 53 lessen · 153 quizvragen + +URL-patroon: `https://atlasacademy.nl/slides/` + +--- + +## Cursusstructuur (Odoo-modellen) + +### `slide.channel` — Cursus +```python +{ + 'name': 'Sales vanaf Nul', + 'website_id': 3, # Atlas Academy + 'website_published': True, + 'website_slug': 'sales-vanaf-nul-2', + 'cover_properties': '{"background-color": "#0f7a3d", ...}', + 'channel_type': 'documentation', +} +``` + +### `slide.slide` — Sectie (is_category=True) +```python +{ + 'channel_id': 2, + 'name': 'Deel 1: Mindset & Voorbereiding', + 'is_category': True, + 'sequence': 1, +} +``` + +### `slide.slide` — Les (artikel) +```python +{ + 'channel_id': 2, + 'name': 'Les 1 — De verkoper als adviseur', + 'slide_category': 'article', + 'is_category': False, + 'category_id': , + 'html_content': '

Theorie tekst...

', + 'sequence': 2, + 'website_published': True, +} +``` + +### `slide.question` — Quizvraag +```python +{ + 'slide_id': , + 'question': 'Wat is het primaire doel van een adviseur-verkoper?', +} +``` + +### `slide.answer` — Antwoordoptie +```python +{ + 'question_id': , + 'text_value': 'Vertrouwen opbouwen en de klant echte waarde bieden', + 'is_correct': True, + 'comment': 'Een adviseur-verkoper stelt klantbelang centraal.', +} +``` + +--- + +## Cursus bouwen via ORM shell + +```python +# save als /tmp/build_cursus.py, dan: +# ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http < /tmp/build_cursus.py" + +env = env # Odoo shell + +# 1. Cursus aanmaken +channel = env['slide.channel'].sudo().create({ + 'name': 'Mijn Nieuwe Cursus', + 'website_id': 3, + 'website_published': True, + 'channel_type': 'documentation', +}) + +# 2. Sectie toevoegen +sectie = env['slide.slide'].sudo().create({ + 'channel_id': channel.id, + 'name': 'Deel 1: Introductie', + 'is_category': True, + 'sequence': 1, +}) + +# 3. Les toevoegen +les = env['slide.slide'].sudo().create({ + 'channel_id': channel.id, + 'name': 'Les 1 — Overzicht', + 'slide_category': 'article', + 'is_category': False, + 'category_id': sectie.id, + 'html_content': '

Theorie...

', + 'sequence': 2, + 'website_published': True, +}) + +# 4. Quizvraag + antwoorden +vraag = env['slide.question'].sudo().create({ + 'slide_id': les.id, + 'question': 'Wat leer je in les 1?', +}) +for tekst, correct, uitleg in [ + ('Optie A', True, 'Correct omdat...'), + ('Optie B', False, 'Fout omdat...'), + ('Optie C', False, 'Fout omdat...'), +]: + env['slide.answer'].sudo().create({ + 'question_id': vraag.id, + 'text_value': tekst, + 'is_correct': correct, + 'comment': uitleg, + }) + +env.cr.commit() +print(f"Cursus aangemaakt: /slides/{channel.website_slug}") +``` + +--- + +## Content-richtlijnen + +- **Theorie per les:** 300–500 woorden, plain HTML (`

`, `

`, `

    `) +- **Quizvragen per les:** minimaal 3, maximaal 5 +- **Antwoordopties:** altijd 3, precies 1 correct +- **Uitleg:** altijd een `comment` bij elke optie (leermoment) +- **Toon:** generiek en professioneel — niet Chaib-centric, voor de community +- **Taal:** Nederlands + +--- + +## Slug-conventie + +`-` + +Voorbeeld: channel ID 4, naam "Strategisch Denken" → `strategisch-denken-4` + +Odoo genereert de slug automatisch op basis van de naam bij aanmaken. + +--- + +## ESF / BiSL (apart, nog te migreren) + +| Pagina | Status | Doel | +|--------|--------|------| +| `bisl.html` | Statisch (actief) | BiSL Foundation examentrainer (custom engine) | +| `bisl_examen.html` | Statisch (actief) | ~82-97 vragen, eigen JS-quizengine | +| `esf.html` | Statisch, noindex | Persoonlijk ITMG ESF-studieoverzicht | + +Migratie naar Odoo eLearning is gepland maar niet launch-blocking. diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..c1f87a4 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,181 @@ +# Deployment Runbook — Atlas Academy + +## Infrastructuur + +| Service | Host | Pad | +|---------|------|-----| +| Caddy (TLS + proxy) | atlas-01 (`178.105.85.200`) | `/etc/caddy/Caddyfile` | +| Static marketing | atlas-01 | `/var/www/atlasacademy.nl/` | +| Odoo eLearning | atlas-01 Docker | container `atlas-odoo`, DB `atlas` | +| Lead relay | atlas-01 systemd | `atlas-academy-relay`, port `7793` | +| Tailnet IP | atlas-01 tailscale | `100.93.16.81` | + +--- + +## 1. Statische pagina deployen + +```bash +# Één pagina pushen +scp pricing.html atlas-01:/var/www/atlasacademy.nl/pricing.html +curl -so /dev/null -w '%{http_code}' https://atlasacademy.nl/pricing.html +# verwacht: 200 + +# Meerdere pagina's tegelijk +scp *.html atlas-01:/var/www/atlasacademy.nl/ +``` + +Geen Caddy reload nodig — Caddy serveert files direct. + +--- + +## 2. Cursus toevoegen aan Odoo + +```bash +# 1. Script schrijven op lokale machine (zie docs/COURSES.md voor formaat) +# 2. Uploaden naar atlas-01 +scp build_cursus.py atlas-01:/tmp/ + +# 3. Uitvoeren in Odoo ORM shell +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http < /tmp/build_cursus.py" + +# Verwachte output: +# Cursus aangemaakt: /slides/mijn-cursus-10 +``` + +**Let op:** altijd `env.cr.commit()` aan het einde van het script, anders worden geen wijzigingen opgeslagen. + +--- + +## 3. Caddy configuratie wijzigen + +```bash +# 1. Huidige config backuppen +ssh atlas-01 "cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%s)" + +# 2. Bewerken +ssh atlas-01 "nano /etc/caddy/Caddyfile" + +# 3. Valideren vóór reload +ssh atlas-01 "caddy validate --config /etc/caddy/Caddyfile" + +# 4. Herladen (zero-downtime) +ssh atlas-01 "caddy reload --config /etc/caddy/Caddyfile" +``` + +--- + +## 4. Lead relay + +```bash +# Status +ssh atlas-01 "systemctl status atlas-academy-relay" + +# Logs +ssh atlas-01 "journalctl -u atlas-academy-relay -n 50 --no-pager" + +# Herstarten (na config-wijziging) +ssh atlas-01 "systemctl restart atlas-academy-relay" + +# Secrets bijwerken +ssh atlas-01 "nano /etc/atlas/academy-relay.env" +ssh atlas-01 "systemctl restart atlas-academy-relay" +``` + +--- + +## 5. Odoo herstarten + +Na wijzigingen die ORM-cache moeten legen (website aanmaken, config params): + +```bash +ssh atlas-01 "docker restart atlas-odoo" +# wacht ~30s +curl -so /dev/null -w '%{http_code}' https://atlasacademy.nl/slides +# verwacht: 200 +``` + +--- + +## 6. Odoo ORM shell — veelgebruikte één-regels + +```bash +# Lijst alle cursussen +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +for c in env['slide.channel'].sudo().search([]): print(c.id, c.name, c.website_id.id) +EOF + +# Controleer website 3 +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +w = env['website'].sudo().browse(3) +print(w.name, w.domain, w.auth_signup_uninvited) +EOF + +# Signup status per website +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +for w in env['website'].sudo().search([]): print(w.id, w.name, w.auth_signup_uninvited) +EOF +``` + +--- + +## 7. Assets / cache legen + +```bash +# Browser-cache bypass: open in incognito +# Odoo assets regenereren (na theme-wijziging) +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +env['ir.attachment'].sudo().search([ + ('url', 'like', '/web/assets/'), + ('store_fname', '!=', False) +]).unlink() +env.cr.commit() +print('Assets cleared') +EOF +ssh atlas-01 "docker restart atlas-odoo" +``` + +--- + +## 8. IndexNow pingen na content-wijziging + +```bash +KEY="atlascorporation-indexnow-2025" +curl -X POST "https://api.indexnow.org/indexnow" \ + -H "Content-Type: application/json" \ + -d "{\"host\":\"atlasacademy.nl\",\"key\":\"$KEY\",\"urlList\":[\"https://atlasacademy.nl/\",\"https://atlasacademy.nl/slides\"]}" +``` + +--- + +## 9. Rollback procedure + +```bash +# Static pagina rollback (bak-bestanden aanwezig) +ssh atlas-01 "ls /var/www/atlasacademy.nl/*.bak* | tail -5" +ssh atlas-01 "cp /var/www/atlasacademy.nl/pricing.html.bak.nav /var/www/atlasacademy.nl/pricing.html" + +# Caddy rollback +ssh atlas-01 "cp /etc/caddy/Caddyfile.bak. /etc/caddy/Caddyfile && caddy reload --config /etc/caddy/Caddyfile" + +# Odoo cursus verwijderen +# Verwijder via Odoo backend UI (tailnet: http://100.93.16.81:8069/web) +``` + +--- + +## 10. Monitoring + +```bash +# HTTPS check +curl -so /dev/null -w '%{http_code}' https://atlasacademy.nl/ +curl -so /dev/null -w '%{http_code}' https://atlasacademy.nl/slides + +# Relay check +curl -s -X POST https://atlasacademy.nl/academy-lead \ + -H "Content-Type: application/json" \ + -d '{"name":"Test","email":"test@test.nl","interest":"test","source":"deploy-check"}' +# verwacht: {"ok": true, ...} + +# Odoo health +curl -so /dev/null -w '%{http_code}' http://100.93.16.81:8069/web/health +``` diff --git a/docs/ODOO.md b/docs/ODOO.md new file mode 100644 index 0000000..4b51966 --- /dev/null +++ b/docs/ODOO.md @@ -0,0 +1,160 @@ +# Odoo eLearning Setup — Atlas Academy + +## Installatie + +`website_slides` is geïnstalleerd als onderdeel van Odoo 19 Community op atlas-01. + +```bash +# Verificatie +ssh atlas-01 "docker exec atlas-odoo odoo --list-db 2>/dev/null" +# DB: atlas + +# Module status +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +m = env['ir.module.module'].sudo().search([('name','=','website_slides')]) +print(m.name, m.state) # verwacht: website_slides installed +EOF +``` + +--- + +## Multi-website configuratie + +Atlas Academy draait op **website 3** (apart van de Atlas Corporation-website op website 1). + +| | Website 1 | Website 3 | +|--|-----------|-----------| +| Naam | Atlas Corporation | Atlas Academy | +| Domein | *(default)* | `https://atlasacademy.nl` | +| Signup | `b2b` (gesloten) | `b2c` (open) | +| Taal | NL | NL | +| Logo | Atlas Corp | Atlas Academy icon | + +### Kritische gotcha's + +**1. Caching van website-routing** +`_get_current_website_id` is ORM-gecached. Na aanmaken/wijzigen van een website: +```bash +ssh atlas-01 "docker restart atlas-odoo" +``` + +**2. X-Forwarded-Host verplicht** +Caddy moet `X-Forwarded-Host {host}` doorgeven, anders serveert Odoo altijd website 1: +```caddyfile +reverse_proxy 100.93.16.81:8069 { + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto https +} +``` + +**3. `proxy_mode = True`** +Controleer `/opt/atlas-odoo/config/odoo.conf`: +```ini +proxy_mode = True +``` + +**4. Signup is per-website, niet globaal** +De globale `auth_signup.allow_uninvited` parameter wordt **genegeerd** als `website` module actief is. Gebruik altijd: +```python +env['website'].sudo().browse(3).write({'auth_signup_uninvited': 'b2c'}) +env.cr.commit() +``` + +--- + +## Website 3 aanmaken (referentie) + +```python +env = env # Odoo shell + +w3 = env['website'].sudo().create({ + 'name': 'Atlas Academy', + 'domain': 'https://atlasacademy.nl', + 'company_id': env.company.id, + 'language_ids': [(4, env.ref('base.lang_nl').id)], + 'default_lang_id': env.ref('base.lang_nl').id, + 'auth_signup_uninvited': 'b2c', +}) +# Stel logo in +import base64, requests +logo_data = requests.get('https://atlasacademy.nl/atlas-icon.png').content +w3.write({'logo': base64.b64encode(logo_data).decode()}) +env.cr.commit() +print(f"Website aangemaakt: ID={w3.id}") +# Vervolgens: docker restart atlas-odoo +``` + +--- + +## Cursus website-toewijzing + +Alle cursussen (`slide.channel`) moeten `website_id=3` hebben: + +```python +channels = env['slide.channel'].sudo().search([]) +for c in channels: + if not c.website_id or c.website_id.id != 3: + c.sudo().write({'website_id': 3}) +env.cr.commit() +print(f"{len(channels)} cursussen toegewezen aan website 3") +``` + +--- + +## Email base-URL + +Odoo gebruikt `website.get_base_url()` voor links in e-mails (wachtwoord reset etc.). +Dankzij multi-website: +- Website 3 → `get_base_url()` = `https://atlasacademy.nl` ✅ +- Website 1 → `get_base_url()` = corp-domein ✅ + +De globale `web.base.url` parameter wordt **niet** gewijzigd (zou corp-emails breken). + +--- + +## Odoo backend bereikbaarheid + +| Route | Bereikbaar? | Via | +|-------|-------------|-----| +| `atlasacademy.nl/slides` | ✅ Publiek | Caddy proxy | +| `atlasacademy.nl/web/login` | ✅ Publiek | Caddy proxy | +| `atlasacademy.nl/web` (backend) | ❌ Niet geproxied | — | +| `http://100.93.16.81:8069` | ✅ Tailnet only | Direct | +| `odoo.atlascorporation.nl` | ✅ SSO only | Authentik + Caddy | + +--- + +## Veelgebruikte ORM-commando's + +```bash +# Shell openen +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" + +# Alle cursussen tonen +for c in env['slide.channel'].sudo().search([]): print(c.id, c.name, c.website_slug) + +# Cursuspagina URL genereren +c = env['slide.channel'].sudo().browse(2) +print(f"https://atlasacademy.nl/slides/{c.website_slug}") + +# Lessen van een cursus tonen +slides = env['slide.slide'].sudo().search([('channel_id','=',2),('is_category','=',False)]) +for s in slides: print(s.sequence, s.name, len(s.question_ids), 'vragen') + +# Website-instellingen inspecteren +w = env['website'].sudo().browse(3) +print(w.name, w.domain, w.auth_signup_uninvited, w.get_base_url()) +``` + +--- + +## Bekende issues & oplossingen + +| Issue | Oorzaak | Oplossing | +|-------|---------|-----------| +| `/web/signup` → 404 | `auth_signup_uninvited` niet op `b2c` | ORM shell: `w.write({'auth_signup_uninvited':'b2c'})` | +| Courses tonen op corp-website | `website_id=None` op channels | Script: set alle channels op `website_id=3` | +| Wachtwoord-reset e-mail heeft wrong URL | `web.base.url` verkeerd OF website 3 geen domein | Controleer `w3.domain` en `w3.get_base_url()` | +| Odoo toont corp-logo op academy-domein | Website-cache niet geleegd | `docker restart atlas-odoo` | +| `/slides` geeft 502 | Odoo container down | `docker start atlas-odoo && docker logs atlas-odoo` | diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..eaab809 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,108 @@ +# Security Model — Atlas Academy + +## Dreigingsmodel + +| Dreiging | Maatregel | Status | +|----------|-----------|--------| +| Hardcoded secrets in source | Env-bestanden (`/etc/atlas/*.env`, root 600) | ✅ Opgelost | +| Zwakke wachtwoord-hashing | bcrypt via `academy_auth_v2.py` (nu retired; Odoo native auth) | ✅ Opgelost | +| PII in publieke admin-panel | `academy_admin.py` verwijderd uit docroot | ✅ Opgelost | +| Odoo backend publiek bereikbaar | `/web` niet geproxied via academy-domein | ✅ Opgelost | +| Open signup op corp-website | `website 1.auth_signup_uninvited = 'b2b'` | ✅ Opgelost | +| Clickjacking | `X-Frame-Options: DENY` via Caddy | ✅ Actief | +| MIME-sniffing | `X-Content-Type-Options: nosniff` | ✅ Actief | +| HTTPS downgrade | `Strict-Transport-Security: max-age=31536000` | ✅ Actief | +| ESF-tracker indexeerbaar | `X-Robots-Tag: noindex, nofollow` + `robots.txt` | ✅ Actief | +| Stale SMTP app-wachtwoord | Handmatige rotatie vereist (Google Account UI) | ⚠️ Openstaand | +| XML-RPC relay-wachtwoord | In env, maar waarde mogelijk stale | ⚠️ Controleren | + +--- + +## Secrets locaties + +Alle secrets zijn **buiten source** gehouden. Alleen locaties zijn gedocumenteerd. + +| Bestand | Inhoud | Rechten | +|---------|--------|---------| +| `/etc/atlas/academy-relay.env` | `ODOO_RELAY_LOGIN`, `ODOO_RELAY_PASS`, `ACADEMY_ADMIN_PASS`, `LEAD_SMTP_PASS` | `root:root 600` | +| `/etc/atlas/academy-auth.env` | `AA_SECRET` (retired Flask JWT secret) | `root:root 600` | + +--- + +## Toegangsarchitectuur + +``` +Internet + │ + ▼ +atlasacademy.nl (Caddy) + │ + ├── /slides, /web/login, /web/signup → Odoo (public eLearning) + │ + ├── /academy-lead → odoo_relay.py (localhost only) + │ + ├── /var/www/atlasacademy.nl/* → Static files + │ + └── /web (NIET geproxied) → ❌ Geblokkeerd voor publiek + (Odoo backend enkel via tailnet) + +odoo.atlascorporation.nl (Caddy) + │ + └── Authentik forward_auth → Alleen via SSO bereikbaar +``` + +--- + +## Odoo signup-beveiliging + +``` +Website 1 (Atlas Corporation) → auth_signup_uninvited = 'b2b' → GESLOTEN +Website 3 (Atlas Academy) → auth_signup_uninvited = 'b2c' → OPEN (gewenst) +``` + +Verificatie: +```bash +ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF' +for w in env['website'].sudo().search([]): + print(f"Website {w.id} ({w.name}): signup={w.auth_signup_uninvited}") +EOF +``` + +--- + +## Headers (Caddy) + +```caddyfile +header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + Referrer-Policy strict-origin-when-cross-origin + Strict-Transport-Security max-age=31536000 +} +``` + +--- + +## Secrets roteren + +### SMTP app-wachtwoord (`LEAD_SMTP_PASS`) +1. Ga naar [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords) +2. Verwijder het oude wachtwoord, maak een nieuw aan +3. Update op atlas-01: `sudo nano /etc/atlas/academy-relay.env` +4. Herstart: `sudo systemctl restart atlas-academy-relay` + +### Odoo relay-wachtwoord (`ODOO_RELAY_PASS`) +1. Log in op Odoo backend (tailnet) +2. Wijzig wachtwoord van de relay-gebruiker +3. Update `/etc/atlas/academy-relay.env` +4. `sudo systemctl restart atlas-academy-relay` + +--- + +## Wat NIET te doen + +- ❌ Nooit secrets committen in git +- ❌ Nooit `/web` proxien via het publieke academy-domein +- ❌ Nooit wachtwoorden automatisch roteren (operator handelt dit af) +- ❌ Nooit `--send` gebruiken in `atlas_client_email.py` zonder goedkeuring +- ❌ Nooit studentgegevens publiceren (geen nep-reviews, nep-studentaantallen) diff --git a/docs/USERFLOW.md b/docs/USERFLOW.md new file mode 100644 index 0000000..4ccfe2c --- /dev/null +++ b/docs/USERFLOW.md @@ -0,0 +1,197 @@ +# User Flows & Use Cases — Atlas Academy + +## Use Cases + +### UC-1: Nieuwe bezoeker ontdekt het platform +**Actor:** Ondernemer (potentiële student) +**Doel:** Cursusaanbod verkennen zonder account + +``` +Bezoeker + │ + ├── [Vorige actie: Google → atlasacademy.nl] + │ + ▼ +atlasacademy.nl (index.html) + │ "Nu live · 9 cursussen" + │ + ├── klikt "Bekijk de cursussen →" + │ ↓ + │ /slides (Odoo cursuscatalogus) + │ │ + │ ├── ziet 9 cursuskaarten met kleur-covers + │ ├── klikt cursus → /slides/sales-vanaf-nul-2 + │ │ │ + │ │ ├── leest eerste lessen (preview) + │ │ └── beantwoordt quizvragen + │ │ + │ └── klikt pricing.html voor kosten + │ + └── verlaat → lead? [nee] → geen actie +``` + +**Succes:** bezoeker heeft minimaal 1 les gelezen + 1 quizvraag beantwoord. + +--- + +### UC-2: Registratie & account aanmaken +**Actor:** Geïnteresseerde bezoeker +**Doel:** Gratis account aanmaken voor voortgangsopslag + +``` +Bezoeker + │ + ├── klikt "Gratis account aanmaken" op homepage + │ ↓ + │ /register → 302 → /web/signup?redirect=/slides + │ │ + │ ├── Odoo signup-formulier (website 3) + │ │ Naam · E-mail · Wachtwoord + │ │ + │ ├── submit → Odoo maakt res.users aan + │ │ + │ ├── bevestigingsmail via atlasacademy.nl + │ │ (base_url = website 3 domein) + │ │ + │ └── redirect → /slides (ingelogd) + │ + └── succes: voortgang wordt opgeslagen per cursus +``` + +**Foutpaden:** +- E-mail al in gebruik → Odoo: "account bestaat al" +- Wachtwoord te kort → Odoo validatie +- Website 1 (corp) = b2b → signup geblokkeerd (correct) + +--- + +### UC-3: Inloggen (terugkerende student) +**Actor:** Bestaande gebruiker +**Doel:** Doorgaan met cursus + +``` +Terugkerende student + │ + ├── klikt "Inloggen" in nav van marketing-pagina + │ ↓ + │ /login → 302 → /web/login?redirect=/slides + │ │ + │ ├── Odoo login-formulier + │ │ + │ ├── submit → sessie cookie gezet + │ │ + │ └── redirect → /slides + │ └── cursus hervatten +``` + +--- + +### UC-4: Cursus volgen (hoofdflow) +**Actor:** Ingelogde student +**Doel:** Les lezen + kennischeck doen + +``` +[/slides] Cursuscatalogus + │ + └── klikt cursus → /slides/ + │ + ├── Cursuspagina: inhoudsopgave + │ + └── klikt les → /slides// + │ + ├── Theorie (HTML, ~300-500 woorden) + │ + └── Kennischeck (3 MC-vragen per les) + │ + ├── kiest antwoord → feedback (uitleg) + ├── alle correct → "Les voltooid" ✓ + └── voortgang opgeslagen in Odoo +``` + +--- + +### UC-5: Lead insturen (interesse formulier) +**Actor:** Bezoeker op marketingpagina +**Doel:** Interesse kenbaar maken (coaching / waitlist) + +``` +Bezoeker + │ + └── vult formulier in op coaching.html of index.html + │ + POST /academy-lead (JSON: {name, email, interest, source}) + │ + └── odoo_relay.py (atlas-01:7793) + │ + ├── maakt crm.lead aan in Odoo + │ + ├── stuurt notificatie e-mail (SMTP fallback) + │ + └── HTTP 200 → "Bedankt" bericht op pagina +``` + +--- + +## Swimlane diagram — Volledige gebruikerscyclus + +``` +STUDENT CADDY (atlasacademy.nl) ODOO (eLearning) CRM (Odoo) + │ │ │ │ + │── GET / ───────────────>│ │ │ + │<── 200 index.html ───────│ │ │ + │ │ │ │ + │── GET /slides ──────────>│── proxy ──────────────>│ │ + │<── 200 cursuscatalogus ──│<──────────────────────│ │ + │ │ │ │ + │── GET /slides/ ───>│── proxy ──────────────>│ │ + │<── 200 cursuspagina ─────│<──────────────────────│ │ + │ │ │ │ + │── GET /register ────────>│── 302 /web/signup ────>│ │ + │── POST signup ──────────>│── proxy ──────────────>│── nieuwe user ─────│ + │<── 302 /slides ──────────│<──────────────────────│ │ + │ │ │ │ + │── POST /academy-lead ───>│── proxy ──────────────>│ >│─ crm.lead + │<── 200 {ok:true} ────────│ │ │ + │ │ │ │ +``` + +--- + +## Flowchart — Auth beslissingsboom + +``` + Bezoeker wil cursus volgen + │ + ▼ + Heeft de user een sessie? + ┌─────────┴─────────┐ + Ja Nee + │ │ + ▼ ▼ + /slides (direct) /web/login + │ + ┌────────┴────────┐ + │ │ + Heeft account? Geen account + │ │ + ▼ ▼ + Inloggen /web/signup + │ │ + └────────┬────────┘ + │ + ▼ + /slides (ingelogd) + │ + Voortgang opgeslagen ✓ +``` + +--- + +## Actoren & rechten + +| Actor | Toegang | Auth | +|-------|---------|------| +| Anonieme bezoeker | Marketingpagina's, preview cursussen | Geen | +| Geregistreerde student | Volledige cursussen, voortgang | Odoo session | +| Operator (Chaib) | Odoo backend, alle content, CRM | Tailnet + Authentik SSO | +| Lead relay service | CRM leads aanmaken | XML-RPC app-user | diff --git a/static/bisl.html b/static/bisl.html new file mode 100644 index 0000000..64630c1 --- /dev/null +++ b/static/bisl.html @@ -0,0 +1,1191 @@ + + + + + + +BiSL Foundation — Atlas Academy + + + + + + + + + + + + + + +
    + + + + + +
    + +
    +
    📚
    +
    +
    + GRATIS + EXIN gecertificeerd +
    +

    BiSL Foundation

    +
    + 17 lessen + 97 oefenvragen + Sessienotities dag 2+3 + EXIN gecertificeerd +
    +
    +
    + + +
    + + +
    +
    +
    +

    ✅ Wat je leert

    +
      +
    • Het BiSL Framework en alle procesclusters
    • +
    • Gebruiksbeheer: ondersteuning, communicatie, IT-aansturing
    • +
    • Functionaliteitenbeheer: behoeftemanagement t/m transitie
    • +
    • Verbindende processen: wijzigingenbeheer & leveranciersmanagement
    • +
    • Sturende en richtinggevende processen
    • +
    • Examentips bij elke les — herkenbaar voor EXIN-vragen
    • +
    +
    +
    +

    🎯 Wie is dit voor

    +
      +
    • Kandidaten die het EXIN BiSL Foundation examen afleggen
    • +
    • Functioneel beheerders die hun kennis willen structureren
    • +
    • IT-professionals die de vraagzijde willen begrijpen
    • +
    • Deelnemers aan een BiSL-training (incl. sessienotities)
    • +
    • Zelfstudenten zonder trainingservaring
    • +
    +
    +
    + +
    + + +
    + +
    +
    + + +
    + + + +
    +
    +
    +

    Klaar voor het examen?

    +

    97 oefenvragen — direct feedback per vraag — EXIN-stijl

    +
    + 🎯 Ga naar de examentrainer → +
    +
    + + +
    +
    +
    +
    Dag 2
    +
    Dag 3
    +
    +
    +
    + + + 🎯 Examentrainer +
    +
    + +
    +
    +
    + + + + diff --git a/static/coaching.html b/static/coaching.html new file mode 100644 index 0000000..d798779 --- /dev/null +++ b/static/coaching.html @@ -0,0 +1,997 @@ + + + + + + + +Coaching — Atlas Academy + + + + + + + + + + + + + + + +
    +
    + + +
    + Chaib Aarab — Founder Atlas Corporation, ERP POS CRM +
    +
    + + +
    +
    + Coaching +
    +

    + Leer van iemand
    die het nu doet
    +

    +

    + Geen consultant met een theorie. Een ondernemer die dagelijks bouwt — AtlasPOS, automatisering, klanten, servers, sales. Coaching die aansluit op jouw realiteit. +

    + +
    + Tilburg + · + Chaib Aarab + · + chaib@atlascorporation.nl + · + 06 39 25 92 20 +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    + +
    + Chaib Aarab +
    +
    Bouchaib (Chaib) Aarab
    +
    Founder & IT Consultant — Atlas Corporation · Tilburg
    +
    +
    +
    + 8+ jaar ervaring + Efficy CRM consultant + AtlasPOS founder + Avans Hogeschool + Scalda ICT + Tilburg + AI & automatisering + Odoo / ERP +
    +

    + Ik begon als applicatieontwikkelaar, deed CRM-implementaties bij Efficy in ’s-Hertogenbosch, en bouw nu vanuit Tilburg AtlasPOS — een live SaaS-product. Naast het product draai ik de volledige IT-stack zelf: servers, automatisering, klantgesprekken, sales. Wat ik je leer, pas ik deze week nog toe. +

    + + Volg op LinkedIn → + +
    + +
    +
    +
    +
    2023
    +
    Atlas Corporation opgericht
    +
    +
    +
    SaaS
    +
    AtlasPOS live in productie
    +
    +
    +
    CRM
    +
    Efficy implementaties
    +
    +
    +
    8+
    +
    Jaar IT-ervaring
    +
    +
    +
    + “De meeste ondernemers leren van mensen die het beschrijven. Ik leer je van iemand die het bouwt — live, met echte klanten, echte servers en echte fouten.” +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    + +

    Wat ik aanbied

    +

    Drie formats, één coach. Kies wat past bij jouw fase.

    +
    + +
    + + +
    +
    👥
    +
    Starter
    +
    Groepscoaching
    +
    1× per maand · Zoom · 45 minuten
    +
    €20 / maand
    +
    +
      +
    • Vaste agenda: 10 min theorie → 25 min cases → 10 min Q&A
    • +
    • Opname beschikbaar na de sessie
    • +
    • Toegang tot Academy community
    • +
    • Leer van ondernemers in vergelijkbare fase
    • +
    + Word Starter-lid → +
    + + +
    +
    🎯
    +
    Pro
    +
    1-op-1 Sessie
    +
    30 min · maandelijks · jouw situatie centraal
    +
    €49 / maand
    +
    +
      +
    • Intake formulier vooraf — coach volledig voorbereid
    • +
    • Persoonlijk leerplan op basis van jouw fase
    • +
    • Directe feedback op jouw project of probleem
    • +
    • Toegang tot Chaibs netwerk waar relevant
    • +
    + Word Pro-lid → +
    + + +
    +
    🌟
    +
    Pro — Custom
    +
    Persoonlijk traject
    +
    Op maat · duur en intensiteit in overleg
    +
    Op aanvraag
    +
    +
      +
    • Diepgaand intake gesprek om jouw situatie te begrijpen
    • +
    • Maatwerk sessies: wekelijks, bi-weekly of ad hoc
    • +
    • Inclusief praktijkopdrachten en review
    • +
    • Directe bereikbaarheid via WhatsApp/mail
    • +
    + Vraag traject aan → +
    + +
    +
    +
    + + +
    +
    +
    + +

    Voor wie is dit?

    +

    Coaching is niet voor iedereen. Dit zijn de drie profielen waar ik het meeste impact heb.

    +
    + +
    + +
    +
    🚀
    +
    Startende ondernemer die wil leren hoe je een product lanceert
    +

    + Je hebt een idee of early-stage product maar weet niet hoe je van nul naar betalende klanten gaat. Ik leer je de weg die ik zelf ben gegaan met AtlasPOS: validatie, pricing, eerste sales, technische opzet. +

    + Product launchen +
    + +
    +
    ⚙️
    +
    ZZP-er die IT-processen wil automatiseren
    +

    + Je werkt solo maar verliest tijd aan repetitieve taken. Ik help je n8n, Odoo of andere tools inzetten zodat je meer kunt doen met minder manueel werk — zonder interne IT-afdeling. +

    + AI & automatisering +
    + +
    +
    📈
    +
    MKB die CRM/ERP wil implementeren zonder dure consultants
    +

    + Je bedrijf groeit maar de processen houden het tempo niet bij. Ik begeleid je bij het kiezen en inrichten van CRM of ERP — vanuit praktijkervaring bij Efficy en eigen Odoo-implementaties. +

    + CRM / ERP +
    + +
    +
    +
    + + +
    +
    +
    +
    + +

    Vraag een sessie aan

    +

    + Vul je gegevens in en Chaib neemt binnen 24 uur contact op. +

    +
    + +
    + ✓ Aanmelding ontvangen. Je hoort binnen 24 uur van Chaib. +
    + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    + +

    Geen spam. Enkel een persoonlijke reactie van Chaib binnen 24 uur.

    +
    +
    +
    +
    + + + + + + + diff --git a/static/esf.html b/static/esf.html new file mode 100644 index 0000000..67c3d97 --- /dev/null +++ b/static/esf.html @@ -0,0 +1,201 @@ + + + + +ESF+ Opleidingen — Atlas + + + + +
    +

    ESF+ Opleidingstraject

    +
    ITMG · gesubsidieerd via Europees Sociaal Fonds+ · 2026-06-02 02:43
    +
    +
    Voortgang3 van 7 afgerond
    +
    +
    +
    + +
    +
    afgerond
    +
    Basiskennis IT
    +
    28–29 mei 2026 · Bart de Best
    +
    6 onderwerpen →
    +
    +
    +
    afgerond
    +
    Effectief Communiceren
    +
    28–30 april 2026 · Arno Janssen
    +
    6 onderwerpen →
    +
    +
    +
    afgerond
    +
    BiSL Foundation
    +
    19–21 mei 2026 · Jan de Vries
    +
    open trainer →
    +
    +
    +
    aankomend
    +
    Workshop Werken in de IT-sector
    +
    16 juni 2026 · 15:00–17:00 · ITMG
    +
    4 onderwerpen →
    +
    +
    +
    aankomend
    +
    Praktijktraining Lean
    +
    23–25 juni 2026 · 18:30–21:30 · ITMG
    +
    7 onderwerpen →
    +
    +
    +
    aankomend
    +
    TMAP Quality for cross-functional teams
    +
    1,2,3,8,9 juli 2026 · 18:30–21:30 · ITMG
    +
    4 onderwerpen →
    +
    +
    +
    aankomend
    +
    Masterclass Effectieve Business Intelligence
    +
    5,6,7,12,13 augustus 2026 · 18:30–21:30 · ITMG
    +
    5 onderwerpen →
    +
    +
    +
    + +
    + +
    +
    afgerond
    +

    Basiskennis IT

    +
    28–29 mei 2026 · Trainer: Bart de Best
    +
    +
    ✓ authoritatieve syllabus
    2 avonden (18:30–21:30) · 28-29 mei 2026 (verplaatst vanaf 23-24 apr) · Trainer: Bart de Best · EXIN IT Fundamentals

    Leerdoel. Een brede basiskennis van IT opbouwen: hardware, software, netwerken, beveiliging en cloud.

    Officiële ITMG-cursuspagina →

    Het IT-landschap

    • ICT is ontstaan vanuit rekenmachines en mainframes; de pc-revolutie maakte IT toegankelijk voor iedereen.
    • Softwaretypen: systeemsoftware (OS), middleware en applicatiesoftware — elk met een eigen rol.
    • Firmware zit tussen hardware en software in: vaste instructies opgeslagen in een chip (bijv. BIOS/UEFI).
    • Applicaties communiceren via API's, protocollen en middleware met andere applicaties en systemen.
    Firmware: Vaste software ingebakken in hardware (bijv. BIOS) — stuurt het apparaat aan voordat het OS laadt.
    API: Application Programming Interface — gestandaardiseerde koppeling waarmee applicaties met elkaar praten.
    Tip Onthoud de drielaag: hardware → firmware → software. Firmware is de brug tussen de twee.

    Software ontwikkelen

    • Softwareontwikkeling doorloopt fasen: analyse, ontwerp, realisatie, testen en beheer (SDLC).
    • Methodieken: Waterval (sequentieel), Agile/Scrum (iteratief), DevOps (doorlopend).
    • Testen is een eigen discipline: unit-tests, integratietests en acceptatietests bewaken kwaliteit.
    • Apps (mobiel, single-purpose) verschillen van enterprise-applicaties in architectuur en levenscyclus.
    SDLC: Software Development Life Cycle — de volledige levenscyclus van een softwareproduct.
    Agile: Iteratieve ontwikkelaanpak met korte sprints, continue feedback en aanpassing.
    Tip Waterval = plan alles vooraf. Agile = bouw stap voor stap, pas aan op feedback.

    IT-beheer — het drievoudig model

    • IT-beheer bestaat uit drie lagen: technisch beheer, applicatiebeheer en functioneel beheer.
    • ITIL is het meestgebruikte beheermodel: definieert processen voor incident-, probleem- en wijzigingsbeheer.
    • BiSL richt zich op functioneel beheer: de gebruikerskant van informatievoorziening.
    • Demand (wat wil de organisatie) vs. Supply (wat levert IT) — de kloof overbruggen is kern van beheer.
    ITIL: Information Technology Infrastructure Library — best practices voor IT-servicemanagement.
    BiSL: Business Information Services Library — framework voor functioneel beheer en informatiemanagement.
    Functioneel beheer: Beheer vanuit de gebruikersorganisatie: eisen stellen aan en regie voeren over IT.
    Tip ITIL = IT-kant, BiSL = gebruikerskant. Samen dekken ze de volledige beheerketen.

    Hosting, housing en on-premise

    • On-premise: servers staan fysiek bij de organisatie zelf — volledige controle, hoge eigen kosten.
    • Housing: de organisatie bezit de servers maar plaatst ze in een extern datacenter.
    • Hosting: de aanbieder levert én beheert de servers — minder controle, minder beheerslast.
    • Outsourcing, insourcing en near sourcing bepalen waar IT-taken en -personeel belegd zijn.
    On-premise: IT-infrastructuur die fysiek binnen de eigen organisatie staat en beheerd wordt.
    Hosting: Externe partij levert én beheert de server- en netwerkcapaciteit.
    Near sourcing: Uitbesteden aan een partij in een nabijgelegen regio/land.
    Tip Beslisregel: hoe meer controle je wilt, hoe meer je on-premise gaat — maar hoe hoger de beheerkosten.

    Actuele IT-trends

    • Artificial Intelligence (AI): systemen die taken uitvoeren waarvoor normaal menselijke intelligentie nodig is.
    • Machine learning: AI die patronen leert uit data zonder expliciet geprogrammeerde regels.
    • Internet of Things (IoT): fysieke apparaten (sensoren, machines) die via het internet zijn verbonden.
    • Robotisering en digitalisering automatiseren repetitieve processen en veranderen functieprofielen.
    Artificial Intelligence (AI): Technologie die menselijke denkprocessen nabootst — redeneren, leren, beslissen.
    Machine learning: AI-techniek waarbij een algoritme leert van voorbeelddata zonder expliciete regels.
    IoT: Internet of Things — netwerk van 'slimme' fysieke objecten met sensoren en connectiviteit.
    Tip AI = het doel, machine learning = een methode om dat doel te bereiken.

    Programmeertalen en softwarearchitectuur

    • Laagniveau-talen (Assembly) geven directe hardware-controle; hoogniveau-talen (Python, Java) zijn leesbaar voor mensen.
    • Gecompileerde talen (C, Java) worden voor uitvoering omgezet naar machinecode; geïnterpreteerde talen (Python) worden regel voor regel uitgevoerd.
    • Gangbare paradigma's: procedureel, object-georiënteerd (OOP) en functioneel programmeren.
    • Softwarearchitectuur beschrijft hoe componenten samenwerken: monoliet vs. microservices vs. cloud-native.
    Compiler: Programma dat broncode vertaalt naar uitvoerbare machinecode.
    OOP: Object-Oriented Programming — code georganiseerd in objecten met eigenschappen en gedrag.
    Microservices: Architectuur waarbij een applicatie bestaat uit kleine, onafhankelijk inzetbare diensten.
    Tip Python = beginner-friendly, geïnterpreteerd. Java = veel gebruikt in enterprise, gecompileerd naar bytecode.
    +
    +
    + +
    +
    afgerond
    +

    Effectief Communiceren

    +
    28–30 april 2026 · Trainer: Arno Janssen
    +
    +
    ✓ authoritatieve syllabus
    3 avonden · 28-30 april 2026 · Trainer: Arno Janssen · geen examen

    Leerdoel. Effectiever communiceren door actief luisteren, feedback en gespreks­technieken.

    Officiële ITMG-cursuspagina →

    Inleiding communicatie en contact maken

    • Communicatie is meer dan woorden: zender, ontvanger, boodschap en ruis bepalen samen het effect.
    • Contact maken is de eerste stap: aandacht, afstemming en het creëren van een veilige gespreksruimte.
    • Onderlinge beïnvloeding: hoe gedrag van de ander jouw communicatie stuurt en vice versa.
    Ruis: Alles wat de boodschap tussen zender en ontvanger verstoort — fysiek, semantisch of psychologisch.
    Onderlinge beïnvloeding: Het principe dat communicatiestijlen op elkaar inwerken en elkaars gedrag aansturen.
    Tip Goede communicatie begint niet met spreken maar met aansluiten — sluit eerst aan op de ander voordat je je boodschap overbrengt.

    Communicatiestijlen en eigen voorkeuren

    • Er zijn meerdere communicatiestijlen (bijv. analytisch, sturend, expressief, meegaand) — geen is beter.
    • Elke stijl heeft sterke punten en valkuilen; inzicht in je eigen voorkeursstijl voorkomt blinde vlekken.
    • Flexibiliteit: de effectiefste communicators kunnen meerdere stijlen bewust inzetten.
    Communicatiestijl: Karakteristiek patroon in hoe iemand informatie overbrengt en reageert op anderen.
    Valkuil: Automatische neiging die in bepaalde situaties juist contraproductief werkt.
    Tip Ken je eigen dominante stijl — dan zie je ook waarom je botst met mensen die een andere stijl hebben.

    Waarnemen en interpreteren

    • Waarnemen en interpreteren zijn twee aparte stappen: feit vs. mening/oordeel scheiden is cruciaal.
    • Referentiekaders en aannames kleuren hoe je gedrag van anderen interpreteert.
    • Bewust waarnemen zonder direct te oordelen verbetert de kwaliteit van gesprekken.
    Referentiekader: Het geheel van ervaringen, waarden en overtuigingen waardoor iemand de wereld filtert.
    Interpretatie: De betekenis die je toekent aan een waarneming — subjectief en beïnvloedbaar.
    Tip Formuleer: "Ik zie / hoor X" (waarneming) en "Ik denk dat dit betekent Y" (interpretatie) — houd ze apart.

    Feedback geven en ontvangen

    • Effectieve feedback is specifiek, gedragsgericht en tijdig — geen aanslagen op de persoon.
    • Feedback ontvangen vraagt openheid: luister volledig, vraag door en reageer niet defensief.
    • Feedbackcultuur: wederzijdse feedback versterkt samenwerking en persoonlijke groei.
    Gedragsgerichte feedback: Feedback gericht op zichtbaar gedrag, niet op karakter of intentie.
    Defensieve reactie: Automatisch zichzelf beschermen bij kritiek — blokkeert leren en dialoog.
    Tip Gebruik bij feedback de ik-boodschap: "Als jij X doet, merk ik Y, en dat heeft voor mij Z als gevolg."

    Omgaan met weerstand en conflicten

    • Weerstand is informatie: het signaleert een onvervulde behoefte of een niet-gehoorde zorg.
    • Technieken: meebewegen, benoemen van weerstand, en het stellen van open vragen.
    • Conflicten kunnen constructief zijn als ze bespreekbaar worden gemaakt en niet escaleren.
    Weerstand: Reactie van een gesprekspartner die aangeeft dat de boodschap niet landt of bedreigend voelt.
    Meebewegen: Techniek waarbij je de weerstand erkent en er niet tegenin gaat, waardoor spanning daalt.
    Tip Ga niet harder duwen bij weerstand — benoem het: "Ik merk dat je hier anders over denkt, wat speelt er voor jou?"

    Zelfherstellend vermogen en mondelinge communicatie in de praktijk

    • Zelfherstellend vermogen: structuur en methodieken helpen je terugkeren naar effectief gedrag na een misstap.
    • Mondelinge communicatie in ICT-omgevingen: heldere taal tegenover collega's, leidinggevenden, leveranciers en klanten.
    • Oefen actief met alternatieve handelingswijzen — inzicht alleen verandert nog geen gedrag.
    Zelfherstellend vermogen: Vermogen om na een communicatieve misstap terug te keren naar effectief en bewust gedrag.
    Handelingswijze: Concrete gedragsalternatieven die je bewust kunt inzetten in lastige communicatiesituaties.
    Tip Inzicht is stap 1, oefenen is stap 2 — zonder oefening verandert je gedrag in de praktijk niet.
    +
    +
    + +
    +
    afgerond
    +

    BiSL Foundation

    +
    19–21 mei 2026 · Trainer: Jan de Vries
    +
    +

    Deze training heeft een eigen interactieve trainer: 82 oefenvragen, lesstof en sessienotities.

    Open volledige examentrainer → +
    +
    + +
    +
    aankomend
    +

    Workshop Werken in de IT-sector

    +
    16 juni 2026 · 15:00–17:00 · Trainer: ITMG
    +
    +
    ✓ authoritatieve syllabus
    1 dagdeel · gratis voor ESF-deelnemers · geen examen · geen voorkennis

    Leerdoel. Je vaardigheden en competenties beter benutten en je sollicitatievaardigheden verbeteren, met insider-view op recruitment in de IT.

    Officiële ITMG-cursuspagina →

    Insider-view recruitment in IT

    • Hoe werving & selectie binnen de IT-sector werkt.
    • Hoe je daar als kandidaat je voordeel mee doet.
    Recruitment: Werving en selectie van kandidaten door werkgevers/bureaus
    Tip Verplaats je in de recruiter: wat zoekt die in de eerste 10 seconden?

    Pitch & voorstellen

    • Een korte, krachtige persoonlijke pitch maken.
    • Jezelf overtuigend introduceren bij sollicitatiemomenten.
    Elevator pitch: Korte zelfintroductie van ~30-60 seconden
    Tip Oefen je pitch hardop — 30 seconden, kernwaarde + wat je zoekt.

    Het sollicitatiegesprek

    • Veelvoorkomende vragen en hoe je je voorbereidt.
    • Praktische tips en coaching voor meer zelfvertrouwen.
    STAR-methode: Situatie-Taak-Actie-Resultaat: structuur om gedragsvragen te beantwoorden
    Tip Beantwoord gedragsvragen met STAR — concreet en resultaatgericht.

    CV & LinkedIn-profiel

    • Een sterk, gericht CV opstellen.
    • Je LinkedIn-profiel optimaliseren voor de IT-arbeidsmarkt.
    LinkedIn: Professioneel netwerk waar IT-recruiters actief zoeken
    Tip Stem CV én LinkedIn af op de functie — recruiters checken beide.
    +
    +
    + +
    +
    aankomend
    +

    Praktijktraining Lean

    +
    23–25 juni 2026 · 18:30–21:30 · Trainer: ITMG
    +
    +
    ✓ authoritatieve syllabus
    2 dagen · €1.450 · examen €250 (optioneel) · 2–4u zelfstudie/dag · geen voorkennis

    Leerdoel. Van enige afstand naar je eigen werk leren kijken en laaghangend verbeter-fruit herkennen en plukken met 10 Lean-gereedschappen.

    Officiële ITMG-cursuspagina →
    📅 Voorbereiding (ITMG)
    3 avonden · 23–25 juni 2026 · 18:30–21:30

    Avond 1: hoofdstuk 1 t/m 5  ·  Avond 2: hoofdstuk 6 t/m 11. Elke avond = theorie (met examen-relevante onderwerpen) afgewisseld met (groeps)oefeningen, vragen en een quiz per onderwerp.

    Doe vooraf Neem in de online leeromgeving de slides met rood kader door en bereid de slides met groen kader alvast voor.

    Voice of the Customer (VOC)

    • Begrijp wie de klant is en wat die écht verwacht van het proces.
    • Vertaal klantbehoeften naar meetbare eisen aan je werk.
    VOC: Voice of the Customer — de stem/verwachting van de klant als startpunt voor verbeteren
    Tip Lean begint altijd bij klantwaarde: wat is de klant bereid voor te betalen?

    Value Stream Mapping (VSM)

    • Breng de hele waardestroom van een proces visueel in kaart.
    • Maak waarde-toevoegende vs niet-waarde-toevoegende stappen zichtbaar.
    Value Stream Mapping: Visuele techniek die de stappen, doorlooptijd en verspilling in een proces toont
    Tip Onderscheid value-add van non-value-add (maar noodzakelijk) en pure verspilling.

    Muda, Muri en Mura — de 3 verspillingen

    • Muda = verspilling (8 soorten: o.a. wachten, transport, voorraad, overproductie).
    • Muri = overbelasting van mens/machine; Mura = onevenwichtigheid/variatie.
    Muda: Activiteit die geen waarde toevoegt voor de klant
    Muri: Overbelasting van mensen of middelen
    Mura: Onregelmatigheid/variatie in het proces
    Tip Ezelsbruggetje 3M: Muda (verspilling), Muri (overbelasting), Mura (variatie).

    Impact/Effort Matrix

    • Prioriteer verbeterideeën op impact versus benodigde inspanning.
    • Begin met quick wins: hoge impact, lage inspanning.
    Impact/Effort Matrix: 2x2-matrix om verbeterideeën te prioriteren
    Tip Quick wins eerst — dat is het 'laaghangend fruit' uit het leerdoel.

    DMAIC

    • Gestructureerde verbeteraanpak: Define, Measure, Analyze, Improve, Control.
    • Borg verbeteringen in de Control-fase zodat ze niet terugvallen.
    DMAIC: Define-Measure-Analyze-Improve-Control — Lean/Six Sigma verbetercyclus
    Tip DMAIC = de ruggengraat van elk verbeterproject. Ken de 5 fasen op volgorde.

    Ishikawa & grondoorzaakanalyse

    • Visgraatdiagram om oorzaken van een probleem te ordenen.
    • Combineer met '5x Waarom' om de werkelijke grondoorzaak te vinden.
    Ishikawa-diagram: Visgraatdiagram dat oorzaken groepeert (mens, methode, machine, materiaal...)
    Tip Behandel grondoorzaken, niet symptomen — anders komt het probleem terug.

    Kanban, 5S, Poka Yoke & Antifragiliteit

    • Kanban: werk visualiseren en flow/WIP beheersen.
    • 5S: werkplek organiseren (Sorteren, Schikken, Schoonmaken, Standaardiseren, Standhouden).
    • Poka Yoke: fouten voorkomen of onmogelijk maken; Antifragiliteit: sterker worden van variatie.
    Kanban: Visueel systeem om werk en work-in-progress te beheersen
    5S: Sorteren, Schikken, Schoonmaken, Standaardiseren, Standhouden
    Poka Yoke: Foutpreventie: het proces zo ontwerpen dat fouten niet kunnen
    Tip 5S onthouden via de 5 Nederlandse S-en.
    +
    +
    + +
    +
    aankomend
    +

    TMAP Quality for cross-functional teams

    +
    1,2,3,8,9 juli 2026 · 18:30–21:30 · Trainer: ITMG
    +
    +
    ✓ authoritatieve syllabus
    3 dagen · examen inbegrepen · voertaal NL · TMAP = NL-standaard voor testorganisatie

    Leerdoel. Testen toepassen in cross-functionele (Agile/DevOps) teams volgens TMAP en 'built-in quality' realiseren.

    Officiële ITMG-cursuspagina →
    E-book Verplicht studiemateriaal: “Quality for DevOps teams” — vouchercode ontvangen via ITMG (16 jun), gebruikt tijdens de training.

    Dag 1 — Fundamenten kwaliteit & testen

    • Wat is softwarekwaliteit en waarom cruciaal in Agile/DevOps.
    • Rol van testen in cross-functionele teams; TMAP-kernprincipes.
    • Testsoorten, teststrategieën en risicogebaseerd testen.
    TMAP: Test Management Approach — de Nederlandse standaard voor testen/kwaliteit
    Risicogebaseerd testen: Testinspanning richten op de grootste risico's
    Tip TMAP = vraagzijde van kwaliteit, ingebouwd in het team i.p.v. losse testfase.

    Testen in Scrum, SAFe & DevOps

    • Hoe testen past binnen Scrum, SAFe en DevOps.
    • CI/CD en Continuous Testing voor geautomatiseerde kwaliteitsbewaking.
    • Samenwerking en verantwoordelijkheden in het team.
    Continuous Testing: Geautomatiseerd testen geïntegreerd in de CI/CD-pijplijn
    Built-in quality: Kwaliteit ingebouwd in elke fase i.p.v. achteraf getest
    Tip In DevOps test je continu — kwaliteit is van het hele team, niet één tester.

    Dag 2 — Testtechnieken & automatisering

    • Testontwerp-methodologie; exploratory vs script-based testing.
    • Risicobeheer in testplanning; wanneer wel/niet automatiseren.
    • Testtools: Selenium, Cypress, Playwright; balans handmatig/automatisch.
    Exploratory testing: Gelijktijdig leren, ontwerpen en uitvoeren van tests zonder vooraf script
    CI/CD: Continuous Integration / Continuous Delivery
    Tip Niet alles automatiseren — kies op basis van risico en herhaalfrequentie.

    Dag 3 — Kwaliteitscultuur & testmanagement

    • Kwaliteitscultuur opbouwen; continuous improvement en feedback.
    • Samenwerking met stakeholders; teststrategie in Agile.
    • Examenvoorbereiding TMAP QCFT + persoonlijk actieplan.
    Kwaliteitscultuur: Gedeelde verantwoordelijkheid voor kwaliteit binnen het hele team
    Tip Het examen (QCFT) zit in de prijs — voorbeeldvragen komen op dag 3 aan bod.
    +
    +
    + +
    +
    aankomend
    +

    Masterclass Effectieve Business Intelligence

    +
    5,6,7,12,13 augustus 2026 · 18:30–21:30 · Trainer: ITMG
    +
    +
    ✓ authoritatieve syllabus
    3 dagen / 5 avonden · €2.250 · examen €250 · hands-on met SQL

    Leerdoel. Beschikbare data binnen de organisatie omzetten in kennis om onderbouwde beslissingen te nemen.

    Officiële ITMG-cursuspagina →

    Inleiding BI

    • Werkveld en definities; self-service reporting en dashboarding.
    • KPI's inventariseren; datamodellen en metadata voor BI.
    Business Intelligence: Data omzetten in inzicht voor betere besluitvorming
    KPI: Key Performance Indicator — meetbare prestatie-indicator
    Tip BI = van data → informatie → kennis → beslissing.

    SQL voor BI

    • SELECT-statements als basis van datavragen.
    • Filteren (WHERE), kolomselectie en berekende kolommen.
    SELECT: SQL-commando om gegevens uit een tabel op te vragen
    Berekende kolom: Kolom die wordt afgeleid via een formule/expressie
    Tip Oefen SELECT/WHERE alvast — dit is de kern van dag 1-2.

    Data ontsluiten — joins & aggregatie

    • Sleutels en joins om tabellen te combineren; complexe queries.
    • Booleaanse algebra, aggregatiefuncties (SUM, COUNT, AVG) en KPI-relaties.
    • Dashboards samenstellen; demonstratie van query-tools.
    Join: Tabellen koppelen op een gedeelde sleutel
    Aggregatie: Gegevens samenvatten (som, gemiddelde, telling)
    Tip Een join koppelt rijen; een aggregatie vat ze samen — verwar ze niet.

    Bronnen ontsluiten & ETL

    • Externe bronnen, open datasets, API's en bestandsimport.
    • Data-mappings en ETL; metadata-beheer; demonstratie ETL-tools.
    ETL: Extract-Transform-Load — data uit bronnen halen, bewerken en laden in een DWH
    Tip ETL is de motor onder elk datawarehouse.

    Datawarehousing & vervolgstappen

    • DWH-architectuur, datamarts en dimensionele datamodellen.
    • Drill-down en roll-up; dimensioneel modelontwerp.
    • Volgende stap: statistiek, voorspellingsmodellen, data science, NoSQL (MongoDB).
    Datawarehouse: Centrale, geïntegreerde database met historische data voor analyse
    Dimensioneel model: Ster-/sneeuwvlokmodel met feiten en dimensies voor BI
    Tip Datamart = onderwerp-specifiek deel van het datawarehouse.
    +
    + + + + \ No newline at end of file diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..32bb808 --- /dev/null +++ b/static/index.html @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + +Atlas Academy — Online leerplatform + + + + + + + + + + + + + +
    +
    +
    + + + + + + + + + + + Atlas Academy +
    +
    + +
    +
    Nu live
    +
    + +

    Atlas Academy

    +

    Praktijkcursussen voor ondernemers die bouwen.
    Theorie én kennischecks — direct toegang tot 9 cursussen.

    + +
    +

    Begin vandaag

    +

    Maak gratis een account aan en start meteen, of bekijk eerst het cursusaanbod.

    + +
    + + + +
    + +
    + Al een account? Inloggen → +   |   + Nieuw account +
    + + + + \ No newline at end of file diff --git a/static/leerpad.html b/static/leerpad.html new file mode 100644 index 0000000..486f9b8 --- /dev/null +++ b/static/leerpad.html @@ -0,0 +1,1371 @@ + + + + + + + +12-weken leerpad — Atlas Academy + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    + + 12 weken · 25 modules · 6 fases +
    +

    🗺️ Het 12-weken leerpad

    +

    Gestructureerde volgorde door alle 25 modules — van fundament tot funding.

    +
    +
    +
    + + +
    +
    +
    + Jouw voortgang + 0% +
    +
    +
    +
    +
    +
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    +
    +

    + 0 van 6 fases afgerond — klik een fase aan om hem te markeren +

    +
    +
    + + +
    +
    + +
    + +

    Volg de route, of kies jouw instapmoment

    +

    Elke fase bouwt voort op de vorige. Klaar met een fase? Klik hem aan om je voortgang bij te houden.

    +
    + + +
    +
    +
    + + +
    +
    1
    +
    +
    📅 Week 1–2
    +
    💡 Fundament
    + + +
    +
    + + +
    +
    2
    +
    +
    📅 Week 3–4
    +
    🔐 Tech & AI basis
    + + +
    +
    + + +
    +
    3
    +
    +
    📅 Week 5–6
    +
    📣 Sales & Marketing
    + + +
    +
    + + +
    +
    4
    +
    +
    📅 Week 7–8
    +
    💶 Geld & Juridisch
    + + +
    +
    + + +
    +
    5
    +
    +
    📅 Week 9–10
    +
    🤖 AI & Automatisering
    + + +
    +
    + + +
    +
    6
    +
    +
    📅 Week 11–12
    +
    🚀 Groei & Funding
    + + +
    +
    + +
    +
    + + +
    +
    📚
    +
    +
    Bonus track — parallel
    +
    BiSL Foundation
    +

    Doe dit parallel in week 3–8. Functioneel beheer en IT-procesontwerp voor ondernemers die met leveranciers of IT-systemen werken. Preview van 3 modules gratis beschikbaar.

    +
    + 97 oefenvragen + 17 lessen + Week 3–8 + Gratis preview +
    + Open BiSL Foundation → +
    +
    + +
    +
    + + +
    +
    +
    +
    +

    Klaar om te beginnen?

    +

    Start bij fase 1 of spring in op het punt dat het meest urgent is. Alles is direct toepasbaar.

    + +
    +
    + + + + + + + diff --git a/static/over.html b/static/over.html new file mode 100644 index 0000000..07e4f96 --- /dev/null +++ b/static/over.html @@ -0,0 +1,487 @@ + + + + + + + + + + + + +Chaib Aarab — Over mij | Atlas Academy + + + + + + + +
    +
    +
    + Bouchaib Aarab — Business IT Consultant & Founder +
    +
    +
    +
    Over mij
    +

    Bouchaib Aarab(Chaib)

    +

    Business IT Consultant · Founder · Tilburg

    +

    Business IT-consultant en implementatiespecialist. Ik help organisaties bij het selecteren, implementeren en optimaliseren van bedrijfssoftware en IT-processen op het snijvlak van operatie en software.

    + +
    + 🇳🇱 Nederlands + 🇬🇧 English + 🇫🇷 Français +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Chaib Aarab — ERP POS CRM Founder +
    +
    +
    Bouchaib Aarab — actief als founder & consultant, Tilburg 2026
    +
    +
    +
    +
    + +

    Van ICT-student tot SaaS-founder

    +

    Ik ben opgegroeid met een fascinatie voor hoe dingen werken. Niet alleen technisch — maar hoe processen, mensen en systemen samen een organisatie vormen. Dat heeft me geleid van een ICT-opleiding aan Scalda in Terneuzen, via projectmanagement in de websitebouw, naar CRM-implementaties voor grote bedrijven, en uiteindelijk naar mijn eigen onderneming.

    +

    Tijdens mijn tijd als voorzitter van Innovision Solutions stuurde ik een studentenbedrijf van 200+ studenten aan. We haalden projecten uit het bedrijfsleven binnen, we presenteerden op beurzen en uiteindelijk zelfs voor het landelijke onderwijsorganisatie in Nederland. Het was de eerste keer dat ik begreep hoe krachtig het is als mensen en technologie goed zijn georganiseerd.

    +

    Bij Efficy deed ik CRM-implementaties van A tot Z. Van intake en requirements tot configuratie, training en oplevering. Ik leerde hoe je een klantproces vertaalt naar een werkend systeem — en hoe je change management doet zonder dat mensen afhaken. Die kennis gebruik ik elke dag nog.

    +

    In 2023 richtte ik Atlas Corporation op. Niet als consultant die zijn uren verkoopt, maar als ondernemer die producten bouwt. AtlasPOS is mijn eerste SaaS: een kassasysteem voor Tilburgse horecazaken voor €79 per maand. Atlas Academy is de bundeling van alles wat ik heb geleerd — voor ondernemers die zelf willen bouwen.

    +
    +
    +
    +
    + +
    +
    +
    + +

    Mijlpalen

    +

    Een decennium bouwen, leren en opstarten.

    +
    +
    +
    2014
    ICT studie gestart
    Scalda, Terneuzen — Applicatie- en mediaontwikkelaar
    +
    2016
    Project Manager
    Innovision Solutions — eerste ervaring met SCRUM en klantaansturing
    +
    2017
    Chairman Innovision Solutions
    200+ studenten aangestuurd · Presentatie landelijke onderwijsorganisatie, Nederland · open dagen & beurzen
    +
    2017
    Support Engineer → Project Manager
    Dutchwebdesign / Hybridd, Breda — front/back-end development, gepromoveerd tijdens contract
    +
    2018
    Business Administration
    Avans Hogeschool, 's-Hertogenbosch — studie niet afgerond — gekozen voor eigen bedrijf
    +
    2022
    CRM Implementation Consultant
    Efficy, 's-Hertogenbosch — full-cycle: intake → requirements → config → training → delivery
    +
    2023
    Atlas Works opgericht
    IT consultancy voor MKB, Tilburg — eerste zelfstandige klanten, Odoo & procesoptimalisatie
    +
    2024
    AtlasPOS gelanceerd
    SaaS kassasysteem €79/maand — eerste betalende klanten in Tilburgse horeca
    +
    2025
    Atlas Corporation officieel
    Holding voor alle Atlas-producten — fleet management, AI-stack, n8n automatisering live
    +
    2026
    Atlas Academy live
    Leerplatform voor ondernemers — kennis van de praktijk, niet de theorie
    +
    +
    +
    + +
    + +
    + +
    +
    +
    + +

    Vaardigheden

    +

    Opgebouwd over 9 jaar op het snijvlak van business en technologie.

    +
    +
    +
    +
    +
    Technisch
    +
    • Odoo / ERP implementatie
    • n8n automatisering
    • AI (Ollama / RAG / LLM)
    • Web development
    • Linux / VPS beheer
    • MeshCentral fleet management
    • Security (OWASP)
    +
    +
    +
    📊
    +
    Business
    +
    • CRM implementatie
    • Procesoptimalisatie
    • Requirements analyse
    • Stakeholdermanagement
    • Projectmanagement (SCRUM)
    • Change management
    • SaaS product development
    +
    +
    +
    🧠
    +
    Persoonlijk
    +
    • Analytisch denken
    • Probleemoplossend
    • Klantgericht
    • Communicatief sterk
    • Zelfstandig en gedisciplineerd
    • Snel leren
    • Ondernemende mindset
    +
    +
    +
    +
    + +
    +
    +
    +
    + +

    Volg mijn werk

    +

    Ik deel inzichten over ondernemen, AI en MKB-technologie.

    +
    +
    +
    + +
    + +
    + +
    +
    +
    + + +
    +
    +
    + +

    Opleiding

    +
    +
    +
    +
    🏛
    +
    +
    2018 – 2021
    +
    Avans Hogeschool
    +
    Business Administration — studie niet afgerond — gekozen voor eigen bedrijf
    +
    's-Hertogenbosch, Nederland
    +
    +
    +
    +
    💻
    +
    +
    2014 – 2018
    +
    Scalda
    +
    ICT: Applicatie- en mediaontwikkelaar — MBO niveau 4, afgerond
    +
    Terneuzen, Nederland
    +
    +
    +
    +
    +
    + +
    +
    +
    + +

    Wil je samenwerken of heb je een vraag?

    +

    Neem direct contact op — ik reageer persoonlijk.

    + +
    +
    +
    + + + + + + \ No newline at end of file diff --git a/static/pricing.html b/static/pricing.html new file mode 100644 index 0000000..9010d82 --- /dev/null +++ b/static/pricing.html @@ -0,0 +1,964 @@ + + + + + + + +Prijzen — Atlas Academy + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    Prijzen
    +

    Transparante prijzen.
    Geen verborgen kosten.

    +

    Kies het plan dat past bij jouw fase. Maandelijks opzegbaar — geen jaarcontract vereist.

    +
    +
    +
    + + +
    +
    + +
    + + +
    +
    Free
    +
    + Gratis +
    +

    Begin zonder risico. Kijk of de aanpak bij je past.

    + +
      +
    • 3 modules gratis
    • +
    • BiSL Foundation preview (lessen 1–3)
    • +
    • Geen credit card nodig
    • +
    + +
      +
    • BiSL les 1–3
    • +
    • Cursuscatalogus
    • +
    • Leerpad inzien
    • +
    • Groepscoaching
    • +
    • Alle modules
    • +
    • 1-op-1 sessie
    • +
    + + + Start gratis + +
    + + + + + +
    +
    Pro
    +
    + €49 + / maand +
    +

    Voor ondernemers die sneller willen groeien met persoonlijke begeleiding.

    + +
      +
    • Alles uit Starter
    • +
    • 1-op-1 sessie 30 min/maand (met Chaib)
    • +
    • Persoonlijk leertraject
    • +
    • Prioriteit e-mail support
    • +
    • Early access nieuwe cursussen
    • +
    + +
      +
    • Alles uit Starter
    • +
    • 1-op-1 sessie
    • +
    • Persoonlijk traject
    • +
    • Prioriteit support
    • +
    • Early access nieuwe cursussen
    • +
    + + + Word Pro → + +
    + +
    + + +
    + Alle betalingen via factuur of automatische incasso. + Maandelijks opzegbaar — geen verborgen kosten, geen jaarcontract vereist. +
    + +
    +
    + + +
    +
    +
    + +

    Alles over onze prijzen

    +
    +
    + +
    + +
    + Ja. Bij jaarlijkse betaling ontvang je twee maanden gratis — effectief betaal je voor 10 maanden in plaats van 12. Vraag het jaarplan aan via info@atlascorporation.nl en wij sturen je een offerte. +
    +
    + +
    + +
    + We hanteren geen automatische restitutie, maar denken altijd mee. Als je binnen de eerste 14 dagen aangeeft dat de inhoud niet aansluit bij je verwachting, nemen we het op. Stuur een mail naar info@atlascorporation.nl met een korte toelichting. +
    +
    + +
    + +
    + Ja. Vanaf 3 medewerkers bieden we een maatwerkprijs. Denk aan een gezamenlijk leerpad, groepscoaching op maat en één centrale facturering. Neem contact op via info@atlascorporation.nl voor een offerte op maat. +
    +
    + +
    + +
    + Studenten en BBZ-deelnemers komen in aanmerking voor een gereduceerd tarief. Stuur een bewijs van inschrijving of een BBZ-toekenning mee in je mail en we regelen een aangepast abonnement. We geloven dat prijs geen drempel mag zijn voor praktische kennis. +
    +
    + +
    + +
    + Stuur een e-mail naar info@atlascorporation.nl vóór de volgende factuurdatum. Geen formulieren, geen gedoe. Je behoudt toegang tot het einde van de lopende betaalperiode. +
    +
    + +
    +
    +
    + + + + + + + diff --git a/static/shop.html b/static/shop.html new file mode 100644 index 0000000..a2cb513 --- /dev/null +++ b/static/shop.html @@ -0,0 +1,204 @@ + + + + + + + + + + + +Shop — Atlas Academy + + + + + + +
    +

    Atlas Hardware

    +

    De machines waar wij zelf op draaien

    +

    Refurbished zakelijke laptops, desktops, monitoren en kassasystemen. Getest, met 24 maanden garantie. Bestellen en betalen gaat veilig via atlasworks.nl.

    +
    +
    +
    Uitgebreid getest
    +
    🔒 24 maanden garantie
    +
    📍 Afhalen in Tilburg
    +
    💳 Veilig betalen via iDEAL
    +
    +
    +
    + + + + + + + +
    +

    +
    Producten laden…
    + +
    +
    + +

    Geen verrassingen — wel werkende hardware

    +
    +
    🔍
    Volledig getest
    Elke machine doorloopt een meerpunts-checklist: scherm, toetsenbord, batterij, SSD, WiFi, poorten — alles werkt of we leveren hem niet.
    +
    🛠️
    24 maanden garantie
    Gaat er iets stuk? Breng hem langs in Tilburg en we fixen het of ruilen om. Geen gezeur met retourlabels of callcenters.
    +
    💳
    Zakelijke factuur
    Netjes op naam van je bedrijf, BTW verrekenbaar. Veilig afrekenen via iDEAL op atlasworks.nl — geen marktplaats-gedoe.
    +
    +
    +
    +

    Vraag of advies nodig?

    +

    Twijfel je welke machine bij je past? Stuur een mail en we denken met je mee — afhalen in Tilburg of verzenden kan ook.

    + Stel je vraag → +
    + + + +