Compare commits
No commits in common. "1d8b7d58a40a53b49d7b8472b574b50011715f89" and "31b2346c626acee795a0f2e86c06beeb4c5d4c1f" have entirely different histories.
1d8b7d58a4
...
31b2346c62
14 changed files with 158 additions and 155 deletions
|
|
@ -1,2 +0,0 @@
|
|||
[tools]
|
||||
claude = "latest"
|
||||
|
|
@ -10,7 +10,7 @@ const t = useTranslations(lang);
|
|||
const year = new Date().getFullYear();
|
||||
---
|
||||
|
||||
<footer class="border-t border-border/80 font-mono">
|
||||
<footer class="border-t border-border/80">
|
||||
<div class="mx-auto flex max-w-3xl flex-col gap-2 px-4 py-8 text-sm text-text-muted sm:flex-row sm:items-center sm:justify-between sm:px-6">
|
||||
<p>
|
||||
© {year} <span class="font-mono text-text">gabeefranco</span> · {t('footer.rights')}
|
||||
|
|
|
|||
|
|
@ -28,71 +28,24 @@ function isActive(href: string): boolean {
|
|||
}
|
||||
---
|
||||
|
||||
|
||||
<header class="sticky top-0 z-40 border-b border-border/80 bg-bg/85 backdrop-blur">
|
||||
<div class="flex flex-col justify-center gap-4 px-4 py-3 sm:px-6">
|
||||
<div class="flex flex-row justify-between items-end">
|
||||
<a href={homeHref} class="flex hover:underline shrink-0 items-center gap-2.5" aria-label={t('site.name')}>
|
||||
<img src="/logo.png" class="h-4"/>
|
||||
<span class="font-mono text-[15px] font-semibold tracking-tight text-text">{t('site.name')}</span>
|
||||
<div class="mx-auto flex max-w-3xl items-center justify-between gap-4 px-4 py-3 sm:px-6">
|
||||
<a href={homeHref} class="flex shrink-0 items-center gap-2.5" aria-label={t('site.name')}>
|
||||
<img src="/favicon.svg" alt="" width="32" height="32" class="size-8" />
|
||||
<span class="font-mono text-[15px] font-semibold tracking-tight text-text">{t('site.name')}</span>
|
||||
</a>
|
||||
|
||||
</a>
|
||||
<div class="ml-10 flex sm:hidden justify-end gap-3">
|
||||
<a
|
||||
href={langSwitchHref}
|
||||
hreflang={otherLang}
|
||||
title={t('lang.switch')}
|
||||
aria-label={`${t('lang.switch')}: ${LANG_LABELS[otherLang]}`}
|
||||
class="text-accent max-w-fit font-mono text-xs sm:text-sm underline hover:cursor-pointer hover:text-accent-deep"
|
||||
>
|
||||
{`${t('lang.switch')}: ${LANG_LABELS[otherLang]}`}
|
||||
</a>
|
||||
|
||||
<ThemeToggle lang={lang} />
|
||||
</div>
|
||||
<div class="hidden sm:flex items-center gap-2">
|
||||
|
||||
<nav class="flex items-center gap-1 justify-right" aria-label={t('nav.menu')}>
|
||||
<div class="flex items-center gap-2">
|
||||
<nav class="hidden items-center gap-1 sm:flex" aria-label={t('nav.menu')}>
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
href={link.href}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
class:list={[
|
||||
'px-2 py-1 text-sm font-medium font-mono underline',
|
||||
'rounded-full px-3 py-1.5 text-sm font-medium transition-colors',
|
||||
isActive(link.href)
|
||||
? 'text-primary hover:text-primary-hover'
|
||||
: 'text-text-muted hover:text-text',
|
||||
]}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
<a
|
||||
href={langSwitchHref}
|
||||
hreflang={otherLang}
|
||||
title={t('lang.switch')}
|
||||
aria-label={`${t('lang.switch')}: ${LANG_LABELS[otherLang]}`}
|
||||
class="text-accent max-w-fit py-1 font-mono text-xs sm:text-sm underline hover:cursor-pointer hover:text-accent-deep "
|
||||
>
|
||||
{`${t('lang.switch')}: ${LANG_LABELS[otherLang]}`}
|
||||
</a>
|
||||
|
||||
<ThemeToggle lang={lang} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end sm:hidden items-center gap-2">
|
||||
<nav class="flex items-center gap-1 justify-right" aria-label={t('nav.menu')}>
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
href={link.href}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
class:list={[
|
||||
'px-2 py-1 text-sm font-medium font-mono underline',
|
||||
isActive(link.href)
|
||||
? 'text-primary hover:text-primary-hover'
|
||||
: 'text-text-muted hover:text-text',
|
||||
? 'bg-primary/10 text-primary'
|
||||
: 'text-text-muted hover:bg-surface-alt hover:text-text',
|
||||
]}
|
||||
>
|
||||
{link.label}
|
||||
|
|
@ -100,7 +53,47 @@ function isActive(href: string): boolean {
|
|||
))}
|
||||
</nav>
|
||||
|
||||
<a
|
||||
href={langSwitchHref}
|
||||
hreflang={otherLang}
|
||||
title={t('lang.switch')}
|
||||
aria-label={`${t('lang.switch')}: ${LANG_LABELS[otherLang]}`}
|
||||
class="grid size-9 shrink-0 place-items-center rounded-full border border-border text-xs font-bold uppercase text-text-muted transition-colors hover:border-primary hover:text-primary"
|
||||
>
|
||||
{otherLang}
|
||||
</a>
|
||||
|
||||
<ThemeToggle lang={lang} />
|
||||
|
||||
<details class="relative sm:hidden">
|
||||
<summary
|
||||
class="grid size-9 cursor-pointer list-none place-items-center rounded-full border border-border text-text-muted transition-colors hover:border-primary hover:text-primary"
|
||||
aria-label={t('nav.menu')}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" class="size-[18px]">
|
||||
<path d="M4 6h16M4 12h16M4 18h16"></path>
|
||||
</svg>
|
||||
</summary>
|
||||
<nav
|
||||
class="absolute right-0 top-11 flex w-40 flex-col gap-1 rounded-xl border border-border bg-surface p-2 shadow-lg"
|
||||
aria-label={t('nav.menu')}
|
||||
>
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
href={link.href}
|
||||
aria-current={isActive(link.href) ? 'page' : undefined}
|
||||
class:list={[
|
||||
'rounded-lg px-3 py-2 text-sm font-medium transition-colors',
|
||||
isActive(link.href)
|
||||
? 'bg-primary/10 text-primary'
|
||||
: 'text-text-muted hover:bg-surface-alt hover:text-text',
|
||||
]}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -15,53 +15,46 @@ const postsHref = getLocalizedPath('/posts', lang);
|
|||
const aboutHref = getLocalizedPath('/about', lang);
|
||||
---
|
||||
|
||||
<section class="mx-10 my-10 flex flex-col gap-5 font-mono">
|
||||
<div class="flex flex-col gap-2">
|
||||
<h1 class="text-text text-2xl">{t('hero.title')}</h1>
|
||||
<h2 class="text-text text-lg">{t('hero.subtitle')}</h2>
|
||||
<section class="mx-auto max-w-3xl px-4 pb-4 pt-14 sm:px-6 sm:pt-20">
|
||||
<div class="flex flex-col items-start gap-8 sm:flex-row sm:items-center">
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt=""
|
||||
width="867"
|
||||
height="458"
|
||||
class="w-40 shrink-0 drop-shadow-sm sm:w-52"
|
||||
/>
|
||||
<div>
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-primary">{t('hero.kicker')}</p>
|
||||
<h1 class="mt-2 text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('hero.title')}</h1>
|
||||
<p class="mt-4 max-w-xl text-lg leading-relaxed text-text-muted">{t('hero.subtitle')}</p>
|
||||
<div class="mt-6 flex flex-wrap gap-3">
|
||||
<a
|
||||
href={postsHref}
|
||||
class="rounded-full bg-primary px-5 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-primary-hover"
|
||||
>
|
||||
{t('hero.cta.posts')}
|
||||
</a>
|
||||
<a
|
||||
href={aboutHref}
|
||||
class="rounded-full border border-border px-5 py-2.5 text-sm font-semibold text-text transition-colors hover:border-primary hover:text-primary"
|
||||
>
|
||||
{t('hero.cta.about')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- <section class="mx-auto max-w-3xl px-4 pb-4 pt-14 sm:px-6 sm:pt-20 font-mono"> -->
|
||||
<!-- <div class="flex flex-col items-start gap-8 sm:flex-row sm:items-center"> -->
|
||||
<!-- <img -->
|
||||
<!-- src="/logo.png" -->
|
||||
<!-- alt="" -->
|
||||
<!-- width="867" -->
|
||||
<!-- height="458" -->
|
||||
<!-- class="w-40 shrink-0 drop-shadow-sm sm:w-52" -->
|
||||
<!-- /> -->
|
||||
<!-- <div> -->
|
||||
<!-- <p class="text-sm font-semibold uppercase tracking-wide text-primary">{t('hero.kicker')}</p> -->
|
||||
<!-- <h1 class="mt-2 text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('hero.title')}</h1> -->
|
||||
<!-- <p class="mt-4 max-w-xl text-lg leading-relaxed text-text-muted">{t('hero.subtitle')}</p> -->
|
||||
<!-- <div class="mt-6 flex flex-wrap gap-5"> -->
|
||||
<!-- <a -->
|
||||
<!-- href={postsHref} -->
|
||||
<!-- class="text-primary hover:underline font-bold px-2 py-1 bg-primary/10" -->
|
||||
<!-- > -->
|
||||
<!-- {t('hero.cta.posts')} -->
|
||||
<!-- </a> -->
|
||||
<!-- <a -->
|
||||
<!-- href={aboutHref} -->
|
||||
<!-- class="text-text hover:underline font-bold px-2 py-1 bg-text/5" -->
|
||||
<!-- > -->
|
||||
<!-- {t('hero.cta.about')} -->
|
||||
<!-- </a> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </section> -->
|
||||
|
||||
<section class="mx-10 font-mono">
|
||||
<section class="mx-auto max-w-3xl px-4 py-12 sm:px-6">
|
||||
<div class="flex items-baseline justify-between gap-4">
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-text">{t('home.recent')}</h2>
|
||||
<p class="mt-1 text-sm text-text-muted mb-2">{t('home.recent.subtitle')}</p>
|
||||
<a href={postsHref} class="shrink-0 text-sm font-medium text-primary hover:underline">
|
||||
{t('home.viewAll')} →
|
||||
</a>
|
||||
<p class="mt-1 text-sm text-text-muted">{t('home.recent.subtitle')}</p>
|
||||
</div>
|
||||
<a href={postsHref} class="shrink-0 text-sm font-medium text-primary hover:underline">
|
||||
{t('home.viewAll')} →
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{recentPosts.length > 0 ? (
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ const href = getLocalizedPath(`/posts/${slugOf(post)}`, lang);
|
|||
const tagsHref = (tag: string) => getLocalizedPath(`/tags/${tag}`, lang);
|
||||
---
|
||||
|
||||
<article class="group border-b border-border py-6 first:pt-0 last:border-b-0 font-mono">
|
||||
<article class="group border-b border-border py-6 first:pt-0 last:border-b-0">
|
||||
<a href={href} class="block">
|
||||
<time datetime={post.data.pubDate.toISOString()} class="text-xs font-medium uppercase tracking-wide text-text-muted">
|
||||
{formatDate(post.data.pubDate, lang)}
|
||||
</time>
|
||||
<h3 class="mt-1.5 text-xl font-semibold text-text group-hover:text-primary group-hover:underline">
|
||||
<h3 class="mt-1.5 text-xl font-semibold text-text transition-colors group-hover:text-primary">
|
||||
{post.data.title}
|
||||
</h3>
|
||||
<p class="mt-1.5 text-[15px] leading-relaxed text-text-muted">{post.data.description}</p>
|
||||
|
|
@ -28,7 +28,7 @@ const tagsHref = (tag: string) => getLocalizedPath(`/tags/${tag}`, lang);
|
|||
{post.data.tags.map((tag) => (
|
||||
<a
|
||||
href={tagsHref(tag)}
|
||||
class="text-text-muted px-1 py-0.5 text-sm hover:text-accent underline"
|
||||
class="rounded-full bg-surface-alt px-2.5 py-1 text-xs font-medium text-text-muted transition-colors hover:bg-accent/15 hover:text-accent"
|
||||
>
|
||||
#{tag}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ const posts = tag ? allPosts.filter((p) => p.data.tags.includes(tag)) : allPosts
|
|||
const postsHref = getLocalizedPath('/posts', lang);
|
||||
---
|
||||
|
||||
<section class="mx-10 mt-10">
|
||||
<section class="mx-auto max-w-3xl px-4 py-12 sm:px-6">
|
||||
{tag ? (
|
||||
<>
|
||||
<p class="text-sm font-mono font-medium text-text-muted">{t('posts.filteredBy')}</p>
|
||||
<h1 class="mt-1 font-mono text-3xl font-bold tracking-tight text-text">#{tag}</h1>
|
||||
<a href={postsHref} class="font-mono mt-2 inline-block text-sm font-medium text-primary hover:underline">
|
||||
<p class="text-sm font-medium text-text-muted">{t('posts.filteredBy')}</p>
|
||||
<h1 class="mt-1 text-3xl font-bold tracking-tight text-text">#{tag}</h1>
|
||||
<a href={postsHref} class="mt-2 inline-block text-sm font-medium text-primary hover:underline">
|
||||
{t('posts.clearFilter')}
|
||||
</a>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h1 class="font-mono text-3xl font-bold tracking-tight text-text">{t('posts.title')}</h1>
|
||||
<p class="font-mono mt-2 text-text-muted">{t('posts.subtitle')}</p>
|
||||
<h1 class="text-3xl font-bold tracking-tight text-text">{t('posts.title')}</h1>
|
||||
<p class="mt-2 text-text-muted">{t('posts.subtitle')}</p>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,26 +11,61 @@ const t = useTranslations(lang);
|
|||
---
|
||||
|
||||
<button
|
||||
id="theme-toggle"
|
||||
type="button"
|
||||
class="theme-toggle text-accent sm:ml-2 font-mono text-xs sm:text-sm underline hover:cursor-pointer hover:text-accent-deep"
|
||||
aria-label={t('theme.switch')}
|
||||
title={t('theme.switch')}
|
||||
class="grid size-9 shrink-0 place-items-center rounded-full border border-border text-text-muted transition-colors hover:border-primary hover:text-primary"
|
||||
>
|
||||
{t('theme.switch')}
|
||||
<svg
|
||||
id="theme-toggle-sun"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="hidden size-[18px]"
|
||||
>
|
||||
<circle cx="12" cy="12" r="4"></circle>
|
||||
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"
|
||||
></path>
|
||||
</svg>
|
||||
<svg
|
||||
id="theme-toggle-moon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="hidden size-[18px]"
|
||||
>
|
||||
<path d="M20 14.5A8.5 8.5 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<script>
|
||||
function init() {
|
||||
const buttons = document.querySelectorAll('.theme-toggle');
|
||||
buttons.forEach((btn) => {
|
||||
btn.addEventListener('click', function () {
|
||||
const isDark = document.documentElement.classList.toggle('dark');
|
||||
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
||||
});
|
||||
});
|
||||
<script is:inline>
|
||||
(function () {
|
||||
const btn = document.getElementById('theme-toggle');
|
||||
const sun = document.getElementById('theme-toggle-sun');
|
||||
const moon = document.getElementById('theme-toggle-moon');
|
||||
if (!btn || !sun || !moon) return;
|
||||
|
||||
function sync() {
|
||||
const isDark = document.documentElement.classList.contains('dark');
|
||||
sun.classList.toggle('hidden', !isDark);
|
||||
moon.classList.toggle('hidden', isDark);
|
||||
}
|
||||
|
||||
init();
|
||||
btn.addEventListener('click', function () {
|
||||
const isDark = document.documentElement.classList.toggle('dark');
|
||||
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
||||
sync();
|
||||
});
|
||||
|
||||
document.addEventListener('astro:after-swap', init);
|
||||
sync();
|
||||
})();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,8 @@
|
|||
---
|
||||
title: "This blog's Hello World (or whatever you want to call this site)"
|
||||
description: "A short note on why this exists and what I plan to write about here."
|
||||
pubDate: 2026-09-22
|
||||
title: "Hello, world"
|
||||
description: "A short note on why this blog exists and what I plan to write about here."
|
||||
pubDate: 2026-01-12
|
||||
tags: ["meta", "blogging"]
|
||||
---
|
||||
|
||||
I've always had a creative side, as anyone who knows me can tell you. Sometimes it gets tucked away somewhere obscure, in the back of a drawer, waiting years to be used. And sometimes I make really good use of it.
|
||||
I've always loved writing, and I've wanted a place of my own to publish my thoughts for a long time. Only the ones I'd want to be public, of course. Nobody wants to hand over the entire inner workings of their brain just like that, for free. Still, I think some of my intellectual adventures deserve a bit of exposure, especially since, without someone to judge them, I'll never know if they were worth it.
|
||||
|
||||
One of my inspirations for creating a site/blog was [Fábio Akita](https://instagram.com/akitaonrails). I've been following him for a long time, and it was through the videos on [his YouTube channel](https://youtube.com/akitaonrails) that I started studying computer science, before I even got into college. Even though the videos are genuinely great, teaching things that are hard to learn any other way, after a while of binge-watching them I found his blog, [akitaonrails.com](https://akitaonrails.com). I thought it was super cool, and I liked the idea of having a personal place to share your opinions and the things you've learned.
|
||||
|
||||
Akita is a seasoned guy who's been in the industry for years. Me? Just a student slightly ahead of the material in my CS program. To people my age, this whole writing thing, having a blog, sounds like something old people do. But, like I said in my [last post](https://gabeefran.co/posts/spotify-complaining), I like the idea of doing things the old-fashioned way every now and then. The word _"Blog"_ sounds so 2010, but I don't know what else I'd call this crappy site you're reading. I guess _"blog"_ it is. Good thing I've been practicing caring less about what other people think, and look at that: it's working!
|
||||
|
||||
Anyway, call it whatever you want, I think it's worth posting something here every now and then. Even if nobody's interested, whatever! Then let it just be my public folder of notes. Just the fact that I opened the drawer and pulled my creativity out from the back of it already makes it all worth it.
|
||||
Hi!
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
---
|
||||
title: "O Hello World desse blog (ou seja lá como você queira chamar esse site)"
|
||||
description: "Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."
|
||||
pubDate: 2026-09-22
|
||||
title: "Olá, mundo"
|
||||
description: "Uma nota curta sobre por que este blog existe e sobre o que pretendo escrever aqui."
|
||||
pubDate: 2026-01-12
|
||||
tags: ["meta", "blogging"]
|
||||
---
|
||||
|
||||
Eu sempre tive um lado criativo, quem me conhece sabe. Às vezes ele fica guardado em algum lugar obscuro, no fundo da gaveta, esperando anos pra ser utilizado. E às vezes eu me aproveito dele muito bem.
|
||||
Sempre gostei muito de escrever, e faz tempo que queria ter um lugar só meu pra publicar meus pensamentos. Mas só aqueles que eu gostaria que fossem públicos, claro. Ninguém quer entregar todo o funcionamento interno do seu cérebro assim, de graça. Ainda assim, acho que algumas das minhas aventuras intelectuais merecem um pouco de exposição, até porque, sem alguém pra julgar, nunca saberei se valeram a pena.
|
||||
|
||||
Uma das minhas inspirações pra criar um site/blog foi o [Fábio Akita](https://instagram.com/akitaonrails). Eu acompanho ele há muito tempo, e foi por meio dos vídeos do [canal do YouTube dele](https://youtube.com/akitaonrails) que eu comecei a estudar sobre computação, antes de entrar na faculdade. Apesar dos vídeos serem realmente muito bons, fornecendo aprendizados difíceis de obter de outra forma, depois de um tempo maratonando os vídeos eu descobri o blog dele, [akitaonrails.com](https://akitaonrails.com). Eu achei muito massa, e gostei da ideia de se ter um lugar pessoal onde se expõem opiniões e aprendizados.
|
||||
|
||||
O Akita é um cara com experiência, que vive há anos na indústria. Eu, um mero estudante levemente adiantado no conteúdo da faculdade de computação. Esse negócio de escrever, ter um blog, parece coisa de gente velha pras pessoas da minha geração. Mas, como falei no [último post](https://gabeefran.co/pt/posts/spotify-complaining), eu gosto da ideia de fazer coisas à moda antiga de vez em quando. O termo _"Blog"_ soa muito 2010, mas não sei que outro nome daria a esta porcaria deste site que você está lendo. Acho que vai ser _"blog"_ mesmo. Bem que eu tenho treinado pra ligar menos pra opinião dos outros, e olha só: tá funcionando!
|
||||
|
||||
Enfim, chame como você quiser, eu acho que vale a pena publicar algo de vez em quando por aqui. Mesmo que ninguém esteja interessado, tanto faz! Que seja apenas a minha pasta pública de notas, então. Só de eu ter aberto a gaveta e tirado de lá do fundo a minha criatividade, considero que já valeu a pena.
|
||||
|
||||
|
||||
Oie
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ const postsHref = getLocalizedPath('/posts', lang);
|
|||
const tagsHref = (tag: string) => getLocalizedPath(`/tags/${tag}`, lang);
|
||||
---
|
||||
|
||||
<article class="mx-10 my-10 font-mono">
|
||||
<a href={postsHref} class="underline inline-flex items-center gap-1.5 text-sm font-medium text-text-muted hover:text-primary">
|
||||
<article class="mx-auto max-w-3xl px-4 py-12 sm:px-6">
|
||||
<a href={postsHref} class="inline-flex items-center gap-1.5 text-sm font-medium text-text-muted transition-colors hover:text-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4">
|
||||
<path d="M15 18l-6-6 6-6"></path>
|
||||
</svg>
|
||||
|
|
@ -42,7 +42,7 @@ const tagsHref = (tag: string) => getLocalizedPath(`/tags/${tag}`, lang);
|
|||
{post.data.tags.map((tag) => (
|
||||
<a
|
||||
href={tagsHref(tag)}
|
||||
class=" text-xs font-medium text-text-muted underline hover:text-accent"
|
||||
class="rounded-full bg-surface-alt px-2.5 py-1 text-xs font-medium text-text-muted transition-colors hover:bg-accent/15 hover:text-accent"
|
||||
>
|
||||
#{tag}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const ui = {
|
|||
'hero.kicker': "Gabriel Franco's notes",
|
||||
'hero.title': 'Building things, and figuring out how they work.',
|
||||
'hero.subtitle':
|
||||
"Notes on computer science, systems, and the open source projects that shaped how I think about software. I'm Gabriel Franco — welcome.",
|
||||
"Notes on computer science, systems, and the open source projects that shaped how I think about software. I'm gabeefranco — welcome.",
|
||||
'hero.cta.posts': 'Read the posts',
|
||||
'hero.cta.about': 'About me',
|
||||
'home.recent': 'Recent posts',
|
||||
|
|
@ -54,7 +54,7 @@ export const ui = {
|
|||
'hero.kicker': 'Anotações do Gabriel Franco',
|
||||
'hero.title': 'Construindo coisas e entendendo como elas funcionam.',
|
||||
'hero.subtitle':
|
||||
'Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software. Eu sou o Gabriel Franco — seja bem-vindo.',
|
||||
'Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software. Eu sou o gabeefranco — seja bem-vindo.',
|
||||
'hero.cta.posts': 'Ler os posts',
|
||||
'hero.cta.about': 'Sobre mim',
|
||||
'home.recent': 'Posts recentes',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const langs: Lang[] = ['en', 'pt'];
|
|||
---
|
||||
|
||||
<BaseLayout title={`${ui.en['404.title']} — gabeefranco`} description={ui.en['404.body']} lang="en">
|
||||
<section class="mx-10 flex flex-col items-start px-4 py-24 sm:px-6 font-mono">
|
||||
<section class="mx-auto flex max-w-3xl flex-col items-start px-4 py-24 sm:px-6">
|
||||
<p class="font-mono text-sm text-primary">404</p>
|
||||
{langs.map((lang) => (
|
||||
<div data-notfound-lang={lang} class={lang === 'en' ? '' : 'hidden'}>
|
||||
|
|
@ -18,7 +18,7 @@ const langs: Lang[] = ['en', 'pt'];
|
|||
<p class="mt-3 text-text-muted">{ui[lang]['404.body']}</p>
|
||||
<a
|
||||
href={getLocalizedPath('/', lang)}
|
||||
class="mt-4 inline-block underline text-primary hover:text-primary-hover font-bold"
|
||||
class="mt-6 inline-block rounded-full bg-primary px-5 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-primary-hover"
|
||||
>
|
||||
{ui[lang]['404.cta']}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const description =
|
|||
---
|
||||
|
||||
<BaseLayout title={`${t('about.title')} — ${t('site.name')}`} description={description} lang="en">
|
||||
<section class="mx-10 mt-10 font-mono">
|
||||
<section class="mx-auto max-w-3xl px-4 py-14 sm:px-6">
|
||||
<h1 class="text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('about.title')}</h1>
|
||||
|
||||
<div class="prose prose-neutral mt-6 max-w-none prose-headings:font-semibold prose-a:text-primary prose-a:no-underline hover:prose-a:underline dark:prose-invert">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const description =
|
|||
---
|
||||
|
||||
<BaseLayout title={`${t('about.title')} — ${t('site.name')}`} description={description} lang="pt">
|
||||
<section class="mx-10 mt-10 font-mono">
|
||||
<section class="mx-auto max-w-3xl px-4 py-14 sm:px-6">
|
||||
<h1 class="text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('about.title')}</h1>
|
||||
|
||||
<div class="prose prose-neutral mt-6 max-w-none prose-headings:font-semibold prose-a:text-primary prose-a:no-underline hover:prose-a:underline dark:prose-invert">
|
||||
|
|
|
|||
Loading…
Reference in a new issue