chore: setup astro

This commit is contained in:
Alejandro Laguna
2025-08-02 14:40:33 +02:00
parent 3b0278b7fc
commit 8bb138dbe5
33 changed files with 5206 additions and 3491 deletions

View File

@@ -1,48 +0,0 @@
import { useEffect, useState } from 'react';
import image from '../assets/sketch.png';
const taglines = [
"Amateur Writer",
"Bookworm",
"Star Gazer",
"Physics Enthusiast",
"Lifelong Learner",
"Tea Enthusiast",
"Cosmic Explorer",
"Knowledge Seeker",
];
export default function About({ theme }) {
const [tagline, setTagline] = useState('');
useEffect(() => {
const randomTagline = taglines[Math.floor(Math.random() * taglines.length)];
setTagline(randomTagline);
}, []);
return (
<section id="about" class="pt-8">
<div class="flex flex-col md:flex-row gap-8 items-center">
<div class="flex-1">
<h1 class={`text-4xl md:text-5xl mb-4 ${theme.accent} font-serif font-semibold`}>Alejandro Laguna</h1>
<h2 class="text-xl md:text-2xl mb-6 text-[#b8c4b5]/80 font-medium font-serif">Software Engineer & {tagline}</h2>
<p class="text-lg mb-6 text-[#b8c4b5]/90">
Crafting digital projects that inspire me, while exploring everything from books and tea to space and science. First-year computer science student.
</p>
<div class="flex gap-4">
<a href="#projects" class={`px-6 py-2 rounded-full border ${theme.border} ${theme.hover} transition-all hover:-translate-y-0.5`}>
View Work
</a>
<a href="mailto:alejandro.laguna@epitech.eu" class={`px-6 py-2 rounded-full ${theme.button} transition-all hover:-translate-y-0.5`}>
Contact
</a>
</div>
</div>
<div class="flex-1 flex justify-center">
<img src={image} alt="Alex Clark's Sketch" class="w-64 h-64 rounded-full object-cover" />
</div>
</div>
</section>
);
}

View File

@@ -1,37 +0,0 @@
import EducationCard from './EducationCard';
const education = [
{
institution: "European Institute of Technology (EPITECH)",
degree: "Degree + Master in Computer Science",
duration: "2024 - 2029",
highlights: [
"ONGOING",
"Multiple courses passed with Honors",
"Completed over 30 projects from different fields"
]
},
{
institution: "INS Cendrassos",
degree: "Microcomputer systems & networks",
duration: "2022 - 2024",
highlights: [
"First of the class",
"ERASMUS+ Scholarship",
"Student of the year"
]
}
];
export default function Education({ theme }) {
return (
<section id="education">
<h2 class={`text-3xl mb-8 font-serif font-semibold ${theme.accent}`}>Education</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
{education.map((edu, i) => (
<EducationCard key={i} education={edu} theme={theme} />
))}
</div>
</section>
);
}

View File

@@ -1,18 +0,0 @@
export default function EducationCard({ education, theme }) {
return (
<div class={`p-4 rounded-xl border ${theme.border} ${theme.card} transition-all hover:-translate-y-1 group`}>
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-lg">{education.degree}</h3>
<p class="text-[#b8c4b5]/80">{education.institution}</p>
</div>
<span class="text-sm text-[#b8c4b5]/50">{education.duration}</span>
</div>
<ul class="list-disc pl-6 space-y-2 mb-4">
{education.highlights.map((highlight, j) => (
<li key={j} class="text-[#b8c4b5]/90">{highlight}</li>
))}
</ul>
</div>
);
}

View File

