- [X] Cambiar el color de fondo por algo gris pero con degradados
- [X] Cambiar el texto por el logo del laboratorio.
- [X] Mejorar el carrusel de imágenes
- [X] Cambiar las imágenes y que sean de un directorio local.
- [X] Mejorar la transición, si doy en un botón se “reinicia” el contador.
- [X] Darle función del botón “Únete a la comunidad”
- [X] Mejorar el aspecto del botón “Explorar Proyectos”
- [X] Tener un poco más de efecto “Glow”, pero que siga siendo sutil…
- [X] Usar un logo para el tema oscuro y otro para el tema claro.
import { Button } from “./ui/button”; import { ArrowRight, ChevronLeft, ChevronRight } from “lucide-react”; import { ImageWithFallback } from “./figma/ImageWithFallback”; import { useState, useEffect } from “react”; import { motion, AnimatePresence } from “motion/react”; import { useLanguage } from “./LanguageProvider”; import Link from “next/link”;
export function Hero() { const [currentImageIndex, setCurrentImageIndex] = useState(0); const [direction, setDirection] = useState(0); const { language } = useLanguage();
const carouselImages = [ { src: “https://images.unsplash.com/photo-1640552435388-a54879e72b28?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=870”, alt: “Debian Neofetch” }, { src: “https://images.unsplash.com/photo-1714846200875-006da50cb5b0?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=870”, alt: “Arch sticker” }, { src: “https://www.tecmint.com/wp-content/uploads/2019/04/herbstluftwm-manual-tiling-window-manager-for-linux-768x556.png”, alt: “Sudo ubuntu” }, { src: “https://images.unsplash.com/photo-1640552435845-d65c23b75934?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=1470”, alt: “HTOP” }, { src: “https://images.unsplash.com/photo-1610812387871-806d3db9f5aa?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=1480”, alt: “Raspberry pi” }, { src: “https://www.tpart.net/wp-content/uploads/2024/12/x210Ai-completed-laptop-768x1024.jpg”, alt: “Thinkpad ubuntu” } ];
const nextImage = () => { setDirection(1); setCurrentImageIndex((prev) => (prev + 1) % carouselImages.length); };
const prevImage = () => { setDirection(-1); setCurrentImageIndex((prev) => (prev - 1 + carouselImages.length) % carouselImages.length); };
// Auto-advance carousel useEffect(() => { const interval = setInterval(() => { setDirection(1); setCurrentImageIndex((prev) => (prev + 1) % carouselImages.length); }, 4000); // Change image every 4 seconds
return () => clearInterval(interval); }, [carouselImages.length]);
const t = { tagline: { en: “FI ● UNAM ● CDMX”, es: “FI ● UNAM ● CDMX” }, description: { en: “We are a laboratory formed by volunteers, students, former students, and academics interested in the development of free and open technologies.”, es: “Somos un laboratorio formado por voluntarios, estudiantes, ex-estudiantes y académicos interesados en el desarrollo de tecnologías libres y abiertas” }, exploreProjects: { en: “Explore Projects”, es: “Explorar Proyectos” }, joinCommunity: { en: “Join Our Community”, es: “Únete a la Comunidad” }, activeProjects: { en: “Active Projects”, es: “Proyectos Activos” }, contributors: { en: “Contributors”, es: “Contribuidores” }, freeOpen: { en: “Free & Open”, es: “Libre y Abierto” }, };
return ( <section className=”relative overflow-hidden bg-background py-20 sm:py-32”> {* Ambient background glows *} <div className=”pointer-events-none absolute inset-0”> <div className=”absolute top-1/4 left-1/4 w-96 h-96 bg-[#1c71d8]/15 rounded-full blur-[130px]” /> <div className=”absolute bottom-0 right-1/3 w-80 h-80 bg-[#6C63FF]/10 rounded-full blur-[110px]” /> <div className=”absolute top-0 right-0 w-72 h-72 bg-[#3B82F6]/10 rounded-full blur-[90px]” /> <div className=”absolute bottom-1/4 left-0 w-64 h-64 bg-[#62a0ea]/10 rounded-full blur-[100px]” /> </div>
<div className=”container mx-auto px-4 sm:px-6 lg:px-8 relative”> <div className=”grid lg:grid-cols-2 gap-12 items-center”> {* Content *} <div className=”space-y-8”> <div className=”inline-block px-5 py-2 bg-primary/10 text-primary rounded-full border border-primary/20”> {t.tagline[language]} </div>
{* Title with glow *} <h1 className=”text-5xl sm:text-6xl lg:text-7xl text-foreground” style={{ textShadow: “0 0 40px rgba(28,113,216,0.35), 0 0 80px rgba(28,113,216,0.15)” }} > LIDSoL </h1>
<p className=”text-xl text-muted-foreground max-w-2xl”> {t.description[language]} </p>
<div className=”flex flex-wrap gap-4”> {* Explore Projects button with glow *} <div className=”relative”> <div className=”absolute inset-0 rounded-full bg-[#1c71d8]/30 blur-lg scale-110” /> <Button asChild size=”lg” className=”relative border-2 border-[#241F31] shadow-lg shadow-[#1c71d8]/30 hover:shadow-xl hover:shadow-[#1c71d8]/50 transition-shadow duration-300 gap-2 bg-[#1E78E4] text-[#F6F5F4] hover:bg-[#241F31]” style={{ animation: “wiggle 1s ease-in-out infinite” }} > <Link href=”#projects”> {t.exploreProjects[language]} <ArrowRight className=”h-4 w-4” /> </Link> </Button> </div>
{* Join Community button with subtle glow *} <div className=”relative”> <div className=”absolute inset-0 rounded-full bg-primary/10 blur-md scale-110” /> <Button size=”lg” variant=”outline” className=”relative” > {t.joinCommunity[language]} </Button> </div> </div>
<div className=”grid grid-cols-3 gap-8 pt-8 border-t border-border”> <div> <div className=”text-3xl text-foreground”>5+</div> <div className=”text-sm text-muted-foreground”>{t.activeProjects[language]}</div> </div> <div> <div className=”text-3xl text-foreground”>5+</div> <div className=”text-sm text-muted-foreground”>{t.contributors[language]}</div> </div> <div> <div className=”text-3xl text-foreground”>100%</div> <div className=”text-sm text-muted-foreground”>{t.freeOpen[language]}</div> </div> </div> </div>
{* Image *} <div className=”relative”> {* Layered glow halos around the image *} <div className=”absolute -inset-8 bg-[#62a0ea]/25 rounded-3xl blur-3xl” /> <div className=”absolute -inset-4 bg-[#1c71d8]/30 rounded-3xl blur-2xl” /> <div className=”absolute -inset-1 bg-[#3B82F6]/20 rounded-3xl blur-md” />
<div className=”aspect-square rounded-3xl overflow-hidden shadow-2xl shadow-[#1c71d8]/20 border border-border relative”> <AnimatePresence initial={false} custom={direction} mode=”popLayout”> <motion.div key={currentImageIndex} custom={direction} initial={{ x: direction > 0 ? 300 : -300, opacity: 0 }} animate={{ x: 0, opacity: 1 }} exit={{ x: direction > 0 ? -300 : 300, opacity: 0 }} transition={{ x: { type: “spring”, stiffness: 300, damping: 30 }, opacity: { duration: 0.2 } }} className=”absolute inset-0” > <ImageWithFallback src={carouselImages[currentImageIndex].src} alt={carouselImages[currentImageIndex].alt} className=”w-full h-full object-cover” /> </motion.div> </AnimatePresence>
{* Navigation buttons at bottom right *} <div className=”absolute bottom-4 right-4 flex gap-2”> <button onClick={prevImage} className=”bg-card/95 backdrop-blur hover:bg-card p-2.5 rounded-full shadow-md transition-all border border-border/50” aria-label=”Previous image” > <ChevronLeft className=”h-5 w-5” /> </button> <button onClick={nextImage} className=”bg-card/95 backdrop-blur hover:bg-card p-2.5 rounded-full shadow-md transition-all border border-border/50” aria-label=”Next image” > <ChevronRight className=”h-5 w-5” /> </button> </div> </div> </div> </div> </div> </section> ); }
- https://unsplash.com/photos/green-and-black-digital-device-xbEVM6oJ1Fs
- https://unsplash.com/photos/a-computer-screen-with-a-program-running-on-it-NLSXFjl_nhc
- https://unsplash.com/photos/a-computer-screen-with-a-lot-of-data-on-it-MU8w72PzRow
- https://unsplash.com/photos/a-close-up-of-a-cell-phone-on-a-table-uZkHtWsi2dE
- https://unsplash.com/photos/a-laptop-sits-open-on-a-wooden-surface-Tiy7aJwWPvc
- [X] Quitar la opción “ver más”
- [X] Mejorar el rendimiento
- [X] Cambiar el grid
- 1 columna en small con tres tarjetas
- 2 columnas en md con dos tarjetas por columna
- 3 columnas en lg con 3 tarjetas
- [X] Mejorar la responsividad
- [X] Mejorar aspecto de los botones y tarjetas
- [X] Mejorar la responsividad
- [X] Mejorar aspecto de los botones y tarjetas
- [X] Mejorar la responsividad
- [X] Mejorar aspecto de los botones y tarjetas
- [X] Textos que invite a unirse al laboratorio.
- [X] Cambiar es estilo de los botones.
- [X] Darte funcionalidad a los botones.
- [X] Cuando es en pantallas pequeñas:
- [X] ¿Menú de hamburguesa a la izquieda o derecha?
- [X] El menú debe aparecer a la izquierda y con animación (estilo nautilus)
- [X] Colocar un ícono a cada sección (tal vez sea bueno que solo sea visible en esta vista de pantallas pequeñas)
- [X] Mejorar la distribución de los elementos (principalmente en pantalla grande)
- [X] Hacer que al dar click se abra en una pestaña nueva y no en la actual
- [X] Debe ser compatible con el selector de idioma
- [X] Hacer una página de licencias…
- [X] 2.2.0 Detalles de la página de proyectos [100%]
- [X] Hacer que acepte imágenes
- [X] Hacer que los botones del github y el sitio funcionen correctamente
- [X] Hacer que la sección de Estrellas, contribuidores, estado y lenguaje estén abajo de la sección de características clave
- [X] Tener una opción para ordenar los proyectos según su ID o su nombre.
- [X] Hacer que el texto esté justificado, hacer que acepte saltos de línea.
- [X] Quitar el “ver más” de la vista de proyectos
- [X] Hacer que soporte markdown
- [X] Cambiar el título…
- [X] Mudar el contenido actual y añadir nuevo 2.2.2 [100%]
- Notas
- Recuerda lo de las comillas y saltos de línea
- Recuerda \n
- ¿Qué proyectos están en desarrollo y cuales son estables?
- [X] Sobre sway id=6
- [X] Sobre el papeador id=5
- [X] Sobre drawdb id=4
- [X] Sobre los mirrors id=3
- [X] Sobre el nodo de tor id=2
- [X] Sobre mecanismos de seguridad y privacidad id=1
- [X] Tal vez sobre apache beam id=7?
- Notas
- [X] Mejoras varias 2.2.1 [100%]
- [X] El botón de ver código de la sección projects no funciona.
- [X] Añadir un botón para descargar un archivo
- [X] Sería bueno ver una animación al entrar a la sección de proyectos, como la hay en About.
- [X] Hacer que la info que pide el json sea opcional (y no se rompa si falta info, como pasaba con el AboutMembers)
- [X] Borrar la “categoría” del proyecto, al final mejor me quedaré con los tags.
- [X] La descripción corta debe aceptar markdown.
- [X] Cambiar el color del botón a regresar
- [X] El estado del proyecto debe tener diferente ícono dependiendo del estado.
- [X] Colocar los tags (en donde antes estaba el gráfico de contribuciones).
- [X] Hacer las correciones pertinentes a la información de los proyectos.
- [X] Que los tags soporten multi-idioma
Los cambios realizados:
- src/data/projects.ts: Cambié el tipo de tags?: string[] a tags?: { en: string[]; es: string[] } y actualicé todos los tags con sus traducciones al español.
- src/components/Projects.tsx: Actualizado para usar project.tags[language]
- src/components/ProjectDetail.tsx: Actualizado para usar project.tags[language]
- src/components/FeaturedProjects.tsx: Actualizado para usar project.tags?.[language]
- [X] Verificar el estado de los proyectos (para que el ícono sea el adecuado)
- [X] Blog [100%]
- [X] Hacer que el Blog y el BlogDetail soporten el multi-idioma
- [X] Hay una Tag, general, que se muestra tanto en el Blog como en BlogDetail, esta no respeta el multi-idioma. Mejorar esto, para que funcionen correctamente los tags (tomados desde los archivos de markdown)
- [X] Mejoras en la responsividad
- [X] Separar más el autor, de la fecha del tiempo de lectura.
- [X] Reducir el espacio entre la imágen y el título del post.
- [X] Aumentar el espacio del título cuando hay salto de línea.
- [X] Cuando se ve en pantalla pequeña, sería mejor que la descripción o los tags se oculten.
- [X] El botón de “leer más” está más arriba o abajo dependiendo de la cantidad de tags y de la longitud del título del post, esto hacer que se vea muy irregular. Pasaba algo simiar con las tarjetas de miembros, tal vez puedas apoyarte de ese código para solucionarlo.
- [X] Mejoras visuales
- [X] Cambiar el bg en el boton readMore
- [X] Cambiar el bg en los tags
- [X] Añadir la misma animación que tiene la sección de proyectos
- [X] Hacer las tarjetas más pequeñas
- [X] Hay un botón hasta la parte inferior “Cargar más artículos” que no tiene funcionalidad. Podría ser bueno limitar la cantidad de post que se muestran y darle uso, o bien, retirarlo y que quede como un scroll con todo el contenido sin más.
- [X] BlogDetail [100%]
- [X] Sería bueno reducir la calidad de algunas de las imágenes, pues son muy pesadas y provocan que el sitio tarde en cargar, o en su defecto, hacer que se cargue una versión reducida en el Blog y en BlogDetail, pero en este último, al dar click en la imágen, verla en tamaño completo a modo de galería. Hacer lazy loading
- [X] Mejorar los meta-datos del sitio [100%]
- [X] Eliminar los metadatos no necesarios de los .md
- [X] Corrección al formato de fechas
- [X] Que el BlogDetail enlace al perfil del miembro del lab que escribió el articulo
- [X] Añadir imágenes de portada a los post que no tienen. Mejorar aquellas que chocan con la estética del sitio.
- [X] Tiempo de lectura
- [X] Mejora en la presentación del post [100%]
- [X] Hacer que el texto tenga justificación completa. apliqué la misma solución que en ProjectDetail.tsx:- text-justify hyphens-auto en las clases, style={{textAlign: ‘justify’}} inline
- [X] Las imágenes deben tener bordes redondeados. Como la imagen de portada. El borde redondeado de las imágenes del markdown se cambió de rounded-lg a rounded-2xl, que es el mismo estilo que usa la imagen de portada. La intención es que el estilo sea “muy libadwaita”.
- [X] Cambiar el color del botón de “volver al blog”.
- [X] Cambiar el color de los tags a secondary.
- [X] Mejorar el aspecto de los bloques de código de markdown Encontré este “plugin” llamado, react-syntax-highlighter que puede ayudarme con el formateo de sintaxis. Ahora el componente pre también maneja los fenced code blocks. Extrae el className del componente code hijo y lo usa para renderizar con SyntaxHighlighter. El componente pre se modificó para que cuando no tenga lenguaje, aun así use SyntaxHighlighter pero sin especificar el lenguaje (o usando un lenguaje genérico como “text”). Se modifica el caso if (language) para que también maneje el caso sin lenguaje, mostrando el bloque con el mismo estilo pero sin highlighting específico.
- [X] Añadir formateo matemático
- Se instaló rehype-katex, remark-math y katex
- Se importaron los plugins y el CSS de KaTeX
- Se agregó remarkMath y rehypeKatex a ReactMarkdown
- Se agreguó el CSS de KaTeX desde CDN en el HTML.
- [X] Mejorar el aspecto de las tablas markdown.
- [X] {{% alert warning %}} ¿NANI KORE!
- Más adelante, sería bueno añadir paginado
- Me doy cuanta que el los separadores de markdown no son correctamente soportados (—) en BlogDetail
- Se usarán archivos de markdown para el blog, cada subdirectorio de content será un post de blog. Hasta ahora se habían usado archivos .ts, pero para el escribir una artículo de blog, sería muy tedioso.
- Separación clara. Esto es contenido y no código.
- Es convencional: SSGs como Hugo, Jekyll usan carpetas similares
Se elige este directorio por: El archivo src/data/blogPosts.ts se sigue usando, este genera los componentes Blog.tsx y BlogPost.tsx. Para no editarlo manualmente se añadió un script que genera automáticamente el contenido desde el directorio content/blog
- El sitio usa LenguajeProvider con un hook y useLanguage() que retorna language ( “en” | “es” ).
- Los datos tienen campos tipo: { en: string; es: string }
- Los componentes usan const { language } = useLanguage() y se acceden con courses[0].title[language]
- Para implementar el soporte multi-idioma:
- Se modificará el directorio de cada post para contener versiones por idioma, un archivo por cada idioma (en este caso solo inglés-español, por ejemplo: index.es.md, index.en.md).
- Se modificará el script que genera el archito ts con que usan los compontes que genran el blog. Deben detectar los archivos con sufijos .es.md o en.md y generar la estructura tipo json adecuada.
- Para implementar el soporte multi-idioma:
- [X] Mudar el contenido “legacy” [100%]
- [X] Las tecnologías de internet en los movimientos sociales
- [X] CCOSS
- [X] Tayer para contribuir a Python
- [X] Introducción a Pandoc
- [X] Python: Zero To Hero
- [X] Introducción a redes neuronales: Un enfoque interpretativo
- [X] Salvemos el internet
- [X] FLSoL 2020
- [X] Seminario de Lisp 2020
- [X] Túneles y agentes de SSH
- [X] FLISoL 2022
- [X] FLISoL 2023
- [X] FLISoL 2024
- [X] Hay dos botones para el “enlace de registro”, me gustaría aprovechar mejor estos botones, con “registrarse” y otro para “acceder al curso” si es que este se dio en línea youtube/meet
- [X] Mejorar el redondeado de las imágenes de la descripción de eventsDetail
- [X] Solo vemos la fecha de inicio pero no del final
- [X] ¿Y Si un evento tiene más de un lugar de ubicación?
- [X] Mejor difuminado en el cover
- [X] Optimización de las imágenes
- [X] Mejorar la tarjeta de ponentes (que se use le nombre en vez del id y que redireccione a su perfil).
- [X] Mejorar el sombreado de eventsDetail
- [X] La tarjeta que muestra los ponentes tiene un bug 🐛
- [X] ¿Podríamos añadir un registro?
- [X] Añadir el nuevo evento flisol
- [X] Ubicación vs Ubicaciones. Hacerlo a modo de lista.
- [X] El “tag” de “próximamente” está en un campo de event.ts, que indica el estado del evento. Sería mejor que esto sea automático.
- [X] Verificar que la notificación de próximo evento y la tarjeta de eventos de src/components/LatestHighlights.tsx no tengan errores.
- [-] Calendario:
Este calendario está basado en la vista de GNOME Notifications/Calendar.
- [X] En el calendario de Events.tsx, se debe mostrar un punto debajo del día del evento
- [ ] Hacer que la notificación tenga el mismo ancho que el calendario.
- [X] Hacer que el calendario soporte el multi-idioma
- [X] Hacer que el color de la notificación sea más clara que el BG general
- [X] En Events.tsx, debajo del calendario, se debe mostrar un apartado de notificaciones que muestre todos los próximos eventos.
- [X] En el calendario de EventDetail.tsx muestra encerrado en un círculo el día del evento
- [-] Mejorar la sección de cronograma
- [X] Tener sub-items por día/hora
- [-] Añadir la información faltante de FLISOL 2026
- [ ] Añadir los ponentes faltantes
- [ ] Añadir los requermientos de los talleres
- [X] Actualizar la descripción
- [X] Añadir botón de registro al evento.
- [X] Añadir el botón de “Ayudar a los asistentes”.
- [ ] Mudar el contenido al sitio actual [0%]
- [ ] Seminario de lisp
- [ ] Fundamentos de Python
- [ ] PumaHat
- [ ] Curso básico de sysadmin GNU/Linux
- [ ] Curso de LaTeX
- [ ] Mejorar la responsividad
- [X] Las fechas están atrasadas por un día
- [X] Justificación completa en la descripción del curso y soporte para Markdown
- [ ] Sería bueno que los tags también soporten el multiidioma
- [ ] Cambiar el “enrolled” a “cupo”
- [ ] ¿Una subsección para contenido de cursos?
- [ ] ¿Sería bueno tener un backen para los cursos, por ejemplo para tener “gente registrada/apuntada” a los cursos?
- [ ] Igual y sería bueno cambiar el botón de Inscribirse ahora a “ver curso” y colocar el enlace a YouTube o a la llamada.
- [ ] Cambiar el botón de “Unirte al curso” a otra cosa como “ver curso”
- [ ] Mejorar el aspecto de la sección de “módulos del curso”
- [X] Mudar el contenido.
- [X] Añadir los “metadatos” a src/data/publications.tsx
- [X] Añadir los contenidos descargables (pdf)
- [X] Funcionalidades y aspecto
- [X] Subpágina con detalles de las publicaciones
- [X] Texto con justificado completo
- [X] Soporte de sintaxis markdown
- [X] Mostrar enlace si tienen los autores de la publicación tienen perfil en la página.
- [X] Botones
- [X] Código fuente
- [X] DOI
- [X] PDF
- [X] Citar
- [X] Animación en el contenido
- [X] Botón de Citar/ventana emergente de citar
- [X] Que sea un modulo independiente para usarlo dentro de Publication y PublicationDetail
- [X] Que se pueda copiar al portapapeles
- [X] Que puedas salir con ESC
- [X] Que no se desborde el contenido
- [X] La página de fondo debe estar más opaca que la ventana emergente.
- [X] Añadir desplazamiento
- [X] Subpágina con detalles de las publicaciones
- [X] Sección CTA con Mailto, es sencillo y se evita configurar un backend de correo o base de datos (que para esto no se requiere).**** About
- [X] Sería bueno que la zona de “Educado en” esté con dots.
- [X] ¿De dónde salió ese ícono de mail? ¿Nani Kore?? Borralo..
- [X] Faltan los intereses… v2.1.1
- [X] Si no hay cierto tipo de datos, se rompe el sitio 2.1.2
- [X] Si no hay bio se rompe el sitio
- [X] Si no hay rol se rompe el sitio
- [X] Mudar el contenido 2.1.3
- [X] Detalles visuales 2.1.4
- [X] Mostrar dos tarjetas en horizontal si el contenido se ve desde movil o desde una ventana pequeña.
- [X] Ocultar la bio, creo que no aporta tanto, y provoca que la tarjeta crezca demasiado en vertical.
- [X] Hacer que el botón de ver perfil se vea correcto.
- [X] Regularizar el tamaño de todas las tarjetas
- [X] Centrar el contenido sin cambiar su tamaño.
- [X] Subir la resolución de las imágenes con upscaler
- [X] Mejorar el color del botón cuando el cursor está sobré él en tema claro
- Tal vez en el futuro sea bueno añadir paginación, si crece mucho el número de miembros. Igual intentar con una base de datos… (si hay más de 50 miembros, tal vea hora de dejar el “json”).
Desactivar la ejecución automática de scripts y crear un por área (miembros, eventos, etc) para añadir info maś fácilmente sin la necesidad de meterte al ts
Tal vez sería bueno cambiar el texto de “Proyectos en desarrollo” del Home, pues hay algunas investigaciones que ya no están en curso.
en blog.tsx hay import { User, ArrowRight, Calendar, Clock } from “lucide-react”, etc
Cuando regreso a una página anterior, que no me regrese hasta el inicio, si no que se quede en el mismo sitio antes de dar click.
Al estar en dispositivos móviles, el efecto de brillo que sigue al cursos se queda pillado.
Hay un problema con las tarjetas de “Último curso, Último post de blog” en dispositivos móviels el contenido no se ve completo.
El sitio web de LIDSoL está construido sobre una arquitectura moderna de aplicaciones web de una sola página (SPA) utilizando las siguientes tecnologías principales:
- Framework frontend: React 18.3.1 con TypeScript para tipado estático
- Build tool: Vite 6.4.1 para desarrollo rápido y construcción optimizada
- Estilos: Tailwind CSS 4.x con plugin @tailwindcss/typography para contenido markdown
- Componentes UI: Radix UI (suite completa de primitivas accesibles) + shadcn/ui pattern
- Iconos: Lucide React
- Markdown: react-markdown con remark-gfm, remark-math, rehype-katex, react-syntax-highlighter
- Gráficos: Recharts para visualizaciones de datos
- Formularios: React Hook Form
- Animaciones: Motion (anteriormente Framer Motion)
- Procesamiento de imágenes: Sharp + vite-plugin-image-optimizer
- SVG: SVGO para optimización
sitio-web-lidsol/ ├── src/ │ ├── components/ │ │ ├── ui/ # Componentes UI reutilizables (Radix-based) │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── dialog.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── navigation-menu.tsx │ │ │ ├── tabs.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── carousel.tsx │ │ │ ├── chart.tsx │ │ │ └── [50+ componentes UI] │ │ ├── Header.tsx # Navegación principal │ │ ├── Footer.tsx # Pie de página │ │ ├── Hero.tsx # Sección hero de homepage │ │ ├── Values.tsx # Valores institucionales │ │ ├── Community.tsx # Sección comunidad │ │ ├── FeaturedProjects.tsx # Proyectos destacados │ │ ├── Blog.tsx # Listado de artículos │ │ ├── BlogPost.tsx # Vista individual de artículo │ │ ├── Projects.tsx # Catálogo de proyectos │ │ ├── ProjectDetail.tsx # Detalle de proyecto │ │ ├── About.tsx # Página nosotros │ │ ├── AboutMember.tsx # Perfil de miembro │ │ ├── Events.tsx # Calendario de eventos │ │ ├── EventDetail.tsx # Detalle de evento │ │ ├── Courses.tsx # Catálogo de cursos │ │ ├── CourseDetail.tsx # Detalle de curso │ │ ├── Publications.tsx # Publicaciones académicas │ │ ├── LanguageSelector.tsx # Selector de idioma │ │ ├── ThemeProvider.tsx # Provider de temas │ │ ├── LanguageProvider.tsx # Provider de i18n │ │ ├── CursorEffect.tsx # Efecto visual cursor │ │ └── Timeline.tsx # Componente timeline │ ├── data/ # Datos estáticos tipados │ │ ├── projects.ts # Catálogo de proyectos │ │ ├── members.ts # Miembros del laboratorio │ │ ├── events.ts # Eventos/cursos/talleres │ │ ├── courses.ts # Cursos disponibles │ │ └── blogPosts.ts # Artículos del blog (generado) │ ├── styles/ │ │ └── globals.css # Estilos globales │ ├── main.tsx # Entry point │ └── App.tsx # Componente raíz + routing ├── content/ │ └── blog/ # Artículos en Markdown │ └── [slug]/ │ ├── index.es.md # Versión española │ ├── index.en.md # Versión inglesa │ └── featured.png # Imagen de portada ├── scripts/ │ └── build-blog.js # Generador de blogPosts.ts desde markdown ├── public/ # Assets estáticos ├── build/ # Output de producción ├── vite.config.ts # Configuración de Vite ├── tailwind.config.js # Configuración de Tailwind ├── package.json # Dependencias y scripts ├── Containerfile # Definición de contenedor Docker └── .gitlab-ci.yml # Pipeline CI/CD (Hugo legacy)
El proyecto utiliza un sistema de hash-based routing implementado manualmente en App.tsx sin necesidad de libraries como React Router. El estado currentView determina qué componente renderizar basado en el hash de la URL:
#home- Homepage#blog/#blog/:id- Blog y artículos#projects/#projects/:id- Proyectos#about/#about/member/:id- Nosotros y miembros#events/#events/:id- Eventos#courses/#courses/:id- Cursos#publications- Publicaciones#contact- Scroll al footer
- ThemeProvider: Integración con
next-themespara soporte de temas oscuro/claro. Persiste la preferencia en localStorage. - LanguageProvider: Implementación custom de i18n con soporte para
esyen. ProveeuseLanguage()hook y contexto para todos los componentes.
Los datos están almacenados como objetos TypeScript en src/data/ con interfaces tipadas:
- Projects: Arreglo de objetos Project con soporte multiidioma en todos los campos de texto
- Members: Miembros categorizados (academic, student, formerStudents) con información de contacto
- Events/Courses: Eventos con fechas, descripciones y metadatos
- BlogPosts: Generado dinámicamente desde archivos Markdown
El sistema de blog utiliza un pipeline de build custom:
- Contenido: Archivos Markdown en
content/blog/[slug]/con frontmatter YAML - Generación:
scripts/build-blog.jsparsea directorios y generasrc/data/blogPosts.ts - Multilenguaje: Detecta archivos
index.es.mdeindex.en.mdpara cada post - Imágenes: Copia automáticamente imágenes del directorio del post a
public/blog-images/[slug]/ - Renderizado: ReactMarkdown con plugins para:
- GFM (GitHub Flavored Markdown)
- Math (KaTeX para fórmulas)
- Syntax highlighting (react-syntax-highlighter)
- Custom image handling
node scripts/build-blog.js && vite build- Ejecuta
build-blog.jspara generarblogPosts.ts - Vite compila el proyecto a
build/ - Optimiza imágenes con
vite-plugin-image-optimizer - Code splitting: chunks separados para
vendor(react, react-dom) yui(lucide, recharts) - Minificación con esbuild
- Sourcemaps deshabilitados en producción (seguridad)
Containerfile usa multi-stage build:
- Stage builder: Node 20 Alpine, instala dependencias, ejecuta build
- Stage runtime: Nginx Alpine sirve archivos estáticos desde
build/ - Configuración custom de Nginx en
container/nginx.conf
Vite configura headers de seguridad en modo desarrollo:
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=block
- Sourcemaps deshabilitados en producción
- Dependencias auditadas con
npm audit - Aliasing de packages en Vite para evitar conflictos de versiones
vite.config.ts incluye:
- Plugin React SWC para fast refresh
- Image optimizer con calidad 80% para PNG, JPEG, WebP, AVIF
- Alias
@pointing to./src - Code splitting manual (vendor, ui)
- Servidor en puerto 3000 con headers de seguridad
- CursorEffect: Efecto de brillo que sigue al cursor implementado en
CursorEffect.tsx - Diseño: Inspirado en libadwaita (bordes redondeados, colores específicos)
- Responsividad: Mobile-first con Tailwind
- Transiciones: Animaciones con Motion library
- Tipografía: Tailwind typography plugin para contenido markdown
- Actualizar .gitlab-ci.yml para construir con Vite y desplegar contenedor
- Implementar Service Worker para PWA/offline
- Agregar tests unitarios y de integración
- Migrar datos estáticos a CMS headless o base de datos
- Implementar SEO con meta tags dinámicos
- Agregar analytics y tracking
El proyecto usa una suite comprehensiva de componentes Radix UI:
- @radix-ui/react-accordion
- @radix-ui/react-dialog
- @radix-ui/react-dropdown-menu
- @radix-ui/react-navigation-menu
- @radix-ui/react-popover
- @radix-ui/react-select
- @radix-ui/react-tabs
- @radix-ui/react-tooltip
- @radix-ui/react-switch
- @radix-ui/react-slider
- @radix-ui/react-checkbox
- @radix-ui/react-radio-group
- Y 20+ más
Adicionalmente:
- embla-carousel-react (carousel)
- cmdk (command palette)
- input-otp (one-time password)
- react-day-picker (date picker)
- react-resizable-panels
- vaul (drawer)
- sonner (toast notifications)
- Build output en
build/ - Servido estáticamente via Nginx
- Docker container definido pero no integrado con CI/CD
El archivo .gitlab-ci.yml está configurado para Hugo (legacy), necesita actualización para el stack actual de Vite/React.