Portfolio Web
Portfolio personal desarrollado con Flask para centralizar mi trayectoria profesional, proyectos técnicos, experiencia, blog y documentación relacionada con redes, sistemas, desarrollo y electrónica.
El proyecto está pensado no solo como una página de presentación, sino como una aplicación web mantenible y extensible sobre la que poder incorporar nuevas funcionalidades y herramientas técnicas.
Objetivos
Los principales objetivos del proyecto son:
- Centralizar mi perfil y trayectoria profesional.
- Documentar proyectos técnicos de forma estructurada.
- Mantener un blog técnico propio.
- Publicar contenido mediante Markdown.
- Disponer de un backend de administración.
- Mantener separada la gestión del contenido de su presentación pública.
- Facilitar futuras ampliaciones de la aplicación.
- Disponer de una arquitectura preparada para despliegue mediante contenedores.
Stack tecnológico
Backend
- Python
- Flask
- SQLAlchemy
- Flask-Migrate
- Alembic
- Flask-Admin
- Flask-Login
- Flask-Babel
- Jinja2
Base de datos
- PostgreSQL
Frontend
- HTML5
- CSS
- Bootstrap
- Bootstrap Icons
- JavaScript
- AOS
Contenido técnico
- Markdown
- Mermaid
- PrismJS
Despliegue
- Docker
- Docker Compose
- Gunicorn
- Nginx
- PostgreSQL
Arquitectura general
La aplicación utiliza el patrón Application Factory de Flask y organiza las distintas áreas mediante Blueprints.
flowchart TD
A["Usuario"] --> B["Nginx"]
B --> C["Gunicorn"]
C --> D["Flask"]
D --> E["Main"]
D --> F["Blog"]
D --> G["Career"]
D --> H["Projects"]
D --> I["Auth"]
D --> J["Admin"]
F --> K["SQLAlchemy"]
G --> K
H --> K
I --> K
J --> K
K --> L[("PostgreSQL")]
D --> M["Jinja2"]
M --> N["HTML / Bootstrap"]
F --> O["Markdown"]
G --> O
H --> O
O --> P["Mermaid / PrismJS"]
%% Estilos de Nodos
style A fill:#e1f5fe,stroke:#039be5,stroke-width:2px,color:#01579b
style B fill:#fff3e0,stroke:#fb8c00,stroke-width:1px,color:#e65100
style C fill:#fff9c4,stroke:#fbc02d,stroke-width:1px,color:#f57f17
style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20
style K fill:#ede7f6,stroke:#5e35b1,stroke-width:1px,color:#311b92
style L fill:#ffebee,stroke:#e53935,stroke-width:2px,color:#b71c1c
style M fill:#e0f7fa,stroke:#00acc1,stroke-width:1px,color:#006064
style N fill:#f1f8e9,stroke:#689f38,stroke-width:1px,color:#33691e
style O fill:#f3e5f5,stroke:#ab47bc,stroke-width:1px,color:#4a148c
style P fill:#efebe9,stroke:#6d4c41,stroke-width:1px,color:#3e2723
Organización de la aplicación
La aplicación se divide en diferentes áreas funcionales.
Página principal
Presenta una visión general del perfil profesional, conocimientos técnicos y principales áreas de especialización.
Trayectoria Profesional
Sección destinada a documentar de forma más extensa la experiencia, evolución profesional y conocimientos adquiridos.
El contenido se almacena en base de datos y puede gestionarse desde Flask-Admin.
Blog Técnico
Permite publicar artículos técnicos con:
- título
- slug
- resumen
- imagen de portada
- contenido Markdown
- tags
- fecha de publicación
Incluye búsqueda, filtrado por etiquetas y archivo cronológico.
Proyectos
Sección destinada a documentar proyectos propios.
Cada proyecto puede disponer de:
- título
- slug
- descripción
- imagen de portada
- tecnologías utilizadas
- repositorio GitHub
- documentación Markdown
- estado de publicación
Los proyectos pueden mantenerse como borradores antes de hacerlos públicos.
Administración
Flask-Admin proporciona una interfaz privada para gestionar el contenido del Portfolio.
Desde ella es posible administrar:
- proyectos
- posts
- tags
- páginas
- usuarios
Modelo de datos
La aplicación utiliza SQLAlchemy como ORM y PostgreSQL como sistema gestor de base de datos.
Entre los principales modelos se encuentran:
PostTagProjectPageUserAccessLog
Las modificaciones del esquema se gestionan mediante Flask-Migrate y Alembic.
erDiagram
POST }o--o{ TAG : tags
POST {
int id
string title
string slug
text content
string summary
text cover_image
datetime created_at
}
TAG {
int id
string name
}
PROJECT {
int id
string title
string slug
text description
text content
text cover_image
text tech_stack
text github_url
boolean is_published
datetime created_at
}
PAGE {
int id
string section
string slug
string title
text content
boolean is_published
}
USER {
int id
string username
string password_hash
}
ACCESSLOG {
int id
datetime timestamp
string ip
string method
string path
int status_code
}
Gestión de contenido
Una parte importante del proyecto es evitar que el contenido esté codificado directamente en los templates.
El flujo general es:
flowchart LR
A["Flask-Admin"] --> B["SQLAlchemy"]
B --> C[("PostgreSQL")]
C --> D["Blueprint"]
D --> E["Jinja2"]
E --> F["Usuario"]
%% Estilos de Nodos
style A fill:#e1f5fe,stroke:#039be5,stroke-width:2px,color:#01579b
style B fill:#fff3e0,stroke:#fb8c00,stroke-width:1px,color:#e65100
style C fill:#ffebee,stroke:#e53935,stroke-width:2px,color:#b71c1c
style D fill:#ede7f6,stroke:#5e35b1,stroke-width:1px,color:#311b92
style E fill:#e0f7fa,stroke:#00acc1,stroke-width:1px,color:#006064
style F fill:#f1f8e9,stroke:#689f38,stroke-width:2px,color:#33691e
Esto permite modificar y publicar contenido sin modificar el código de la aplicación.
Markdown
Los artículos, páginas y proyectos pueden contener documentación escrita en Markdown.
El contenido Markdown se procesa en el backend antes de enviarse al template.
Esto permite incorporar:
- encabezados
- tablas
- bloques de código
- listas
- enlaces
- notas
- diagramas Mermaid
Sistema de publicación
Las secciones que lo requieren disponen de un estado de publicación.
Un contenido puede permanecer en borrador mientras se prepara y únicamente hacerse visible cuando esté terminado.
flowchart LR
A["Crear contenido"] --> B["Draft"]
B --> C{"Publicar"}
C -->|No| B
C -->|Sí| D["Visible públicamente"]
%% Estilos de Nodos
style A fill:#e1f5fe,stroke:#039be5,stroke-width:2px,color:#01579b
style B fill:#fff3e0,stroke:#fb8c00,stroke-width:1px,color:#e65100
style C fill:#fff9c4,stroke:#fbc02d,stroke-width:1px,color:#f57f17
style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20
Además, las rutas públicas comprueban el estado del contenido, por lo que conocer directamente un slug no permite acceder a un elemento no publicado.
Registro de accesos
La aplicación incorpora un sistema propio de registro de peticiones.
Entre la información registrada se encuentra:
- fecha y hora
- dirección IP
- método HTTP
- ruta
- código de estado
- tiempo de respuesta
- User-Agent
- navegador
- sistema operativo
- dispositivo
- referencia de origen
Esto permite disponer de información básica sobre el uso de la aplicación sin depender exclusivamente de los logs del servidor web.
Despliegue
La versión de producción está preparada para ejecutarse mediante contenedores.
La arquitectura de despliegue utiliza:
flowchart LR
A["Internet"] --> B["Nginx"]
B --> C["Flask / Gunicorn"]
C --> D[("PostgreSQL")]
%% Estilos de Nodos
style A fill:#e1f5fe,stroke:#039be5,stroke-width:2px,color:#01579b
style B fill:#fff3e0,stroke:#fb8c00,stroke-width:1px,color:#e65100
style C fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#1b5e20
style D fill:#ffebee,stroke:#e53935,stroke-width:2px,color:#b71c1c
Nginx actúa como reverse proxy mientras Gunicorn ejecuta la aplicación Flask.
PostgreSQL mantiene los datos persistentes de la aplicación.
Evolución del proyecto
Portfolio Web está diseñado como un proyecto en evolución continua.
Entre las futuras ampliaciones previstas se encuentra una sección de herramientas técnicas interactivas, donde podrán incorporarse aplicaciones como:
- calculadora IP
- análisis de configuraciones de FortiGate
- análisis de logs
- utilidades de networking
- otras herramientas orientadas a administración de sistemas y redes
La intención es evolucionar progresivamente desde un portfolio convencional hacia una plataforma técnica personal que combine presentación profesional, documentación y herramientas propias.
Estado
El proyecto se encuentra en desarrollo activo y continúa evolucionando mediante nuevas secciones, mejoras funcionales y ampliaciones de contenido.