@@ -1,39 +0,0 @@
import ExperienceCard from './ExperienceCard';
const experience = [
{
company: "Avantiam Inc - Figueres, Spain",
role: "Full-Stack Developer",
duration: "Sep 2023 - Sep 2024",
technologies: ["Laravel", "Livewire", "AlpineJS", "TailwindCSS", "MariaDB/MySQL"],
highlights: [
"Developed and maintained a comprehensive business management service used by over 100 companies",
"Managed all aspects of the project lifecycle, including server administration, performance tuning, and user experience improvements.",
"Recommendation letter available upon request."
]
},
{
company: "Niblu Group - Maribor, Slovenia",
role: "Backend Developer Intern",
duration: "Summer 2023",
technologies: ["NextJS", "TailwindCSS", "TypeScript", "FastAPI", "AWS S3 Bucket"],
highlights: [
"Developed a secure authentication system and features for managing courses across different user roles.",
"Integrated AWS S3 for seamless storage and retrieval of course materials.",
"Gained valuable personal and professional growth through the ERASMUS experience, adapting to new challenges abroad alone."
]
}
];
export default function Experience({ theme }) {
return (
<section id="experience">
<h2 class={`text-3xl mb-8 ${theme.accent} font-semibold font-serif`}>Work Experience</h2>
<div class="space-y-8">
{experience.map((exp, i) => (
<ExperienceCard key={i} experience={exp} theme={theme} />
))}
</div>
</section>
);
}

View File

@@ -1,36 +0,0 @@
export default function ExperienceCard({ experience, theme }) {
return (
<div class={`p-6 rounded-xl border ${theme.border} ${theme.card} transition-all hover:-translate-y-1 group`}>
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-xl">{experience.company}</h3>
<p class="text-[#b8c4b5]/80">{experience.role}</p>
</div>
<span class="text-sm text-[#b8c4b5]/50">{experience.duration}</span>
</div>
<ul class="list-disc pl-6 space-y-2 mb-4">
{experience.highlights.map((highlight, j) => (
<li key={j} class="text-[#b8c4b5]/90">{highlight}</li>
))}
</ul>
{experience.technologies && (
<div class="flex flex-wrap gap-2 mb-4">
<h4 class="text-lg font-semibold text-[#b8c4b5]/90">Technologies Used:</h4>
{experience.technologies.map((tech, i) => (
<span key={i} class={`px-3 rounded-full ${theme.bg} text-[#b8c4b5]/80`}>{tech}</span>
))}
</div>
)}
{experience.link && (
<a
href={experience.link}
class={`inline-flex items-center text-sm ${theme.accent} ${theme.hover}`}
>
View More
<span class="ml-2 transition-transform group-hover:translate-x-1"></span>
</a>
)}
</div>
);
}

View File

@@ -1,15 +0,0 @@
export default function Footer({ theme }) {
return (
<footer class={`pt-8 border-t border-opacity-20 ${theme.border}`}>
<div class="flex flex-col md:flex-row justify-between items-center">
<p class="text-sm text-[#b8c4b5]/50 mb-4 md:mb-0">© 2025 Alejandro Laguna</p>
<div class="flex gap-6">
<a href="https://github.com/alejandrolaguna20" class={`text-sm ${theme.text} ${theme.hover}`}>GitHub</a>
<a href="https://www.linkedin.com/in/alejandro-laguna-939687278/" class={`text-sm ${theme.text} ${theme.hover}`}>LinkedIn</a>
<a href="/resume_eng.pdf" download="cv_english_alejandro_laguna.pdf" target="_blank" rel="noopener" class={`text-sm ${theme.text} ${theme.hover}`}>CV</a>
</div>
</div>
</footer>
);
}

View File

@@ -1,22 +0,0 @@
export function Header({ theme }) {
return (
<header class="fixed w-full top-0 z-50 backdrop-blur-sm">
<div class="max-w-5xl mx-auto px-4 py-3 flex justify-between items-center">
<h1 class={`text-xl font-bold opacity-50 ${theme.accent} tracking-wider font-serif`}>alejandrolaguna.dev</h1>
<nav class="hidden md:flex gap-6">
{['About', 'Projects', 'Experience'].map((item) => (
<a
href={`#${item.toLowerCase()}`}
class={`text-sm ${theme.text} ${theme.hover} transition-colors`}
>
{item}
</a>
))}
</nav>
</div>
</header>
);
}

View File

@@ -1,10 +0,0 @@
export default function Layout({ children, theme }) {
return (
<div class={`min-h-screen transition-colors duration-300 ${theme.bg} ${theme.text}`}>
<main class="max-w-5xl mx-auto px-4 pt-24 pb-16 space-y-16">
{children}
</main>
</div>
);
}

View File

@@ -1,26 +0,0 @@
export default function ProjectCard({ project, theme }) {
return (
<div class={`p-6 rounded-xl border ${theme.border} ${theme.card} transition-all hover:-translate-y-1 group`}>
<div class="flex justify-between items-start mb-4">
<h3 class="text-xl">{project.title}</h3>
<span class="text-sm text-[#b8c4b5]/50">{project.year}</span>
</div>
<p class="mb-4 text-[#b8c4b5]/80">{project.description}</p>
<div class="flex flex-wrap gap-2 mb-4">
{project.tech.map((tech, j) => (
<span key={j} class={`px-3 py-1 rounded-full ${theme.bg} text-[#b8c4b5]/80`}>{tech}</span>
))}
</div>
{project.link && (
<a
href={project.link}
class={`inline-flex items-center text-sm ${theme.accent} ${theme.hover}`}
>
View Details
<span class="ml-2 transition-transform group-hover:translate-x-1"></span>
</a>
)}
</div>
);
}

View File

@@ -1,53 +0,0 @@
import ProjectCard from './ProjectCard';
const projects = [
{
title: "Morph",
description: "Lightweight URL shortening API built in Go with minimal dependencies. First ever project with this language, and I tried to focus on the stdlib and build any needed tools",
tech: ["Go"],
year: "2025",
link: "https://github.com/alejandrolaguna20/morph"
},
{
title: "Runes",
description: "A small, simple, smooth and beautiful flashcard TUI program featuring keyboard navigation and custom study sessions. Built with Go and the Bubbletea framework.",
tech: ["Go", "Bubbletea"],
year: "2025",
link: "https://github.com/alejandrolaguna20/nook.nvim"
},
{
title: "Nook.nvim",
description: "A tiny Neovim plugin created to manage tasks in a way that perfectly fits my personal workflow ",
tech: ["Lua"],
year: "2025",
link: "https://github.com/alejandrolaguna20/nook.nvim"
},
{
title: "Portfolio",
description: "The website you are currently browsing, my little corner on the web.",
tech: ["Typescript", "PreactJS", "TailwindCSS", "Vite"],
year: "2025",
link: "https://github.com/alejandrolaguna20/portfolio"
},
{
title: "Epitech Projects",
description: "A variety of projects I am building in my first year @ Epitech that range from algorithm implementation, graphical and mathematical simulations, and developing from scratch different Linux commands and programs, including a shell.",
tech: ["C", "Bash", "Python"],
year: "2025",
link: "https://www.epitech.eu/programme-grande-ecole-informatique/"
}
];
export default function Projects({ theme }) {
return (
<section id="projects">
<h2 class={`text-3xl font-semibold font-serif mb-8 ${theme.accent}`}>Projects</h2>
<div class="grid gap-6">
{projects.map((project, i) => (
<ProjectCard key={i} project={project} theme={theme} />
))}
</div>
</section>
);
}

View File

