diff options
| -rw-r--r-- | astro.config.mjs | 22 | ||||
| -rw-r--r-- | src/data/blog/mapa-facil-protomaps.md | 72 | ||||
| -rw-r--r-- | src/i18n/en.json | 89 | ||||
| -rw-r--r-- | src/i18n/es.json | 89 | ||||
| -rw-r--r-- | src/i18n/index.ts | 34 | ||||
| -rw-r--r-- | src/layouts/ContactPageLayout.astro | 99 | ||||
| -rw-r--r-- | src/layouts/HomePageLayout.astro | 62 | ||||
| -rw-r--r-- | src/layouts/Layout.astro | 28 | ||||
| -rw-r--r-- | src/layouts/PortfolioPageLayout.astro | 113 | ||||
| -rw-r--r-- | src/layouts/TrajectoryPageLayout.astro | 81 | ||||
| -rw-r--r-- | src/pages/blog.xml.ts (renamed from src/pages/blog.xml.js) | 38 | ||||
| -rw-r--r-- | src/pages/en/contact.astro | 5 | ||||
| -rw-r--r-- | src/pages/en/index.astro | 5 | ||||
| -rw-r--r-- | src/pages/en/portfolio.astro | 5 | ||||
| -rw-r--r-- | src/pages/en/trajectory.astro | 5 | ||||
| -rw-r--r-- | src/pages/index.astro | 68 | ||||
| -rw-r--r-- | src/pages/portfolio/index.astro | 145 | ||||
| -rw-r--r-- | src/pages/trajectory.astro | 110 | ||||
| -rw-r--r-- | src/partials/Footer.astro | 26 | ||||
| -rw-r--r-- | src/partials/Header.astro | 17 | ||||
| -rw-r--r-- | styles/shared.scss | 3 |
21 files changed, 716 insertions, 400 deletions
diff --git a/astro.config.mjs b/astro.config.mjs index 843c997..12285a1 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -2,16 +2,30 @@ import sitemap from '@astrojs/sitemap'; import { defineConfig } from 'astro/config'; import mdx from '@astrojs/mdx'; +import { DEFAULT_LANGUAGE, LANGUAGE_CODES } from './src/i18n'; export default defineConfig({ compressHTML: true, site: "https://www.costas.dev", - integrations: [sitemap({ - priority: 0.5, - changefreq: 'weekly' - }), mdx()], + i18n: { + defaultLocale: DEFAULT_LANGUAGE, + locales: LANGUAGE_CODES, + routing: { + prefixDefaultLocale: false, + fallbackType: 'redirect', + redirectToDefaultLocale: true + } + }, + integrations: [ + sitemap({ + priority: 0.5, + changefreq: 'weekly' + }), + mdx() + ], build: { assets: 'assets', inlineStylesheets: 'never', }, + scopedStyleStrategy: 'where' });
\ No newline at end of file diff --git a/src/data/blog/mapa-facil-protomaps.md b/src/data/blog/mapa-facil-protomaps.md index 43f5309..acdc13b 100644 --- a/src/data/blog/mapa-facil-protomaps.md +++ b/src/data/blog/mapa-facil-protomaps.md @@ -46,46 +46,46 @@ Si estás usando tecnologías JavaScript (ya sea Vite con algún framework, o As ```html <!DOCTYPE html> <html lang="es"> - <head> - <!-- ... --> - <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.0.0/dist/maplibre-gl.min.css" /> - <style> - #map { - height: 100vh; - width: 100vw; - } - </style> - </head> - - <body> - <div id="map"></div> + <head> + <!-- ... --> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.0.0/dist/maplibre-gl.min.css" /> + <style> + #map { + height: 100vh; + width: 100vw; + } + </style> + </head> + + <body> + <div id="map"></div> - <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.0.0/dist/maplibre-gl.min.js"></script> - <script src="https://cdn.jsdelivr.net/npm/pmtiles-protocol@1.0.4/index.min.js"></script> - <script> - /* - * Si estás usando paquetes de npm o un importmap o similar, puedes importar los módulos así: - * import maplibregl from "maplibre-gl"; - * import * as pmtiles from "pmtiles"; - */ + <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.0.0/dist/maplibre-gl.min.js"></script> + <script src="https://cdn.jsdelivr.net/npm/pmtiles-protocol@1.0.4/index.min.js"></script> + <script> + /* + * Si estás usando paquetes de npm o un importmap o similar, puedes importar los módulos así: + * import maplibregl from "maplibre-gl"; + * import * as pmtiles from "pmtiles"; + */ - // Añadir el protocolo de pmtiles a MapLibre - let protocol = new pmtiles.Protocol(); - maplibregl.addProtocol('pmtiles', protocol.tile); + // Añadir el protocolo de pmtiles a MapLibre + let protocol = new pmtiles.Protocol(); + maplibregl.addProtocol('pmtiles', protocol.tile); - // Crear el mapa - const map = new maplibregl.Map({ - container: 'map', - style: '/miestilo.json', - bounds: [ - [2.0428702462744956, 41.263970142291704], - [2.243836537167097, 41.48757944350839] - ] - }); - </script> - </body> + // Crear el mapa + const map = new maplibregl.Map({ + container: 'map', + style: '/miestilo.json', + bounds: [ + [2.0428702462744956, 41.263970142291704], + [2.243836537167097, 41.48757944350839] + ] + }); + </script> + </body> </html> Y luego el archivo `miestilo.json` puedes descargarlo de [maps.protomaps.com](https://maps.protomaps.com/#map=0.89/0/0&theme=light&lang=en&tiles=https://demo-bucket.protomaps.com/v4.pmtiles&local_sprites=true) clicando en "Get style JSON" y guardándolo en tu servidor. Cambias la ruta a tu pmtiles y ya. Y puedes usar cualquier otro estilo para MapLibre, como los de [OpenMapTiles](https://openmaptiles.org/styles/) mismamente, o hacer uno propio con algo como [Maputnik](https://maputnik.github.io/editor/). -Y con esto, ya tienes un mapa vectorial personalizado de Barcelona, servido desde tu servidor estático, sin tener que preocuparte de configurar un servidor de mapas ni costes adicionales. Y puedes personalizarlo todo lo que quieras, desde los colores hasta los datos que se muestran. Sin cargar pesados SDKs desde CDNs, sin depender de terceros, y sin el riesgo de una factura deorbitada porque te pasaste de peticiones.
\ No newline at end of file +Y con esto, ya tienes un mapa vectorial personalizado de Barcelona, servido desde tu servidor estático, sin tener que preocuparte de configurar un servidor de mapas ni costes adicionales. Y puedes personalizarlo todo lo que quieras, desde los colores hasta los datos que se muestran. Sin cargar pesados SDKs desde CDNs, sin depender de terceros, y sin el riesgo de una factura deorbitada porque te pasaste de peticiones. diff --git a/src/i18n/en.json b/src/i18n/en.json new file mode 100644 index 0000000..1c4c1b1 --- /dev/null +++ b/src/i18n/en.json @@ -0,0 +1,89 @@ +{ + "header": { + "home": "Home", + "trajectory": "Trajectory", + "portfolio": "Portfolio", + "blog": "Blog", + "contact": "Contact" + }, + "footer": { + "copyright": "All rights reserved.", + "contentLicencedUnder": "Unless otherwise stated, the content of this site is licensed under", + "sourceCodeAvailableOn": "Source code for this site is available on", + "andIsLicencedUnder": "and is licenced under", + "eupl": "European Union Public Licence" + }, + "contactPage": { + "title": "Contact", + "description": "The ways to contact me, either by email, phone or social networks.", + "headline": "Get in touch with me!", + "enableJs": "JavaScript must be enabled to view the email address and phone number. This is done to prevent scrapers and spam.", + "intro": "The easiest way to contact me is through my email address: <a href=\"#\" id=\"email-addr\">Enable JS</a>. You can also use <a href=\"https://wa.me/message/W7T7L4EZAELQI1\">WhatsApp</a> with the phone number <a href=\"#\" id=\"phone-number\">Enable JS</a>.", + "socialMedia": "You can also find me on some social networks:" + }, + "homePage": { + "title": "Home", + "description": "Homepage of my website", + "welcome": "Welcome to my website. My name is Ariel, and here you will find information about me and my projects.", + "whoAmI": "Who am I?", + "whoAmIDesc": "I am a web developer who likes to learn new things and share knowledge. I enjoy programming, web design, and creativity. I love creating new things and learning from others.", + "moreAboutMe": "More about me", + "whatIDo": "What do I do?", + "whatIDoDesc": "I currently work as a software developer and Cloud administrator at a technology company. I develop web applications in PHP and deploy them in the cloud securely and efficiently.", + "myPortfolio": "My portfolio", + "latestBlogPosts": "Latest blog posts", + "viewAllPosts": "View all posts" + }, + "trajectoryPage": { + "title": "Trajectory", + "description": "My trajectory as a software developer, with information about my education, work experience and projects I have worked on.", + "headline": "My trajectory as a developer", + "intro": "I am a software developer living in Vigo, Spain. I love technology and I enjoy learning new things. I am professionally dedicated to software development in all its aspects: from architecture design, implementation and production deployment, to other aspects such as user experience, accessibility and security.", + "techTitle": "Technologies I master", + "techDescription1": "I mainly master the Microsoft ecosystem: .NET (C#), ASP.NET Core, SQL Server, Azure and Azure DevOps. I also have experience with other languages and technologies, such as PHP, Python and Java. Additionally, I have frontend knowledge with HTML5, CSS3, JavaScript and TypeScript.", + "techDescription2": "I also have experience with DevOps tools such as Docker, Kubernetes, Terraform and GitHub Actions; as well as the Azure Cloud ecosystem.", + "educationTitle": "Education and credentials", + "efsetCert1": "Official EF SET C2 Proficient Certificate", + "efsetCert2": ": certifies my C2 English level, the highest according to the Common European Framework of Reference for Languages.", + "viewCertificate": "View certificate", + "azureDeveloperCert1": "Microsoft Certified: Azure Developer Associate", + "azureDeveloperCert2": ": certifies my knowledge in Azure application development.", + "viewCredential": "View credential", + "azureDevOpsCert1": "Microsoft Certified: Azure DevOps Engineer Expert", + "azureDevOpsCert2": ": certifies my knowledge in implementing DevOps methodologies in Azure with Azure DevOps and GitHub.", + "higherTechCert1": "Higher Technical Certificate in Multiplatform Application Development", + "higherTechCert2": ": higher vocational training degree, obtained at", + "higherTechCert3": "IES de Teis", + "higherTechCert4": "in Vigo.", + "experienceTitle": "Work experience", + "estelaria1": "Estelaria Solutions (Q3 2023 - present)", + "estelaria2": "Full-stack application development, mainly in PHP with Symfony, MongoDB and Vanilla JavaScript. In addition, I implemented a considerable number of improvements in usability, accessibility and performance.", + "estelaria3": "I am also responsible for managing the infrastructure on AWS, and implementing collaboration tools such as Jira and GitHub.", + "polygon1": "Internship at Polygon-E (Q2 2023)", + "polygon2": "I did my professional training internship at Polygon-E, where I developed several internal management applications with ASP.NET Core and Blazor, deploying on on-premise environments with Windows Server, IIS and SQL Server.", + "projectsTitle": "Projects", + "projectsDescription": "You can find the (public) projects I have worked on in <a href=\"/portfolio\">my portfolio</a> and on my <a href=\"https://github.com/arielcostas\">GitHub profile</a>." + }, + "portfolioPage": { + "title": "Portfolio", + "description": "A list of projects I have worked on in recent years, with the technologies used.", + "headline": "My portfolio", + "intro": "In this section, you will find a list of the projects I have worked on, both for third parties and my own. If you would like more information about any of them, please do not hesitate to <a href=\"/contact\">contact me</a>.", + "freelanceTitle": "Projects for third parties (freelance)", + "freelanceDesc": "I have developed projects for third parties by commission, the most notable being the following:", + "orderExtractorTitle": "Online Order Purchase Extractor", + "orderExtractorDesc": "Desktop application that extracts data about online orders from various platforms (such as WooCommerce, Amazon, and eBay). <a href=\"/portfolio/order-extractor\">More information</a>.", + "touristInfoTitle": "Tourist Information Point on Mobile Devices", + "touristInfoDesc": "Web application for tourist information, with QR codes, 360° content, and YouTube embedding. <a href=\"/portfolio/dynamic-tourist-info\">More information</a>.", + "wpConsultingTitle": "WordPress Consulting", + "wpConsultingDesc": "Maintenance, optimisation, and migration work for WordPress websites and WooCommerce online shops. <a href=\"/portfolio/wp-consulting\">More information</a>. <a href=\"/contact\">Contact</a>.", + "ownProjectsTitle": "My own projects", + "ownProjectsDesc": "Additionally, I have several personal projects that I have developed in my own time, some of which are active and open source.", + "personalWebTitle": "Personal Website", + "personalWebDesc": "Developed with Astro, a static site generator that lets you write content in Markdown and publish to the web with excellent performance. Deployed on Azure Static Web Apps.", + "mientrenoTitle": "MiEntreno (end-of-course project)", + "mientrenoDesc": "Web application for managing sports training, with a simple and easy-to-use interface. Developed with ASP.NET Core, Razor Pages, and SQL Server. <a href=\"/portfolio/mientreno\">More information</a>. <a href=\"https://github.com/arielcostas/mientreno\">Source code</a>.", + "vigo360Title": "Vigo 360", + "vigo360Desc": "Blog about Vigo and its surroundings, mainly focused on mobility and toponymy. Developed in Go, with a MySQL database and deployed on a VPS managed by myself. <a href=\"/portfolio/vigo-360\">More information</a>. <a href=\"https://github.com/arielcostas/vigo360\">Source code</a>. <a href=\"https://vigo360.es\">Website</a>." + } +}
\ No newline at end of file diff --git a/src/i18n/es.json b/src/i18n/es.json new file mode 100644 index 0000000..0e6e8bb --- /dev/null +++ b/src/i18n/es.json @@ -0,0 +1,89 @@ +{ + "header": { + "home": "Inicio", + "trajectory": "Trayectoria", + "portfolio": "Portafolio", + "blog": "Blog", + "contact": "Contacto" + }, + "footer": { + "copyright": "Todos los derechos reservados.", + "contentLicencedUnder": "Salvo que se indique lo contrario, el contenido de este sitio está bajo licencia", + "sourceCodeAvailableOn": "El código fuente de este sitio está disponible en", + "andIsLicencedUnder": "y se ofrece bajo licencia", + "eupl": "Licencia Pública de la Unión Europea" + }, + "contactPage": { + "title": "Contacto", + "description": "Las formas de ponerte en contacto conmigo, ya sea por correo electrónico, teléfono o redes sociales.", + "headline": "¡Ponte en contacto conmigo!", + "enableJs": "Es necesario activar JavaScript para ver la dirección de correo electrónico y el número de teléfono. Esto se hace para evitar scrapers y spam.", + "intro": "La forma más sencilla de contactar conmigo es a través de mi dirección de correo electrónico: <a href=\"#\" id=\"email-addr\">Activa JS</a>. También puedes usar <a href=\"https://wa.me/message/W7T7L4EZAELQI1\">WhatsApp</a> con el número de teléfono <a href=\"#\" id=\"phone-number\">Activa JS</a>.", + "socialMedia": "También puedes encontrarme en algunas redes sociales:" + }, + "homePage": { + "title": "Inicio", + "description": "Página de inicio de mi web", + "welcome": "Te doy la bienvenida a mi web. Me llamo Ariel, y aquí encontrarás información sobre mí y mis proyectos.", + "whoAmI": "¿Quién soy?", + "whoAmIDesc": "Soy un desarrollador web que le gusta aprender cosas nuevas y compartir su conocimiento. Me gusta la programación, el diseño web y la creatividad. Me encanta crear cosas nuevas y aprender de los demás.", + "moreAboutMe": "Más información sobre mí", + "whatIDo": "¿Qué hago?", + "whatIDoDesc": "Actualmente trabajo como desarrollador de software y administrador Cloud en una empresa de tecnología. Me encargo de desarrollar aplicaciones web en PHP y desplegarlas en la nube de forma segura y eficiente.", + "myPortfolio": "Mi portfolio", + "latestBlogPosts": "Últimas entradas del blog", + "viewAllPosts": "Ver todas las entradas" + }, + "trajectoryPage": { + "title": "Trayectoria", + "description": "Mi trayectoria como desarrollador de software, con información sobre mi educación, experiencia laboral y proyectos en los que he trabajado.", + "headline": "Mi trayectoria como desarrollador", + "intro": "Soy un desarrollador de software que vive en Vigo, España. Me gusta mucho la tecnología, y me gusta aprender cosas nuevas. Me dedico profesionalmente al desarrollo de software en todos sus ámbitos: desde el diseño de la arquitectura, la implementación y el despliegue en producción, pasando por otros aspectos como la experiencia de usuario, la accesibilidad y la seguridad.", + "techTitle": "Tecnologías que domino", + "techDescription1": "Domino principalmente el ecosistema de Microsoft: .NET (C#), ASP.NET Core, SQL Server, Azure y Azure DevOps. También tengo experiencia con otros lenguajes y tecnologías, como PHP, Python y Java. Además, tengo conocimientos de frontend con HTML5, CSS3, JavaScript y TypeScript.", + "techDescription2": "También tengo experiencia con herramientas de DevOps como Docker, Kubernetes, Terraform y GitHub Actions; así como el ecosistema Cloud de Azure.", + "educationTitle": "Educación y credenciales", + "efsetCert1": "Certificado oficial EF SET C2 Proficient", + "efsetCert2": ": acredita mi nivel de inglés C2, el más alto según el Marco Común Europeo de Referencia para las Lenguas.", + "viewCertificate": "Ver certificado", + "azureDeveloperCert1": "Microsoft Certified: Azure Developer Associate", + "azureDeveloperCert2": ": acredita mis conocimientos en el desarrollo de aplicaciones en Azure.", + "viewCredential": "Ver credencial", + "azureDevOpsCert1": "Microsoft Certified: Azure DevOps Engineer Expert", + "azureDevOpsCert2": ": acredita mis conocimientos en la implementación de metodologías de DevOps en Azure con Azure DevOps y GitHub.", + "higherTechCert1": "Técnico Superior en Desarrollo de Aplicaciones Multiplataforma", + "higherTechCert2": ": título de formación profesional de grado superior, obtenido en el", + "higherTechCert3": "IES de Teis", + "higherTechCert4": "en Vigo.", + "experienceTitle": "Experiencia laboral", + "estelaria1": "Estelaria Solutions (Q3 2023 - actualidad)", + "estelaria2": "Desarrollo de aplicaciones full-stack, principalmente en PHP con Symfony, MongoDB y JavaScript Vanilla. Además, implementé una cantidad considerable de mejoras en usabilidad, accesibilidad y rendimiento.", + "estelaria3": "También me encargo de la gestión de la infraestructura en AWS, y de la implementación de herramientas de colaboración como Jira y GitHub.", + "polygon1": "FCT en Polygon-E (Q2 2023)", + "polygon2": "Realicé mis prácticas de formación profesional en la empresa Polygon-E, donde desarrollé varias aplicaciones de gestión interna con ASP.NET Core y Blazor, desplegando sobre entornos on-premise con Windows Server, IIS y SQL Server.", + "projectsTitle": "Proyectos", + "projectsDescription": "Puedes encontrar los proyectos (públicos) en los que he trabajado en <a href=\"/portfolio\">mi portfolio</a> y en mi <a href=\"https://github.com/arielcostas\">perfil de GitHub</a>." + }, + "portfolioPage": { + "title": "Portfolio", + "description": "Un listado de los proyectos en los que he trabajado en los últimos años, con las tecnologías utilizadas.", + "headline": "Mi portfolio", + "intro": "En esta sección encontrarás una lista de los proyectos en los que he trabajado, tanto para terceros como propios. Si quieres más información sobre alguno de ellos, no dudes en <a href=\"/contact\">contactar conmigo</a>.", + "freelanceTitle": "Proyectos para terceros (freelance)", + "freelanceDesc": "He realizado desarrollos de proyectos para terceros por encargo, siendo los más destacados los siguientes:", + "orderExtractorTitle": "Extractor de pedidos compra online", + "orderExtractorDesc": "Aplicación de escritorio que extrae los datos sobre los pedidos on-line de diversas plataformas (como WooCommerce, Amazon y Ebay). <a href=\"/portfolio/order-extractor\">Más información</a>.", + "touristInfoTitle": "Punto de información turística en móviles", + "touristInfoDesc": "Aplicación web de información turística, con QR, contenido en 360º e incrustado de YouTube. <a href=\"/portfolio/dynamic-tourist-info\">Más información</a>.", + "wpConsultingTitle": "Consultoría WordPress", + "wpConsultingDesc": "Trabajos de mantenimiento, optimización y migración de sitios web WordPress y tiendas online WooCommerce. <a href=\"/portfolio/wp-consulting\">Más información</a>. <a href=\"/contact\">Contactar</a>.", + "ownProjectsTitle": "Proyectos propios", + "ownProjectsDesc": "Además, tengo varios proyectos propios que he desarrollado en mi tiempo, estando algunos de ellos en activo, y como código abierto.", + "personalWebTitle": "Web personal", + "personalWebDesc": "Desarrollado con Astro, un generador de sitios web estáticos que permite escribir contenido en Markdown y publicar en la web con un rendimiento excelente. Desplegado sobre Azure Static Web Apps.", + "mientrenoTitle": "MiEntreno (proyecto fin de ciclo)", + "mientrenoDesc": "Aplicación web para la gestión de entrenamientos deportivos, con una interfaz sencilla y fácil de usar. Desarrollado con ASP.NET Core, Razor Pages y SQL Server. <a href=\"/portfolio/mientreno\">Más información</a>. <a href=\"https://github.com/arielcostas/mientreno\">Código fuente</a>.", + "vigo360Title": "Vigo 360", + "vigo360Desc": "Blog sobre Vigo y su entorno, orientado principalmente a hablar de movilidad y toponimia. Desarrollado en Go, con base de datos MySQL y desplegado sobre VPS administrado por mí mismo. <a href=\"/portfolio/vigo-360\">Más información</a>. <a href=\"https://github.com/arielcostas/vigo360\">Código fuente</a>. <a href=\"https://vigo360.es\">Web</a>." + } +}
\ No newline at end of file diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..4ed1a52 --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,34 @@ +import Spanish from './es.json'; +import English from './en.json'; + +export const SHOW_DEFAULT_LANGUAGE = false; +export const DEFAULT_LANGUAGE = "es"; + +export type LanguageKeys = "es" | "en"; + +export const languages: Record<LanguageKeys, { code: string, name: string }> = { + es: { + code: "es", + name: "Español" + }, + en: { + code: "en", + name: "English" + } +} + +export const LANGUAGE_CODES = Object.keys(languages); + +export const useTranslations = (lang: string | undefined) => { + switch (lang) { + case languages.en.code: + return English; + case languages.es.code: + default: + return Spanish; + } +} + +export function getUrlWithoutLocale(url: string) { + return url.replace(/\/[a-z]{2}\//, "/"); +}
\ No newline at end of file diff --git a/src/layouts/ContactPageLayout.astro b/src/layouts/ContactPageLayout.astro new file mode 100644 index 0000000..3b3c278 --- /dev/null +++ b/src/layouts/ContactPageLayout.astro @@ -0,0 +1,99 @@ +--- +import { useTranslations } from "../i18n"; +import Layout from "./Layout.astro"; + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "https://schema.org", + "@type": "ContactPage", + url: "https://www.costas.dev/contact", + headline: t.contactPage.headline, +}; +--- + +<Layout title={t.contactPage.title} description={t.contactPage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.contactPage.headline}</h1> + + <noscript> + <div role="alert" class="warning"> + {t.contactPage.enableJs} + </div> + </noscript> + + <p set:html={t.contactPage.intro} /> + + <p>{t.contactPage.socialMedia}</p> + + <dl> + <dt>GitHub</dt> + <dd><a href="https://github.com/arielcostas">@arielcostas</a></dd> + <dt>LinkedIn</dt> + <dd> + <a href="https://www.linkedin.com/in/ariel-costas/" + >/in/ariel-costas</a> + </dd> + <dt>BlueSky</dt> + <dd><a href="https://bsky.app/profile/costas.dev">@costas.dev</a></dd> + </dl> +</Layout> + +<script> + const encryptedEmail = "LygNLiMmFRo/GlQZaFIWBA=="; + const encryptedPhoneNumber = "ZWlQfX1QT0Z+XgVd"; + const key = "NZdKOfvuLn5jF6sryF0Q"; + + const emailAddrLink = document.getElementById( + "email-addr", + ) as HTMLAnchorElement; + const phoneNumberLink = document.getElementById( + "phone-number", + ) as HTMLAnchorElement; + + (() => { + if (emailAddrLink == null || phoneNumberLink == null) { + return; + } + + const emailAddress = xorData(encryptedEmail, key); + const phoneNumber = xorData(encryptedPhoneNumber, key); + + emailAddrLink.href = `mailto:${emailAddress}`; + emailAddrLink.textContent = emailAddress; + + phoneNumberLink.href = `tel:${phoneNumber}`; + phoneNumberLink.textContent = phoneNumber; + })(); + + function xorData(data: string, key: string): string { + let actualData = atob(data); + let actualKey = key; + const keyLength = key.length; + const dataLength = actualData.length; + const result = new Array(dataLength); + + // If the key is 12 characters but the data is 30 characters, the key should be repeated 3 times and truncated to 30 characters + if (keyLength < dataLength) { + actualKey = key + .repeat(Math.ceil(dataLength / keyLength)) + .substring(0, dataLength); + } else if (keyLength > dataLength) { + actualKey = key.substring(0, dataLength); + } + + for (let i = 0; i < dataLength; i++) { + result[i] = String.fromCharCode( + actualData.charCodeAt(i) ^ actualKey.charCodeAt(i), + ); + } + + return result.join(""); + } +</script> diff --git a/src/layouts/HomePageLayout.astro b/src/layouts/HomePageLayout.astro new file mode 100644 index 0000000..146eaec --- /dev/null +++ b/src/layouts/HomePageLayout.astro @@ -0,0 +1,62 @@ +--- +import { getCollection } from "astro:content"; +import Layout from "./Layout.astro"; +import { useTranslations } from "../i18n"; + +const blogCollection = (await getCollection("blog")).sort((a, b) => { + return b.data.publishedAt.getTime() - a.data.publishedAt.getTime(); +}); + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "http://schema.org", + "@type": "WebSite", + id: "https://www.costas.dev/", + url: "https://www.costas.dev/", + headline: t.homePage.title, +}; +--- + +<Layout title={t.homePage.title} description={t.homePage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.homePage.title}</h1> + <p>{t.homePage.welcome}</p> + + <h2>{t.homePage.whoAmI}</h2> + <p>{t.homePage.whoAmIDesc}</p> + <a href="/trajectory">{t.homePage.moreAboutMe}</a> + + <h2>{t.homePage.whatIDo}</h2> + <p>{t.homePage.whatIDoDesc}</p> + <a href="/portfolio">{t.homePage.myPortfolio}</a> + + <h2>{t.homePage.latestBlogPosts}</h2> + <ul> + { + blogCollection.slice(0, 5).map((p) => { + const date = Intl.DateTimeFormat(Astro.currentLocale, { + day: "2-digit", + month: "short", + year: "numeric", + }).format(p.data.publishedAt); + return ( + <li> + <time datetime={p.data.publishedAt.toISOString()}> + {date} + </time> + <a href={`/blog/${p.id}`}>{p.data.title}</a> + </li> + ); + }) + } + </ul> + <a href="/blog">{t.homePage.viewAllPosts}</a> + +</Layout> diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 4952d55..eda1716 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -13,7 +13,7 @@ const { title, description } = Astro.props; --- <!doctype html> -<html lang="es"> +<html lang={Astro.currentLocale}> <head> <meta charset="UTF-8" /> <meta name="description" content={description} /> @@ -53,6 +53,7 @@ const { title, description } = Astro.props; <style is:global lang="scss"> @use "../../styles/shared.scss" as *; + @use "sass:color"; html, body { @@ -82,7 +83,7 @@ const { title, description } = Astro.props; } *::selection { - background-color: transparentize($accent, 0.85); + background-color: color.adjust($accent, $alpha: -0.85); } li > time { @@ -93,12 +94,17 @@ const { title, description } = Astro.props; padding: 1rem; margin-block: 1rem; border-radius: 0.5rem; - - box-shadow: 0 0 0 1px $accent; - + &.note { background-color: $noteBackground; color: $noteText; + box-shadow: 0 0 0 1px $noteText; + } + + &.warning { + background-color: $warningBackground; + color: $warningText; + box-shadow: 0 0 0 1px $warningText; } } @@ -132,10 +138,15 @@ const { title, description } = Astro.props; } } - main a, footer a { + main a { color: $accentDark; - transition: color 0.2s ease-in-out, - box-shadow 0.2s ease-in-out; + } + + footer a { + color: $accentLight; + } + + main a, footer a { text-decoration: none; padding: 0.1rem; box-shadow: 0 1px $accent; @@ -145,6 +156,7 @@ const { title, description } = Astro.props; } &:focus { + color: $accentDark; outline: none; background-color: $secondary; box-shadow: 0 4px #0b0c0c; diff --git a/src/layouts/PortfolioPageLayout.astro b/src/layouts/PortfolioPageLayout.astro new file mode 100644 index 0000000..0ade4ba --- /dev/null +++ b/src/layouts/PortfolioPageLayout.astro @@ -0,0 +1,113 @@ +--- +import Layout from "./Layout.astro"; +import { useTranslations } from "../i18n"; +import TechnologyBadge from "../partials/TechnologyBadge.astro"; + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "https://schema.org", + "@type": "WebPage", + url: "https://www.costas.dev/portfolio", + headline: t.portfolioPage.headline, +}; +--- + +<Layout title={t.portfolioPage.title} description={t.portfolioPage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + ></script> + + <h1>{t.portfolioPage.headline}</h1> + + <p set:html={t.portfolioPage.intro} /> + + <h2>{t.portfolioPage.freelanceTitle}</h2> + + <p>{t.portfolioPage.freelanceDesc}</p> + + <section> + <article> + <h3>{t.portfolioPage.orderExtractorTitle}</h3> + + <p set:html={t.portfolioPage.orderExtractorDesc} /> + + <TechnologyBadge code="java" /> + <TechnologyBadge code="windows" /> + </article> + + <article> + <h3>{t.portfolioPage.touristInfoTitle}</h3> + + <p set:html={t.portfolioPage.touristInfoDesc} /> + + <TechnologyBadge code="php" /> + <TechnologyBadge code="mysql" /> + </article> + + <article> + <h3>{t.portfolioPage.wpConsultingTitle}</h3> + + <p set:html={t.portfolioPage.wpConsultingDesc} /> + + <TechnologyBadge code="php" /> + </article> + </section> + + <h2>{t.portfolioPage.ownProjectsTitle}</h2> + + <p>{t.portfolioPage.ownProjectsDesc}</p> + + <section> + <article> + <h3>{t.portfolioPage.personalWebTitle}</h3> + + <p>{t.portfolioPage.personalWebDesc}</p> + + <TechnologyBadge code="astro" /> + <TechnologyBadge code="azure" /> + </article> + + <article> + <h3>{t.portfolioPage.mientrenoTitle}</h3> + + <p set:html={t.portfolioPage.mientrenoDesc} /> + + <TechnologyBadge code="dotnet" /> + <TechnologyBadge code="sqlserver" /> + <TechnologyBadge code="azure" /> + <TechnologyBadge code="rabbitmq" /> + </article> + + <article> + <h3>{t.portfolioPage.vigo360Title}</h3> + + <p set:html={t.portfolioPage.vigo360Desc} /> + + <TechnologyBadge code="go" /> + <TechnologyBadge code="mysql" /> + <TechnologyBadge code="linux" /> + </article> + </section> +</Layout> + +<style> + section { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + gap: 1rem; + } + + article { + padding: 1rem; + border: 1px solid var(--accent); + border-radius: 0.5rem; + } + + article h3 { + margin-top: 0; + } +</style>
\ No newline at end of file diff --git a/src/layouts/TrajectoryPageLayout.astro b/src/layouts/TrajectoryPageLayout.astro new file mode 100644 index 0000000..1739a32 --- /dev/null +++ b/src/layouts/TrajectoryPageLayout.astro @@ -0,0 +1,81 @@ +--- +import { useTranslations } from "../i18n"; +import Layout from "./Layout.astro"; + +const t = useTranslations(Astro.currentLocale); + +const schema = { + "@context": "https://schema.org", + "@type": "WebPage", + url: "https://www.costas.dev/trajectory", + headline: t.trajectoryPage.headline, +}; +--- + +<Layout title={t.trajectoryPage.title} description={t.trajectoryPage.description}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{t.trajectoryPage.headline}</h1> + + <p>{t.trajectoryPage.intro}</p> + + <h2>{t.trajectoryPage.techTitle}</h2> + + <p>{t.trajectoryPage.techDescription1}</p> + + <p>{t.trajectoryPage.techDescription2}</p> + + <h2>{t.trajectoryPage.educationTitle}</h2> + + <ul> + <li> + <strong>{t.trajectoryPage.efsetCert1}</strong> + {t.trajectoryPage.efsetCert2} <a + href="https://cert.efset.org/es/Yxzc9L" + >{t.trajectoryPage.viewCertificate}</a + > + </li> + + <li> + <strong>{t.trajectoryPage.azureDeveloperCert1}</strong> + {t.trajectoryPage.azureDeveloperCert2} <a + href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/E15072607CCF2DA9?sharingId=149A1CD9C13790F4" + >{t.trajectoryPage.viewCredential}</a + >. + </li> + + <li> + <strong>{t.trajectoryPage.azureDevOpsCert1}</strong> + {t.trajectoryPage.azureDevOpsCert2} <a + href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/5FB94876A1701595?sharingId=149A1CD9C13790F4" + >{t.trajectoryPage.viewCredential}</a + > + </li> + + <li> + <strong>{t.trajectoryPage.higherTechCert1}</strong> + {t.trajectoryPage.higherTechCert2} <a href="https://iesteis.es/">{t.trajectoryPage.higherTechCert3}</a> {t.trajectoryPage.higherTechCert4} + </li> + </ul> + + <h2>{t.trajectoryPage.experienceTitle}</h2> + + <h3>{t.trajectoryPage.estelaria1}</h3> + + <p>{t.trajectoryPage.estelaria2}</p> + + <p>{t.trajectoryPage.estelaria3}</p> + + <h3>{t.trajectoryPage.polygon1}</h3> + + <p>{t.trajectoryPage.polygon2}</p> + + <h2>{t.trajectoryPage.projectsTitle}</h2> + + <p set:html={t.trajectoryPage.projectsDescription} /> +</Layout> diff --git a/src/pages/blog.xml.js b/src/pages/blog.xml.ts index b4fbe38..f165475 100644 --- a/src/pages/blog.xml.js +++ b/src/pages/blog.xml.ts @@ -1,19 +1,19 @@ -import rss from '@astrojs/rss';
-import { getCollection } from 'astro:content';
-
-
-export async function GET(context) {
- const collection = await getCollection('blog');
-
- return rss({
- title: "Blog de Ariel Costas",
- description: "Artículos del blog de Ariel Costas",
- site: context.site,
- items: collection.map((post) => ({
- title: post.data.title,
- link: `${context.site}blog/${post.slug}`,
- description: post.data.metaDescription,
- pubDate: post.data.publishedAt
- }))
- })
-}
+import rss from '@astrojs/rss'; +import { getCollection } from 'astro:content'; + + +export async function GET(context: any) { + const collection = await getCollection('blog'); + + return rss({ + title: "Blog de Ariel Costas", + description: "Artículos del blog de Ariel Costas", + site: context.site, + items: collection.map((post: any) => ({ + title: post.data.title, + link: `${context.site}blog/${post.slug}`, + description: post.data.metaDescription, + pubDate: post.data.publishedAt + })) + }) +} diff --git a/src/pages/en/contact.astro b/src/pages/en/contact.astro new file mode 100644 index 0000000..ef69d6e --- /dev/null +++ b/src/pages/en/contact.astro @@ -0,0 +1,5 @@ +--- +import ContactPageLayout from "../../layouts/ContactPageLayout.astro"; +--- + +<ContactPageLayout />
\ No newline at end of file diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro new file mode 100644 index 0000000..8c5945a --- /dev/null +++ b/src/pages/en/index.astro @@ -0,0 +1,5 @@ +--- +import HomePageLayout from "../../layouts/HomePageLayout.astro"; +--- + +<HomePageLayout />
\ No newline at end of file diff --git a/src/pages/en/portfolio.astro b/src/pages/en/portfolio.astro new file mode 100644 index 0000000..63840f5 --- /dev/null +++ b/src/pages/en/portfolio.astro @@ -0,0 +1,5 @@ +--- +import PortfolioPageLayout from "../../layouts/PortfolioPageLayout.astro"; +--- + +<PortfolioPageLayout />
\ No newline at end of file diff --git a/src/pages/en/trajectory.astro b/src/pages/en/trajectory.astro new file mode 100644 index 0000000..3f5ff77 --- /dev/null +++ b/src/pages/en/trajectory.astro @@ -0,0 +1,5 @@ +--- +import TrajectoryPageLayout from "../../layouts/TrajectoryPageLayout.astro"; +--- + +<TrajectoryPageLayout />
\ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index fcef172..8ac64a6 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,69 +1,5 @@ --- -import { getCollection } from "astro:content"; -import Layout from "../layouts/Layout.astro"; - -const blogCollection = (await getCollection("blog")).sort((a, b) => { - return b.data.publishedAt.getTime() - a.data.publishedAt.getTime(); -}); - -const schema = { - "@context": "http://schema.org", - "@type": "WebSite", - id: "https://www.costas.dev/", - url: "https://www.costas.dev/", -}; +import HomePageLayout from "../layouts/HomePageLayout.astro"; --- -<Layout title="Inicio" description="Página de inicio de mi web"> - <script - is:inline - type="application/ld+json" - slot="head-jsonld" - set:html={JSON.stringify(schema)} - /> - - <h1>Inicio</h1> - <p> - Te doy la bienvenida a mi web. Me llamo Ariel, y aquí encontrarás - información sobre mí y mis proyectos. - </p> - - <h2>¿Quién soy?</h2> - <p> - Soy un desarrollador web que le gusta aprender cosas nuevas y compartir - su conocimiento. Me gusta la programación, el diseño web y la - creatividad. Me encanta crear cosas nuevas y aprender de los demás. - </p> - <a href="/trajectory">Más información sobre mí</a> - - <h2>¿Qué hago?</h2> - <p> - Actualmente trabajo como desarrollador de software y admistrador - Cloud en una empresa de tecnología. Me encargo de desarrollar - aplicaciones web en PHP y desplegarlas en la nube de forma segura y eficiente. - </p> - <a href="/portfolio">Mi portfolio</a> - - <h2>Últimas entradas del blog</h2> - <ul> - { - blogCollection.slice(0, 5).map((p) => { - const date = Intl.DateTimeFormat("es-ES", { - day: "2-digit", - month: "short", - year: "numeric", - }).format(p.data.publishedAt); - return ( - <li> - <time datetime={p.data.publishedAt.toISOString()}> - {date} - </time> - <a href={`/blog/${p.id}`}>{p.data.title}</a> - </li> - ); - }) - } - </ul> - <a href="/blog">Ver todas las entradas</a> - -</Layout> +<HomePageLayout />
\ No newline at end of file diff --git a/src/pages/portfolio/index.astro b/src/pages/portfolio/index.astro index 43f776b..63840f5 100644 --- a/src/pages/portfolio/index.astro +++ b/src/pages/portfolio/index.astro @@ -1,146 +1,5 @@ --- -import Layout from "../../layouts/Layout.astro"; -import TechnologyBadge from "../../partials/TechnologyBadge.astro"; - -const schema = { - "@context": "https://schema.org", - "@type": "WebPage", - url: "https://www.costas.dev/portfolio", - headline: "Mi portfolio de proyectos", -}; +import PortfolioPageLayout from "../../layouts/PortfolioPageLayout.astro"; --- -<Layout title="Portfolio" description="Un listado de los proyectos en los que he trabajado en los últimos años, con las tecnologías utilizadas."> - <script - is:inline - type="application/ld+json" - slot="head-jsonld" - set:html={JSON.stringify(schema)} - ></script> - - <h1>Mi portfolio</h1> - - <p> - En esta sección encontrarás una lista de los proyectos en los que he - trabajado, tanto para terceros como propios. Si quieres más información - sobre alguno de ellos, no dudes en - <a href="/contact">contactar conmigo</a>. - </p> - - <h2>Proyectos para terceros (freelance)</h2> - - <p> - He realizado desarrollos de proyectos para terceros por encargo, siendo los más destacados los siguientes: - </p> - - <section> - <article> - <h3>Extractor de pedidos compra online</h3> - - <p> - Aplicación de escritorio que extrae los datos sobre los pedidos - on-line de diversas plataformas (como WooCommerce, Amazon y - Ebay). <a href="/portfolio/order-extractor">Más información</a>. - </p> - - <TechnologyBadge code="java" /> - <TechnologyBadge code="windows" /> - </article> - - <article> - <h3>Punto de información turística en móviles</h3> - - <p> - Aplicación web de información turística, con QR, contenido en 360º e incrustado - de YouTube. <a href="/portfolio/dynamic-tourist-info">Más información</a>. - </p> - - <TechnologyBadge code="php" /> - <TechnologyBadge code="mysql" /> - </article> - - <article> - <h3>Consultoría WordPress</h3> - - <p> - Trabajos de mantenimiento, optimización y migración de sitios web WordPress y tiendas online WooCommerce. - <a href="/portfolio/wp-consulting">Más información</a>. - <a href="/contact">Contactar</a>. - </p> - - <TechnologyBadge code="php" /> - </article> - </section> - - <h2>Proyectos propios</h2> - - <p> - Además, tengo varios proyectos propios que he desarrollado en mi tiempo, estando algunos de ellos en activo, y como código abierto. - </p> - - <section> - <article> - <h3>Web personal</h3> - - <p> - Desarrollado con Astro, un generador de sitios web estáticos que - permite escribir contenido en Markdown y publicar en la web con un - rendimiento excelente. Desplegado sobre Azure Static Web Apps. - </p> - - <TechnologyBadge code="astro" /> - <TechnologyBadge code="azure" /> - </article> - - <article> - <h3>MiEntreno (proyecto fin de ciclo)</h3> - - <p> - Aplicación web para la gestión de entrenamientos deportivos, con - una interfaz sencilla y fácil de usar. Desarrollado con ASP.NET Core, - Razor Pages y SQL Server. <a href="/portfolio/mientreno">Más información</a>. - <a href="https://github.com/arielcostas/mientreno">Código fuente</a>. - </p> - - <TechnologyBadge code="dotnet" /> - <TechnologyBadge code="sqlserver" /> - <TechnologyBadge code="azure" /> - <TechnologyBadge code="rabbitmq" /> - </article> - - <article> - <h3>Vigo 360</h3> - - <p> - Blog sobre Vigo y su entorno, orientado principalmente a hablar de - movilidad y toponimia. Desarrollado en Go, con base de datos MySQL - y desplegado sobre VPS administrado por mí mismo. - <a href="/portfolio/vigo-360">Más información</a>. - <a href="https://github.com/arielcostas/vigo360">Código fuente</a>. - <a href="https://vigo360.es">Web</a>. - </p> - - <TechnologyBadge code="go" /> - <TechnologyBadge code="mysql" /> - <TechnologyBadge code="linux" /> - </article> - </section> -</Layout> - -<style> - section { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); - gap: 1rem; - } - - article { - padding: 1rem; - border: 1px solid var(--accent); - border-radius: 0.5rem; - } - - article h3 { - margin-top: 0; - } -</style>
\ No newline at end of file +<PortfolioPageLayout />
\ No newline at end of file diff --git a/src/pages/trajectory.astro b/src/pages/trajectory.astro index 87557de..b1366e6 100644 --- a/src/pages/trajectory.astro +++ b/src/pages/trajectory.astro @@ -1,111 +1,5 @@ --- -import Layout from "../layouts/Layout.astro"; - -const schema = { - "@context": "https://schema.org", - "@type": "WebPage", - "url": "https://www.costas.dev/trajectory", - "headline": "Mi trayectoria como desarrollador" -}; +import TrajectoryPageLayout from "../layouts/TrajectoryPageLayout.astro"; --- -<Layout title="Trayectoria" description="Mi trayectoria como desarrollador de software, con información sobre mi educación, experiencia laboral y proyectos en los que he trabajado."> - <script is:inline type="application/ld+json" slot="head-jsonld" set:html={JSON.stringify(schema)}></script> - - <h1>Mi trayectoria como desarrollador</h1> - - <p> - Soy un desarrollador de software que vive en Vigo, España. Me gusta - mucho la tecnología, y me gusta aprender cosas nuevas. Me dedico - profesionalmente al desarrollo de software en todos sus ámbitos: desde - el diseño de la arquitectura, la implementación y el despliegue en - producción, pasando por otros aspectos como la experiencia de usuario, - la accesibilidad y la seguridad. - </p> - - <h2>Tecnologías que domino</h2> - - <p> - Domino principalmente el ecosistema de Microsoft: .NET (C#), ASP.NET - Core, SQL Server, Azure y Azure DevOps. También tengo experiencia con - otros lenguajes y tecnologías, como PHP, Python y Java. Además, tengo - conocimientos de frontend con - <abbr title="Hypertext Markup Language">HTML5</abbr>, - <abbr title="Cascading Style Sheets">CSS3</abbr>, JavaScript y - TypeScript. - </p> - - <p> - También tengo experiencia con herramientas de DevOps como Docker, - Kubernetes, Terraform y GitHub Actions; así como el ecosistema Cloud de - Azure. - </p> - - <h2>Educación y credenciales</h2> - - <ul> - <li> - <strong>Certificado oficial EF SET C2 Proficient</strong>: - acredita mi nivel de inglés C2, el más alto según el Marco Común - Europeo de Referencia para las Lenguas. <a - href="https://cert.efset.org/es/Yxzc9L" - >Ver certificado</a> - </li> - - <li> - <strong>Microsoft Certified: Azure Developer Associate</strong>: - acredita mis conocimientos en el desarrollo de aplicaciones en - Azure. <a - href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/E15072607CCF2DA9?sharingId=149A1CD9C13790F4" - >Ver credencial</a - >. - </li> - - <li> - <strong>Microsoft Certified: Azure DevOps Engineer Expert</strong>: - acredita mis conocimientos en la implementación de metodologías de - DevOps en Azure con Azure DevOps y GitHub. <a - href="https://learn.microsoft.com/api/credentials/share/en-us/ariel-costas/5FB94876A1701595?sharingId=149A1CD9C13790F4" - >Ver credencial</a - > - </li> - - <li> - <strong - >Técnico Superior en Desarrollo de Aplicaciones Multiplataforma</strong - >: título de formación profesional de grado superior, obtenido en el - <a href="https://iesteis.es/">IES de Teis</a> en Vigo. - </li> - </ul> - - <h2>Experiencia laboral</h2> - - <h3>Estelaria Solutions (Q3 2023 - actualidad)</h3> - - <p> - Desarrollo de aplicaciones full-stack, principalmente en PHP con - Symfony, MongoDB y JavaScript Vanilla. Además, implementé una cantidad - considerable de mejoras en usabilidad, accesibilidad y rendimiento. - </p> - - <p> - También me encargo de la gestión de la infraestructura en AWS, y de la - implementación de herramientas de colaboración como Jira y GitHub. - </p> - - <h3>FCT en Polygon-E (Q2 2023)</h3> - - <p> - Realicé mis prácticas de formación profesional en la empresa Polygon-E, - donde desarrollé varias aplicaciones de gestión interna con ASP.NET Core - y Blazor, desplegando sobre entornos <i>on-premise</i> con Windows Server, - IIS y SQL Server. - </p> - - <h2>Proyectos</h2> - - <p> - Puedes encontrar los proyectos (públicos) en los que he trabajado en <a href="/portfolio">mi portfolio</a> - y en mi <a href="https://github.com/arielcostas">perfil de GitHub</a>. - </p> -</Layout> +<TrajectoryPageLayout /> diff --git a/src/partials/Footer.astro b/src/partials/Footer.astro index dae78b7..d5ca5cb 100644 --- a/src/partials/Footer.astro +++ b/src/partials/Footer.astro @@ -1,19 +1,23 @@ +--- +import { useTranslations } from "../i18n" + +const t = useTranslations(Astro.currentLocale); +--- + <footer> <p> - Copyright © 2023-{new Date().getFullYear()} Ariel Costas Guerrero. Todos - los derechos reservados. + Copyright © 2023-{new Date().getFullYear()} Ariel Costas Guerrero. {t.footer.copyright} </p> + <p> - Contenido cedido bajo licencia <a - href="https://creativecommons.org/licenses/by-sa/4.0/deed.es" - >CC BY-SA 4.0</a - > salvo que se indique lo contrario. El código fuente de este sitio está - disponible en <a href="https://github.com/arielcostas/costasdev" - >GitHub</a - >, bajo los términos de la <a + {t.footer.contentLicencedUnder} <a + href={`https://creativecommons.org/licenses/by-sa/4.0/deed.${Astro.currentLocale}`} + >CC BY-SA 4.0</a>. + + {t.footer.sourceCodeAvailableOn} <a href="https://github.com/arielcostas/costasdev">GitHub</a> + {t.footer.andIsLicencedUnder} <a href="https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12" - >Licencia Pública de la Unión Europea</a - >. + >{t.footer.eupl} 1.2</a </p> </footer> diff --git a/src/partials/Header.astro b/src/partials/Header.astro index 35a39ae..bd8c9d6 100644 --- a/src/partials/Header.astro +++ b/src/partials/Header.astro @@ -1,9 +1,16 @@ +--- +import { getRelativeLocaleUrl } from "astro:i18n"; +import { useTranslations } from "../i18n" + +const t = useTranslations(Astro.currentLocale); +--- + <header> - <a href="/">Inicio</a> - <a href="/trajectory">Trayectoria</a> - <a href="/portfolio">Portfolio</a> - <a href="/blog">Blog</a> - <a href="/contact">Contacto</a> + <a href={getRelativeLocaleUrl(Astro.currentLocale!, "")}>{t.header.home}</a> + <a href={getRelativeLocaleUrl(Astro.currentLocale!, "trajectory")}>{t.header.trajectory}</a> + <a href={getRelativeLocaleUrl(Astro.currentLocale!, "portfolio")}>{t.header.portfolio}</a> + <a href={getRelativeLocaleUrl("es", "blog")}>{t.header.blog}</a> + <a href={getRelativeLocaleUrl(Astro.currentLocale!, "contact")}>{t.header.contact}</a> </header> <style lang="scss"> diff --git a/styles/shared.scss b/styles/shared.scss index d36696f..202651c 100644 --- a/styles/shared.scss +++ b/styles/shared.scss @@ -15,6 +15,9 @@ $lightAlt: hsl(0, 0%, 100%); $noteBackground: hsl(210, 40%, 96%); $noteText: hsl(210, 40%, 40%); +$warningBackground: hsl(40, 100%, 90%); +$warningText: hsl(40, 100%, 30%); + $shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15); $floatingRadius: 0.5rem; |
