- Kevin Veen-Birkenbach Logo
-
-
-
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..79ed49a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+app/static/logos/*
\ No newline at end of file
diff --git a/512x512/logo.png b/512x512/logo.png
deleted file mode 100644
index 6e8f472..0000000
Binary files a/512x512/logo.png and /dev/null differ
diff --git a/512x512/logo_agile-coach.png b/512x512/logo_agile-coach.png
deleted file mode 100644
index ade80da..0000000
Binary files a/512x512/logo_agile-coach.png and /dev/null differ
diff --git a/512x512/logo_cybermaster.png b/512x512/logo_cybermaster.png
deleted file mode 100644
index 5b6c3d4..0000000
Binary files a/512x512/logo_cybermaster.png and /dev/null differ
diff --git a/512x512/logo_diver.png b/512x512/logo_diver.png
deleted file mode 100644
index d310676..0000000
Binary files a/512x512/logo_diver.png and /dev/null differ
diff --git a/512x512/logo_face.png b/512x512/logo_face.png
deleted file mode 100644
index 5b123e7..0000000
Binary files a/512x512/logo_face.png and /dev/null differ
diff --git a/512x512/logo_hunter.png b/512x512/logo_hunter.png
deleted file mode 100644
index 0116ad3..0000000
Binary files a/512x512/logo_hunter.png and /dev/null differ
diff --git a/512x512/logo_hypnotherapist.png b/512x512/logo_hypnotherapist.png
deleted file mode 100644
index fcac4b3..0000000
Binary files a/512x512/logo_hypnotherapist.png and /dev/null differ
diff --git a/512x512/logo_massage_therapist.png b/512x512/logo_massage_therapist.png
deleted file mode 100644
index 962ddbe..0000000
Binary files a/512x512/logo_massage_therapist.png and /dev/null differ
diff --git a/512x512/logo_mediator.png b/512x512/logo_mediator.png
deleted file mode 100644
index 5adff0e..0000000
Binary files a/512x512/logo_mediator.png and /dev/null differ
diff --git a/512x512/logo_personal_coach.png b/512x512/logo_personal_coach.png
deleted file mode 100644
index 1984270..0000000
Binary files a/512x512/logo_personal_coach.png and /dev/null differ
diff --git a/512x512/logo_polymath.png b/512x512/logo_polymath.png
deleted file mode 100644
index 12b3995..0000000
Binary files a/512x512/logo_polymath.png and /dev/null differ
diff --git a/512x512/logo_prompt_master.png b/512x512/logo_prompt_master.png
deleted file mode 100644
index d061f4d..0000000
Binary files a/512x512/logo_prompt_master.png and /dev/null differ
diff --git a/512x512/logo_skydiver.png b/512x512/logo_skydiver.png
deleted file mode 100644
index 7fed710..0000000
Binary files a/512x512/logo_skydiver.png and /dev/null differ
diff --git a/512x512/logo_yachtmaster.png b/512x512/logo_yachtmaster.png
deleted file mode 100644
index 68b25ed..0000000
Binary files a/512x512/logo_yachtmaster.png and /dev/null differ
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..fdc27cc
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+# Basis-Image für Python
+FROM python:slim
+
+# Arbeitsverzeichnis festlegen
+WORKDIR /app
+
+# Abhängigkeiten kopieren und installieren
+COPY app/requirements.txt requirements.txt
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Anwendungscode kopieren
+COPY app/ .
+
+# Port freigeben
+EXPOSE 5000
+
+# Startbefehl
+CMD ["python", "app.py"]
diff --git a/README.md b/README.md
index 2e9f754..d7fe0f8 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,9 @@
-# homepage.veen.world
\ No newline at end of file
+# homepage.veen.world
+
+docker build -t flask-app .
+
+docker run -d -p 5000:5000 --name landingpage flask-app
+
+http://127.0.0.1:5000
+
+sudo docker run -d -p 5000:5000 --name landingpage -v $(pwd)/app/:/app -e FLASK_APP=app.py -e FLASK_ENV=development flask-app
\ No newline at end of file
diff --git a/app/app.py b/app/app.py
new file mode 100644
index 0000000..9798fda
--- /dev/null
+++ b/app/app.py
@@ -0,0 +1,70 @@
+import json
+import os
+from flask import Flask, render_template
+import requests
+import hashlib
+
+def cache_icon(icon_url, cache_dir="static/logos"):
+ """Lädt ein Icon herunter und speichert es lokal, wenn es nicht existiert. Fügt einen Hash hinzu."""
+ # Erstelle das Verzeichnis, falls es nicht existiert
+ os.makedirs(cache_dir, exist_ok=True)
+
+ # Generiere einen 8-Zeichen-Hash basierend auf der URL
+ hash_object = hashlib.blake2s(icon_url.encode('utf-8'), digest_size=8)
+ hash_suffix = hash_object.hexdigest()
+
+ # Erstelle den Dateinamen mit Hash
+ base_name = icon_url.split("/")[-2]
+ filename = f"{base_name}_{hash_suffix}.png"
+ full_path = os.path.join(cache_dir, filename)
+
+ # Wenn die Datei existiert, überspringe den Download
+ if os.path.exists(full_path):
+ return full_path
+
+ # Lade die Datei herunter
+ response = requests.get(icon_url, stream=True)
+ if response.status_code == 200:
+ with open(full_path, "wb") as f:
+ for chunk in response.iter_content(1024):
+ f.write(chunk)
+ return full_path
+
+
+app = Flask(__name__)
+
+# Hole die Umgebungsvariable FLASK_ENV oder setze einen Standardwert
+FLASK_ENV = os.getenv("FLASK_ENV", "production")
+
+config_data = None # Globale Variable für die Konfiguration
+
+def load_config():
+ """Lädt die Konfiguration aus der JSON-Datei."""
+ with open("config.json", "r") as config_file:
+ return json.load(config_file)
+
+@app.before_request
+def reload_config_in_dev():
+ """Lädt die Datei bei jedem Request neu im Dev-Modus."""
+ global config_data
+ if FLASK_ENV == "development" or config_data is None:
+ config_data = load_config()
+
+ # Cachen der Icons
+ for card in config_data["cards"]:
+ card["icon"] = cache_icon(card["icon"])
+
+@app.route('/')
+def index():
+ return render_template("pages/index.html.j2", cards=config_data.get("cards", []), networks=config_data.get("networks", []), company=config_data["company"])
+
+@app.route('/imprint')
+def imprint():
+ return render_template('pages/imprint.html.j2')
+
+@app.route('/agb')
+def agb():
+ return render_template('pages/agb.html.j2')
+
+if __name__ == "__main__":
+ app.run(debug=(FLASK_ENV == "development"), host="0.0.0.0", port=5000)
\ No newline at end of file
diff --git a/app/config.json b/app/config.json
new file mode 100644
index 0000000..0761ba6
--- /dev/null
+++ b/app/config.json
@@ -0,0 +1,112 @@
+{
+ "cards": [
+ {
+ "icon": "https://cloud.veen.world/s/logo_agile_coach_512x512/download",
+ "title": "Agile Coach",
+ "text": "I lead agile transformations and improve team dynamics through Scrum, DevOps, and Agile Coaching. My goal is to enhance collaboration and efficiency in organizations, ensuring agile principles are effectively implemented for sustainable success.",
+ "link": "https://www.agile-coach.world",
+ "link_text": "www.agile-coach.world"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_personal_coach_512x512/download",
+ "title": "Personal Coach",
+ "text": "Offering personalized coaching for growth and development, I utilize a blend of hypnotherapy, mediation, and holistic techniques. My approach is tailored to help you achieve personal and professional milestones, fostering holistic well-being.",
+ "link": "https://www.personalcoach.berlin",
+ "link_text": "www.personalcoach.berlin"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_yachtmaster_512x512/download",
+ "title": "Yachtmaster",
+ "text": "As a Yachtmaster, I provide comprehensive sailing education, yacht delivery, and voyage planning services. Whether you're learning to sail or need an experienced skipper, my expertise ensures a safe and enjoyable experience on the water.",
+ "link": "https://www.yachtmaster.world",
+ "link_text": "www.yachtmaster.world"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_polymath_512x512/download",
+ "title": "Polymath",
+ "text": "I support the evaluation and execution of complex cross-domain projects, offering insights across land, sea, sky, and digital realms. My expertise helps clients navigate and succeed in multifaceted environments with strategic precision.",
+ "link": "https://www.crossdomain.consulting/",
+ "link_text": "www.crossdomain.consulting"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_cybermaster_512x512/download",
+ "title": "Cybermaster",
+ "text": "Specializing in open-source IT solutions for German SMBs, I focus on automation, security, and reliability. My services are designed to create robust infrastructures that streamline operations and safeguard digital assets.",
+ "link": "https://www.cybermaster.space",
+ "link_text": "www.cybermaster.space"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_prompt_master_512x512/download",
+ "title": "Prompt Engineer",
+ "text": "Leveraging AI's power, I specialize in crafting custom prompts and creative content for AI-driven applications. My services are aimed at businesses, creatives, and researchers looking to harness AI technology for innovation, efficiency, and exploring new possibilities.",
+ "link": "https://promptmaster.nexus",
+ "link_text": "www.promptmaster.nexus"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_mediator_512x512/download",
+ "title": "Mediator",
+ "text": "Specializing in resolving interpersonal and business conflicts with empathy and neutrality, I facilitate open communication to achieve lasting agreements and strengthen relationships. My mediation services are designed for individuals, teams, and organizations to foster a harmonious and productive environment.",
+ "link": "https://www.mediator.veen.world",
+ "link_text": "www.mediator.veen.world"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_hypnotherapist_512x512/download",
+ "title": "Hypnotherapist",
+ "text": "As a certified Hypnotherapist, I offer tailored sessions to address mental and emotional challenges through hypnosis. My approach helps unlock the subconscious to overcome negative beliefs and stress, empowering you to activate self-healing and embrace positive life changes.",
+ "link": "https://www.hypno.veen.world",
+ "link_text": "www.hypno.veen.world"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_skydiver_512x512/download",
+ "title": "Aerospace Consultant",
+ "text": "As an Aerospace Consultant with aviation credentials, including a Sport Pilot License for Parachutes, and a Restricted Radiotelephony and Operator's Certificate I deliver expert consulting services. Currently training for my Private Pilot License, I specialize in guiding clients through aviation regulations, safety standards, and operational efficiency.",
+ "link": null,
+ "link_text": "Website under construction"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_hunter_512x512/download",
+ "title": "Wildlife Expert",
+ "text": "As a certified hunter and wildlife coach, I offer educational programs, nature walks, survival trainings, and photo expeditions, merging ecological knowledge with nature respect. My goal is to foster sustainable conservation and enhance appreciation for the natural world through responsible practices.",
+ "link": null,
+ "link_text": "Website under construction"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_diver_512x512/download",
+ "title": "Master Diver",
+ "text": "As a certified master diver with trainings in various specialties, I offer diving instruction, underwater photography, and guided dive tours. My experience ensures safe and enriching underwater adventures, highlighting marine conservation and the wonders of aquatic ecosystems.",
+ "link": null,
+ "link_text": "Website under construction"
+ },
+ {
+ "icon": "https://cloud.veen.world/s/logo_massage_therapist_512x512/download",
+ "title": "Massage Therapist",
+ "text": "Certified in Tantra Massage, I offer unique full-body rituals to awaken senses and harmonize body and mind. My sessions, a blend of ancient Tantra and modern relaxation, focus on energy flow, personal growth, and spiritual awakening.",
+ "link": null,
+ "link_text": "Website under construction"
+ }
+
+ ],
+ "networks": [
+ {
+ "name": "GitHub",
+ "icon": "bi bi-github",
+ "link": "https://github.com/kevinveenbirkenbach"
+ },
+ {
+ "name": "Instagram",
+ "icon": "fa-brands fa-instagram",
+ "link": "https://www.instagram.com/kevinveenbirkenbach/"
+ }
+ ],
+ "company": {
+ "titel": "Kevin Veen-Birkenbach",
+ "subtitel": "Consulting and Coaching Solutions",
+ "logo": "https://cloud.veen.world/s/logo_face_512x512/download",
+ "address": {
+ "street": "Afrikanische Straße 43",
+ "postal_code": "DE-13351",
+ "city": "Berlin",
+ "country": "Germany"
+ }
+ }
+ }
\ No newline at end of file
diff --git a/app/requirements.txt b/app/requirements.txt
new file mode 100644
index 0000000..5eaf725
--- /dev/null
+++ b/app/requirements.txt
@@ -0,0 +1,2 @@
+flask
+requests
\ No newline at end of file
diff --git a/app/static/css/default.css b/app/static/css/default.css
new file mode 100644
index 0000000..8d8c800
--- /dev/null
+++ b/app/static/css/default.css
@@ -0,0 +1,67 @@
+a {
+ text-decoration: none;
+ color: #000000;
+ }
+ .header img {
+ float: right;
+ width: 100px;
+ height: 100px;
+ }
+
+ .header h1 {
+ position: relative;
+ }
+ .equal-height {
+ display: flex;
+ flex: 1;
+ }
+ .card-body {
+ display: flex;
+ flex-direction: column;
+ align-items: center; /* Zentriert die Inhalte horizontal */
+ text-align: center; /* Zentriert den Text */
+ }
+
+ .card-icon {
+ display: flex;
+ justify-content: center; /* Zentriert das Icon horizontal */
+ }
+
+ .card-text,
+ .card ul {
+ text-align: left; /* Stellt sicher, dass der Text linksbündig ist */
+ }
+
+ .card{
+ flex: 1; /* Stellt sicher, dass die Karten die ganze Höhe ihrer Container ausfüllen */
+ border-width: 3px;
+ /*border-color: #000000;*/
+ }
+
+ h3.card-title{
+ font-size: 1.3em;
+ }
+
+ .card .stretched-link{
+ font-size: 0.7em;
+ }
+
+ .card-column{
+ padding-top: 12px;
+ padding-bottom: 12px;
+ }
+
+ h3.footer-title{
+ font-size: 1.3em;
+ }
+
+ .footer {
+ margin-top: 12px;
+ text-align: center;
+ font-size: 0.7em;
+ }
+
+ .footer p, h3{
+ margin: 0px;
+ padding: 0px;
+ }
\ No newline at end of file
diff --git a/favicon.ico b/app/static/images/favicon.ico
similarity index 100%
rename from favicon.ico
rename to app/static/images/favicon.ico
diff --git a/app/templates/base.html b/app/templates/base.html
new file mode 100644
index 0000000..47a404a
--- /dev/null
+++ b/app/templates/base.html
@@ -0,0 +1,35 @@
+
+
+
+ {{company.titel}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{company.titel}}
+
{{company.subtitel}}
+
+
+ {% block content %}{% endblock %}
+
+
+
+
+
\ No newline at end of file
diff --git a/app/templates/card.html.j2 b/app/templates/card.html.j2
new file mode 100644
index 0000000..41590e9
--- /dev/null
+++ b/app/templates/card.html.j2
@@ -0,0 +1,13 @@
+