featmigrate from Angular to Astro static site
BREAKING CHANGE: Complete rewrite from Angular SPA to Astro - Replace Angular 18 with Astro 5.16.7 + Tailwind CSS - Convert all Angular components to Astro components - Add content collections for blog with markdown support - Setup S3 deployment with CloudFront invalidation - Add RSS feed and sitemap generation - Configure Prettier and Biome for code formatting - Switch from npm to pnpm - Remove Amplify backend (now fully static) - Improve SEO and performance with static generation
This commit is contained in:
parent
cda19e8624
commit
69d5850f5b
191 changed files with 7821 additions and 21755 deletions
154
src/pages/blog/[slug].astro
Normal file
154
src/pages/blog/[slug].astro
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection } from "astro:content";
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import Navbar from "../../components/Navbar.astro";
|
||||
import Footer from "../../components/Footer.astro";
|
||||
import "../../styles/prose.css";
|
||||
|
||||
type BlogPost = CollectionEntry<"blog">;
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const blogEntries: BlogPost[] = await getCollection("blog");
|
||||
return blogEntries.map((entry: BlogPost) => ({
|
||||
params: { slug: entry.slug },
|
||||
props: { entry },
|
||||
}));
|
||||
}
|
||||
|
||||
const { entry }: { entry: BlogPost } = Astro.props;
|
||||
const { Content } = await entry.render();
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${entry.data.title} | Lorenzo Iovino`}
|
||||
description={entry.data.description}
|
||||
canonicalUrl={`https://www.lorenzoiovino.com/blog/${entry.slug}`}
|
||||
image={entry.data.heroImage || "/photos/me.png"}
|
||||
type="article"
|
||||
publishedTime={entry.data.pubDate}
|
||||
modifiedTime={entry.data.updatedDate}
|
||||
tags={entry.data.tags}
|
||||
>
|
||||
<Navbar />
|
||||
<div class="min-h-screen pt-16 bg-gray-50">
|
||||
<article class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8 md:py-12">
|
||||
<header class="mb-8 md:mb-12">
|
||||
<time datetime={entry.data.pubDate.toISOString()} class="block mb-3 text-sm text-gray-600">
|
||||
{
|
||||
entry.data.pubDate.toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})
|
||||
}
|
||||
</time>
|
||||
{
|
||||
entry.data.tags.length > 0 && (
|
||||
<div class="flex gap-2 flex-wrap mb-4">
|
||||
{entry.data.tags.map((tag: string) => (
|
||||
<a
|
||||
href={`/blog/tag/${tag}`}
|
||||
class="px-3 py-1.5 bg-gray-100 text-gray-700 text-xs rounded-lg font-medium hover:bg-gray-900 hover:text-white transition-all duration-200"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<h1 class="text-gray-900 mb-4 text-3xl md:text-4xl lg:text-5xl font-bold leading-tight">
|
||||
{entry.data.title}
|
||||
</h1>
|
||||
<p class="text-lg md:text-xl text-gray-600 leading-relaxed mb-6">
|
||||
{entry.data.description}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{
|
||||
entry.data.heroImage && (
|
||||
<div class="mb-8 md:mb-12 -mx-4 sm:mx-0">
|
||||
<div class="relative h-64 sm:h-80 md:h-96 overflow-hidden sm:rounded-2xl shadow-xl">
|
||||
<img
|
||||
src={entry.data.heroImage}
|
||||
alt={entry.data.title}
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div class="bg-white rounded-xl md:rounded-2xl shadow-xl p-6 sm:p-8 md:p-12 lg:p-16">
|
||||
<div class="prose prose-xl max-w-none">
|
||||
<Content />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 md:mt-12 bg-white rounded-xl md:rounded-2xl shadow-lg p-6 sm:p-8">
|
||||
<div class="flex items-start gap-6">
|
||||
<img
|
||||
src="/photos/me.png"
|
||||
alt="Lorenzo Iovino"
|
||||
class="w-20 h-20 rounded-full object-cover"
|
||||
/>
|
||||
<div>
|
||||
<h3 class="text-lg md:text-xl font-bold text-gray-900 mb-2">Lorenzo Iovino</h3>
|
||||
<p class="text-sm md:text-base text-gray-700 mb-4">
|
||||
Software Engineer based in Sicily, passionate about technology, remote work, and life
|
||||
balance. When not coding, you'll find me working on my vineyard or exploring the
|
||||
beautiful Sicilian countryside.
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
<a
|
||||
href="https://www.linkedin.com/in/lorenzoiovino/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-gray-900 transition-colors"
|
||||
>
|
||||
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/thisloke"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-gray-600 hover:text-gray-900 transition-colors"
|
||||
>
|
||||
<svg class="w-5 h-5 md:w-6 md:h-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 md:mt-12 text-center">
|
||||
<a
|
||||
href="/blog"
|
||||
class="inline-flex items-center px-5 py-2.5 md:px-6 md:py-3 bg-white hover:bg-gray-50 text-gray-900 font-medium rounded-lg md:rounded-xl transition-all duration-200 shadow-md hover:shadow-lg border border-gray-200"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5 mr-2"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M9.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L7.414 9H15a1 1 0 110 2H7.414l2.293 2.293a1 1 0 010 1.414z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
Back to Blog
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<Footer />
|
||||
</BaseLayout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue