From 6cb688bd1b2285fb917194852fdc285c798d43cc Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Sat, 7 Jun 2025 20:17:01 +0200 Subject: Add new images and update portfolio layouts for enhanced presentation --- src/content.config.ts | 4 +- src/data/portfolio/mapa-ferrol.mdx | 37 +++- src/layouts/BlogSingleLayout.astro | 134 ++++++++++++ src/layouts/Layout.astro | 1 - src/layouts/PortfolioItemLayout.astro | 77 ------- src/layouts/PortfolioListLayout.astro | 137 ++++++++++++ src/layouts/PortfolioPageLayout.astro | 137 ------------ src/layouts/PortfolioSingleLayout.astro | 370 ++++++++++++++++++++++++++++++++ src/pages/blog/[id].astro | 125 +---------- src/pages/portfolio/[id].astro | 4 +- src/pages/portfolio/index.astro | 4 +- 11 files changed, 684 insertions(+), 346 deletions(-) create mode 100644 src/layouts/BlogSingleLayout.astro delete mode 100644 src/layouts/PortfolioItemLayout.astro create mode 100644 src/layouts/PortfolioListLayout.astro delete mode 100644 src/layouts/PortfolioPageLayout.astro create mode 100644 src/layouts/PortfolioSingleLayout.astro (limited to 'src') diff --git a/src/content.config.ts b/src/content.config.ts index f3d7755..acaaf8a 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -20,7 +20,9 @@ const portfolio = defineCollection({ githubLink: z.string().url().optional(), onlineLink: z.string().url().optional(), demoLink: z.string().url().optional(), - images: z.array(z.string()).default([]) + images: z.array( + z.object({ src: z.string(), alt: z.string() }) + ).default([]) }), }); diff --git a/src/data/portfolio/mapa-ferrol.mdx b/src/data/portfolio/mapa-ferrol.mdx index 144ac62..6152ced 100644 --- a/src/data/portfolio/mapa-ferrol.mdx +++ b/src/data/portfolio/mapa-ferrol.mdx @@ -3,16 +3,43 @@ title: "Mapa de patrimonio da Costa Ártabra" description: "Desarrollo de una aplicación completa para el patrimonio cultural y militar de la Costa Ártabra." technologies: ["dotnet", "react", "mysql", "ubuntu"] onlineLink: "https://mapacostaartabramilitar.com" +images: +- src: "/images/portfolio/mapa-ferrol/home-narrow" + alt: "Vista principal del mapa con los elementos del patrimonio" +- src: "/images/portfolio/mapa-ferrol/home-info-narrow" + alt: "Sheet con información de un elemento patrimonial" +- src: "/images/portfolio/mapa-ferrol/route-id-narrow" + alt: "Vista de una ruta predefinida" +- src: "/images/portfolio/mapa-ferrol/planner-narrow" + alt: "Planificador de rutas de senderismo" --- -Se desarrolló una aplicación web completa para la gestión del patrimonio cultural y militar de la Costa Ártabra, en Galicia, España. Esta aplicación permite a los usuarios explorar y descubrir el patrimonio de la región (Ferrol, Ares y Valdoviño) incluyendo las baterías militares, faros, iglesias, miradores, playas, etc. +Desarrollo de una **aplicación web integral** para la exploración del patrimonio cultural y militar de la Costa Ártabra (Ferrol, Ares, Valdoviño). La plataforma incluye baterías costeras, faros, rutas de senderismo y puntos de interés natural, ofreciendo una experiencia adaptada principalmente a dispositivos móviles. -La aplicación está desarrollada con ASP.NET Core y React, utilizando una base de datos MySQL para almacenar la información del patrimonio y permitir al personal de la administración añadir, editar y eliminar elementos del patrimonio. +Tecnologías clave: -Para la parte del frontend, se utilizó React con TypeScript, creando una interfaz de usuario intuitiva y fluida, adaptándose primordialmente a dispositivos móviles. Además, se implementó un mapa interactivo utilizando MapLibre y capas de OpenStreetMap (mapa base) y el PNOA (Satélite del IGN) para mostrar la ubicación de los elementos del patrimonio. +* Backend con ASP.NET Core y base de datos MySQL. +* Frontend en React (TypeScript) y mapas interactivos con MapLibre. +* Teselas vectoriales de OpenStreetMap con [Protomaps](https://protomaps.com/) para un mapa de alta calidad y buen rendimiento. +* Calculador de rutas autoalojado con [OSRM](https://project-osrm.org/) para optimización de rutas. -La aplicación también incluye un sistema de rutas de senderismo, tanto proporcionadas por la administración como generadas a medida por los usuarios, permitiendo a los visitantes explorar la región a su manera. +Diseñada para autonomía y privacidad: -Una complejidad destacable fue hacer la aplicación rápida y fluida para el usuario, para garantizar la mejor experiencia posible al navegar por el patrimonio, sobre todo desde dispositivos móviles en redes móviles. +* Infraestructura autoalojada (Ubuntu) sin dependencia de APIs comerciales. +* Optimización de rutas con motor de cálculo interno (OSRM). +* Panel de administración para gestión centralizada del patrimonio. + +## Características clave + +1. **Tecnologías autónomas**: Implementación sin dependencia de servicios externos (como Google Maps), garantizando privacidad del usuario y reducción de costos. + +2. **Gestión de recursos**: Solución personalizada para iconografía y capas de mapa, asegurando consistencia visual y eficiencia. + +3. **Planificación de rutas inteligente**: Sistema de optimización para senderismo basado en puntos patrimoniales, con énfasis en rendimiento y estabilidad. + +4. **Panel de administración**: Herramienta interna para gestión de contenido por personal no técnico. + + +--- Desarrollado en 2025 en colaboración con [Kendra](https://kendra.es/). diff --git a/src/layouts/BlogSingleLayout.astro b/src/layouts/BlogSingleLayout.astro new file mode 100644 index 0000000..0c3b934 --- /dev/null +++ b/src/layouts/BlogSingleLayout.astro @@ -0,0 +1,134 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import { getCollection, render } from "astro:content"; +import { type GetStaticPaths } from "astro"; + +interface Props { + entry: any; +} + +export const getStaticPaths: GetStaticPaths = async () => { + const entries = await getCollection("blog"); + return entries.map((entry: any) => ({ + params: { id: entry.id }, + props: { entry }, + })); +}; + +const { entry } = Astro.props; +const { Content } = await render(entry); +const formattedDate = new Date(entry.data.publishedAt).toLocaleDateString( + "es-ES", + { + year: "numeric", + month: "long", + day: "numeric", + weekday: "long", + }, +); + +const schema = { + "@context": "https://schema.org", + "@type": "BlogPosting", + headline: entry.data.title, + datePublished: entry.data.publishedAt.toISOString(), + keywords: entry.data.tags || [], + author: { + "@type": "Person", + name: "Ariel Costas Guerrero", + }, + publisher: { + "@type": "Person", + name: "Ariel Costas Guerrero", + url: "https://www.costas.dev", + image: { + "@type": "ImageObject", + url: "https://www.costas.dev/favicon.png", + }, + }, +}; +--- + + + + + diff --git a/src/pages/blog/[id].astro b/src/pages/blog/[id].astro index 3dc324a..8f02b65 100644 --- a/src/pages/blog/[id].astro +++ b/src/pages/blog/[id].astro @@ -1,11 +1,7 @@ --- -import Layout from "@/layouts/Layout.astro"; -import { getCollection, render } from "astro:content"; -import { type GetStaticPaths } from "astro"; - -interface Props { - entry: any; -} +import type { GetStaticPaths } from "astro"; +import { getCollection } from "astro:content"; +import BlogSingleLayout from "@/layouts/BlogSingleLayout.astro"; export const getStaticPaths: GetStaticPaths = async () => { const entries = await getCollection("blog"); @@ -16,119 +12,6 @@ export const getStaticPaths: GetStaticPaths = async () => { }; const { entry } = Astro.props; -const { Content } = await render(entry); -const formattedDate = new Date(entry.data.publishedAt).toLocaleDateString( - "es-ES", - { - year: "numeric", - month: "long", - day: "numeric", - weekday: "long", - }, -); - -const schema = { - "@context": "https://schema.org", - "@type": "BlogPosting", - headline: entry.data.title, - datePublished: entry.data.publishedAt.toISOString(), - keywords: entry.data.tags || [], - author: { - "@type": "Person", - name: "Ariel Costas Guerrero", - }, - publisher: { - "@type": "Person", - name: "Ariel Costas Guerrero", - url: "https://www.costas.dev", - image: { - "@type": "ImageObject", - url: "https://www.costas.dev/favicon.png", - }, - }, -}; --- - -