Initial commit
This commit is contained in:
26
docker-compose.yaml
Normal file
26
docker-compose.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
website:
|
||||
container_name: website
|
||||
build: ./src
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.flask.rule=Host(`portfolio.vavaas.dev`)"
|
||||
- "traefik.http.routers.flask.entrypoints=websecure"
|
||||
- "traefik.http.routers.flask.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.flask.loadbalancer.server.port=5000"
|
||||
|
||||
- "traefik.http.routers.redirect-vavaas.rule=Host(`vavaas.dev`,`www.vavaas.dev`)"
|
||||
- "traefik.http.routers.redirect-vavaas.entrypoints=web,websecure"
|
||||
- "traefik.http.routers.redirect-vavaas.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.redirect-vavaas.middlewares=redirect-to-portfolio"
|
||||
- "traefik.http.middlewares.redirect-to-portfolio.redirectregex.regex=^https?://vavaas.dev/(.*)"
|
||||
- "traefik.http.middlewares.redirect-to-portfolio.redirectregex.replacement=https://portfolio.vavaas.dev/$1"
|
||||
- "traefik.http.middlewares.redirect-to-portfolio.redirectregex.permanent=true"
|
||||
networks:
|
||||
- web
|
||||
volumes:
|
||||
- "./src/data:/data"
|
||||
|
||||
networks:
|
||||
web:
|
||||
external: true
|
||||
13
src/Dockerfile
Normal file
13
src/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
RUN pip install --no-cache-dir -r /data/requirements.txt
|
||||
|
||||
RUN ls
|
||||
RUN pwd
|
||||
|
||||
CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app"]
|
||||
BIN
src/data/__pycache__/app.cpython-311.pyc
Normal file
BIN
src/data/__pycache__/app.cpython-311.pyc
Normal file
Binary file not shown.
15
src/data/app.py
Normal file
15
src/data/app.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from flask import Flask, render_template
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
return render_template("index.html", title="Accueil")
|
||||
|
||||
@app.route("/projects")
|
||||
def projects():
|
||||
return render_template("projects.html", title="Projets")
|
||||
|
||||
@app.route("/contact")
|
||||
def contact():
|
||||
return render_template("contact.html", title="Contact")
|
||||
2
src/data/requirements.txt
Normal file
2
src/data/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
flask
|
||||
gunicorn
|
||||
174
src/data/static/css/style.css
Normal file
174
src/data/static/css/style.css
Normal file
@@ -0,0 +1,174 @@
|
||||
* ======================================
|
||||
Base styles
|
||||
====================================== */
|
||||
:root {
|
||||
--bs-body-bg: #2c2c2c;
|
||||
--bs-body-color: #f8f9fa;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #2c2c2c; /* Dark background to match navbar */
|
||||
color: #f8f9fa; /* Light text for readability */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 0 auto;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Header / Navbar tweaks
|
||||
====================================== */
|
||||
.navbar {
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.navbar .nav-link {
|
||||
color: #f8f9fa; /* Ensure nav links are visible */
|
||||
}
|
||||
|
||||
.navbar .nav-link.active {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.navbar .nav-link:hover {
|
||||
color: #ffc107; /* Bootstrap warning color for hover highlight */
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Footer
|
||||
====================================== */
|
||||
footer {
|
||||
flex-shrink: 0;
|
||||
background: #343a40; /* Dark gray, same tone as navbar */
|
||||
color: #f8f9fa;
|
||||
border-top: 1px solid #444;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
footer img {
|
||||
margin-left: 0.3rem;
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Projects page cards
|
||||
====================================== */
|
||||
.projects-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.project-card {
|
||||
background: #3c3f44; /* Slightly lighter than page background */
|
||||
color: #f8f9fa;
|
||||
padding: 1.5rem;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.project-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 15px rgba(0,0,0,0.45);
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Links
|
||||
====================================== */
|
||||
a {
|
||||
color: #0d6efd; /* Bootstrap primary color */
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ======================================
|
||||
Responsive tweaks
|
||||
====================================== */
|
||||
@media (max-width: 576px) {
|
||||
main {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zoom effect for profile picture */
|
||||
.profile-pic {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.profile-pic:hover {
|
||||
transform: scale(1.1); /* Zoom in slightly on hover */
|
||||
}
|
||||
|
||||
/* Hero section styling */
|
||||
.hero-section {
|
||||
background: linear-gradient(135deg, #1f1f1f, #2c2c2c); /* dark gradient */
|
||||
box-shadow: 0 8px 20px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.hero-section p, .hero-section h1 {
|
||||
color: #f8f9fa; /* Ensure text is readable on dark bg */
|
||||
}
|
||||
|
||||
/* Profile picture hover zoom */
|
||||
.profile-pic {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.profile-pic:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Hero box animation */
|
||||
.hero-box {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
animation: fadeInUp 1s forwards;
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
/* Project box hover scale */
|
||||
.hover-scale {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-scale:hover {
|
||||
transform: scale(1.03);
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* Fade-in animation */
|
||||
@keyframes fadeInUp {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.project-row .row > div > .bg-dark {
|
||||
background-color: #1c1c1c; /* slightly darker than default bg-dark */
|
||||
}
|
||||
/* Alternate spacing for left/right boxes */
|
||||
.project-row .row:nth-child(even) {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.project-img {
|
||||
max-height: 180px; /* adjust as you like */
|
||||
width: auto; /* keeps proportions */
|
||||
object-fit: contain;
|
||||
}
|
||||
BIN
src/data/static/img/companion.png
Executable file
BIN
src/data/static/img/companion.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
src/data/static/img/kfs.png
Executable file
BIN
src/data/static/img/kfs.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
src/data/static/img/monster.png
Executable file
BIN
src/data/static/img/monster.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 498 B |
BIN
src/data/static/img/override.png
Executable file
BIN
src/data/static/img/override.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
src/data/static/img/profile.png
Executable file
BIN
src/data/static/img/profile.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 246 KiB |
BIN
src/data/static/img/profile.webp
Executable file
BIN
src/data/static/img/profile.webp
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
55
src/data/templates/base.html
Normal file
55
src/data/templates/base.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ title if title else "Portfolio" }}</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header / Navbar -->
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ url_for('home') }}">Mon Portfolio</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if title=='Accueil' %}active{% endif %}" href="{{ url_for('home') }}">Accueil</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if title=='Projets' %}active{% endif %}" href="{{ url_for('projects') }}">Projets</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if title=='Contact' %}active{% endif %}" href="{{ url_for('contact') }}">Contact</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<!-- Main content -->
|
||||
<main class="container my-5">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-dark text-center text-lg-start py-3 border-top">
|
||||
<div class="container d-flex justify-content-center align-items-center">
|
||||
<p class="mb-0 text-light">
|
||||
© 2025 Avec amour et
|
||||
<img src="{{ url_for('static', filename='img/monster.png') }}" alt="Battery" width="16" height="16" class="ms-1">
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
5
src/data/templates/contact.html
Normal file
5
src/data/templates/contact.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h1>Contact</h1>
|
||||
<p>Tu peux me joindre à <a href="mailto:vavaas.dev@gmail.com">vavaas.dev@gmail.com</a></p>
|
||||
{% endblock %}
|
||||
93
src/data/templates/index.html
Normal file
93
src/data/templates/index.html
Normal file
@@ -0,0 +1,93 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div class="container py-5">
|
||||
<!-- Hero / Presentation Box -->
|
||||
<div class="p-5 mb-5 rounded-4 bg-dark text-light shadow hero-box">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6 mb-4 mb-md-0">
|
||||
<h1 class="display-4 mb-3">Bienvenue sur mon portfolio</h1>
|
||||
<p class="lead">
|
||||
Salut ! Je suis Valentin, développeur bas-niveau passionné par la cybersécurité et le DevOps.
|
||||
Ici, vous pouvez découvrir mes projets et me contacter directement.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6 text-center">
|
||||
<img src="{{ url_for('static', filename='img/profile.webp') }}"
|
||||
alt="Profile picture"
|
||||
class="rounded-circle img-fluid profile-pic"
|
||||
style="width: 250px; height: 250px; object-fit: cover;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Featured Projects Title -->
|
||||
<h2 class="text-light text-center mb-5">Featured Projects</h2>
|
||||
|
||||
<!-- Featured Project Boxes -->
|
||||
<div class="container mb-5">
|
||||
<!-- Project 1 (left) -->
|
||||
<div class="row mb-5 justify-content-start">
|
||||
<div class="col-md-8">
|
||||
<a href="https://github.com/Kbz-8/42_KFS" class="text-decoration-none">
|
||||
<div class="p-4 rounded-4 bg-dark text-light shadow hover-scale">
|
||||
<div class="row align-items-center">
|
||||
<!-- Text -->
|
||||
<div class="col-md-7">
|
||||
<h4>Kernel From Scratch</h4>
|
||||
<p>Création d'un kernel en Zig 0.13 avec pilotes claviers et graphiques, IDT, GDT, gestion mémoire et shell intégré</p>
|
||||
</div>
|
||||
<!-- Image -->
|
||||
<div class="col-md-5 text-center">
|
||||
<img src="{{ url_for('static', filename='img/kfs.png') }}"
|
||||
alt="Projet 1" class="img-fluid rounded shadow project-img">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project 2 (right) -->
|
||||
<div class="row mb-5 justify-content-end">
|
||||
<div class="col-md-8">
|
||||
<a href="https://github.com/Namonay/swifty-companion" class="text-decoration-none">
|
||||
<div class="p-4 rounded-4 bg-dark text-light shadow hover-scale">
|
||||
<div class="row align-items-center flex-md-row-reverse">
|
||||
<div class="col-md-7">
|
||||
<h4>Swifty Companion</h4>
|
||||
<p>Application mobile Android et iOS utilisant l'API de 42 pour avoir des informations sur les campus</p>
|
||||
</div>
|
||||
<div class="col-md-5 text-center">
|
||||
<img src="{{ url_for('static', filename='img/companion.png') }}"
|
||||
alt="Projet 2" class="img-fluid rounded shadow project-img">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Project 3 (left) -->
|
||||
<div class="row mb-5 justify-content-start">
|
||||
<div class="col-md-8">
|
||||
<a href="https://github.com/C18H24O2/override" class="text-decoration-none">
|
||||
<div class="p-4 rounded-4 bg-dark text-light shadow hover-scale">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-7">
|
||||
<h4>Override</h4>
|
||||
<p>Défis de cybersécurité sous formes de CTF, avec reverse engineering, pwn et exploitation de failles</p>
|
||||
</div>
|
||||
<div class="col-md-5 text-center">
|
||||
<img src="{{ url_for('static', filename='img/override.png') }}"
|
||||
alt="Projet 3" class="img-fluid rounded shadow project-img">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
9
src/data/templates/projects.html
Normal file
9
src/data/templates/projects.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h1>Mes Projets</h1>
|
||||
<ul>
|
||||
<li>Projet 1 – Devenir un tigre</li>
|
||||
<li>Projet 2 – Un script d’automatisation pour acheter des monsters</li>
|
||||
<li>Projet 3 – Trouver un job</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user