@@ -0,0 +1,210 @@
---
import astroLogo from '../assets/astro.svg';
import background from '../assets/background.svg';
---
<div id="container">
<img id="background" src={background.src} alt="" fetchpriority="high" />
<main>
<section id="hero">
<a href="https://astro.build"
><img src={astroLogo.src} width="115" height="48" alt="Astro Homepage" /></a
>
<h1>
To get started, open the <code><pre>src/pages</pre></code> directory in your project.
</h1>
<section id="links">
<a class="button" href="https://docs.astro.build">Read our docs</a>
<a href="https://astro.build/chat"
>Join our Discord <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"
><path
fill="currentColor"
d="M107.7 8.07A105.15 105.15 0 0 0 81.47 0a72.06 72.06 0 0 0-3.36 6.83 97.68 97.68 0 0 0-29.11 0A72.37 72.37 0 0 0 45.64 0a105.89 105.89 0 0 0-26.25 8.09C2.79 32.65-1.71 56.6.54 80.21a105.73 105.73 0 0 0 32.17 16.15 77.7 77.7 0 0 0 6.89-11.11 68.42 68.42 0 0 1-10.85-5.18c.91-.66 1.8-1.34 2.66-2a75.57 75.57 0 0 0 64.32 0c.87.71 1.76 1.39 2.66 2a68.68 68.68 0 0 1-10.87 5.19 77 77 0 0 0 6.89 11.1 105.25 105.25 0 0 0 32.19-16.14c2.64-27.38-4.51-51.11-18.9-72.15ZM42.45 65.69C36.18 65.69 31 60 31 53s5-12.74 11.43-12.74S54 46 53.89 53s-5.05 12.69-11.44 12.69Zm42.24 0C78.41 65.69 73.25 60 73.25 53s5-12.74 11.44-12.74S96.23 46 96.12 53s-5.04 12.69-11.43 12.69Z"
></path></svg
>
</a>
</section>
</section>
</main>
<a href="https://astro.build/blog/astro-5/" id="news" class="box">
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"
><path
d="M24.667 12c1.333 1.414 2 3.192 2 5.334 0 4.62-4.934 5.7-7.334 12C18.444 28.567 18 27.456 18 26c0-4.642 6.667-7.053 6.667-14Zm-5.334-5.333c1.6 1.65 2.4 3.43 2.4 5.333 0 6.602-8.06 7.59-6.4 17.334C13.111 27.787 12 25.564 12 22.666c0-4.434 7.333-8 7.333-16Zm-6-5.333C15.111 3.555 16 5.556 16 7.333c0 8.333-11.333 10.962-5.333 22-3.488-.774-6-4-6-8 0-8.667 8.666-10 8.666-20Z"
fill="#111827"></path></svg
>
<h2>What's New in Astro 5.0?</h2>
<p>
From content layers to server islands, click to learn more about the new features and
improvements in Astro 5.0
</p>
</a>
</div>
<style>
#background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
filter: blur(100px);
}
#container {
font-family: Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif;
height: 100%;
}
main {
height: 100%;
display: flex;
justify-content: center;
}
#hero {
display: flex;
align-items: start;
flex-direction: column;
justify-content: center;
padding: 16px;
}
h1 {
font-size: 22px;
margin-top: 0.25em;
}
#links {
display: flex;
gap: 16px;
}
#links a {
display: flex;
align-items: center;
padding: 10px 12px;
color: #111827;
text-decoration: none;
transition: color 0.2s;
}
#links a:hover {
color: rgb(78, 80, 86);
}
#links a svg {
height: 1em;
margin-left: 8px;
}
#links a.button {
color: white;
background: linear-gradient(83.21deg, #3245ff 0%, #bc52ee 100%);
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.12),
inset 0 -2px 0 rgba(0, 0, 0, 0.24);
border-radius: 10px;
}
#links a.button:hover {
color: rgb(230, 230, 230);
box-shadow: none;
}
pre {
font-family:
ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono',
monospace;
font-weight: normal;
background: linear-gradient(14deg, #d83333 0%, #f041ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: 0;
}
h2 {
margin: 0 0 1em;
font-weight: normal;
color: #111827;
font-size: 20px;
}
p {
color: #4b5563;
font-size: 16px;
line-height: 24px;
letter-spacing: -0.006em;
margin: 0;
}
code {
display: inline-block;
background:
linear-gradient(66.77deg, #f3cddd 0%, #f5cee7 100%) padding-box,
linear-gradient(155deg, #d83333 0%, #f041ff 18%, #f5cee7 45%) border-box;
border-radius: 8px;
border: 1px solid transparent;
padding: 6px 8px;
}
.box {
padding: 16px;
background: rgba(255, 255, 255, 1);
border-radius: 16px;
border: 1px solid white;
}
#news {
position: absolute;
bottom: 16px;
right: 16px;
max-width: 300px;
text-decoration: none;
transition: background 0.2s;
backdrop-filter: blur(50px);
}
#news:hover {
background: rgba(255, 255, 255, 0.55);
}
@media screen and (max-height: 368px) {
#news {
display: none;
}
}
@media screen and (max-width: 768px) {
#container {
display: flex;
flex-direction: column;
}
#hero {
display: block;
padding-top: 10%;
}
#links {
flex-wrap: wrap;
}
#links a.button {
padding: 14px 18px;
}
#news {
right: 16px;
left: 16px;
bottom: 2.5rem;
max-width: 100%;
}
h1 {
line-height: 1.5;
}
}
</style>