Compare commits

..

No commits in common. "523127092f0fb665e9ba81de9b847fee2dddd268" and "db0964e79265d9d30e78f686d50f0850ff67fbba" have entirely different histories.

66 changed files with 112 additions and 426 deletions

View file

@ -1,24 +0,0 @@
import { n as __exportAll, t as createComponent } from "./compiler_DiXpMM4i.mjs";
import { g as renderHead, m as renderTemplate, w as createAstro } from "./jsx-runtime_DseUv9uh.mjs";
//#region src/pages/page-card.astro
var page_card_exports = /* @__PURE__ */ __exportAll({
default: () => $$PageCard,
file: () => $$file,
prerender: () => false,
url: () => $$url
});
createAstro("https://gabeefran.co");
var $$PageCard = createComponent(($$result, $$props, $$slots) => {
const Astro = $$result.createAstro($$props, $$slots);
Astro.self = $$PageCard;
const title = Astro.url.searchParams.get("title") || "gabeefranco";
const description = Astro.url.searchParams.get("description");
return renderTemplate`<html data-astro-cid-jwkqgd2l><head><meta charset="utf-8"><meta name="robots" content="noindex"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=JetBrains+Mono:wght@600&display=swap" rel="stylesheet">${renderHead($$result)}</head><body data-astro-cid-jwkqgd2l><div class="brand" data-astro-cid-jwkqgd2l><img src="/logo.png" alt="" data-astro-cid-jwkqgd2l><span data-astro-cid-jwkqgd2l>gabeefranco</span></div><h1 class="title" data-astro-cid-jwkqgd2l>${title}</h1>${description && renderTemplate`<p class="description" data-astro-cid-jwkqgd2l>${description}</p>`}</body></html>`;
}, "/home/gabe/src/gabeefran.co-blog/src/pages/page-card.astro", void 0);
var $$file = "/home/gabe/src/gabeefran.co-blog/src/pages/page-card.astro";
var $$url = "/page-card";
//#endregion
//#region \0virtual:astro:page:src/pages/page-card@_@astro
var page = () => page_card_exports;
//#endregion
export { page };

File diff suppressed because one or more lines are too long

View file

@ -19,10 +19,6 @@
"src": "^/_image/?$",
"dest": "_render"
},
{
"src": "^/page-card/?$",
"dest": "_render"
},
{
"src": "^/social-card/?$",
"dest": "_render"

View file

@ -1,24 +0,0 @@
import { n as __exportAll, t as createComponent } from "./compiler_DiXpMM4i.mjs";
import { g as renderHead, m as renderTemplate, w as createAstro } from "./jsx-runtime_DseUv9uh.mjs";
//#region src/pages/page-card.astro
var page_card_exports = /* @__PURE__ */ __exportAll({
default: () => $$PageCard,
file: () => $$file,
prerender: () => false,
url: () => $$url
});
createAstro("https://gabeefran.co");
var $$PageCard = createComponent(($$result, $$props, $$slots) => {
const Astro = $$result.createAstro($$props, $$slots);
Astro.self = $$PageCard;
const title = Astro.url.searchParams.get("title") || "gabeefranco";
const description = Astro.url.searchParams.get("description");
return renderTemplate`<html data-astro-cid-jwkqgd2l><head><meta charset="utf-8"><meta name="robots" content="noindex"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=JetBrains+Mono:wght@600&display=swap" rel="stylesheet">${renderHead($$result)}</head><body data-astro-cid-jwkqgd2l><div class="brand" data-astro-cid-jwkqgd2l><img src="/logo.png" alt="" data-astro-cid-jwkqgd2l><span data-astro-cid-jwkqgd2l>gabeefranco</span></div><h1 class="title" data-astro-cid-jwkqgd2l>${title}</h1>${description && renderTemplate`<p class="description" data-astro-cid-jwkqgd2l>${description}</p>`}</body></html>`;
}, "/home/gabe/src/gabeefran.co-blog/src/pages/page-card.astro", void 0);
var $$file = "/home/gabe/src/gabeefran.co-blog/src/pages/page-card.astro";
var $$url = "/page-card";
//#endregion
//#region \0virtual:astro:page:src/pages/page-card@_@astro
var page = () => page_card_exports;
//#endregion
export { page };

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/404/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/404/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/404/"><meta name="generator" content="Astro v7.2.10"><title>Page not found — gabeefranco</title><meta name="description" content="There’s nothing here. Let’s get you back home."><meta property="og:type" content="website"><meta property="og:title" content="Page not found — gabeefranco"><meta property="og:description" content="There’s nothing here. Let’s get you back home."><meta property="og:url" content="https://gabeefran.co/404/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Page not found — gabeefranco"><meta name="twitter:description" content="There’s nothing here. Let’s get you back home."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/404/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/404/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/404/"><meta name="generator" content="Astro v7.2.10"><title>Page not found — gabeefranco</title><meta name="description" content="There’s nothing here. Let’s get you back home."><meta property="og:type" content="website"><meta property="og:title" content="Page not found — gabeefranco"><meta property="og:description" content="There’s nothing here. Let’s get you back home."><meta property="og:url" content="https://gabeefran.co/404/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/about/"><meta name="generator" content="Astro v7.2.10"><title>About — gabeefranco</title><meta name="description" content="Gabriel Franco: computer science student at PUCRS, interested in how software actually works and in the history of open source."><meta property="og:type" content="website"><meta property="og:title" content="About — gabeefranco"><meta property="og:description" content="Gabriel Franco: computer science student at PUCRS, interested in how software actually works and in the history of open source."><meta property="og:url" content="https://gabeefran.co/about/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="About — gabeefranco"><meta name="twitter:description" content="Gabriel Franco: computer science student at PUCRS, interested in how software actually works and in the history of open source."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/about/"><meta name="generator" content="Astro v7.2.10"><title>About — gabeefranco</title><meta name="description" content="Gabriel Franco (gabeefranco): computer science student at PUCRS, interested in how software actually works and in the history of the open source movement."><meta property="og:type" content="website"><meta property="og:title" content="About — gabeefranco"><meta property="og:description" content="Gabriel Franco (gabeefranco): computer science student at PUCRS, interested in how software actually works and in the history of the open source movement."><meta property="og:url" content="https://gabeefran.co/about/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/"><meta name="generator" content="Astro v7.2.10"><title>gabeefranco — Gabriel Franco&#39;s notes</title><meta name="description" content="Notes on computer science, systems, and the open source projects that shaped how I think about software."><meta property="og:type" content="website"><meta property="og:title" content="gabeefranco — Gabriel Franco's notes"><meta property="og:description" content="Notes on computer science, systems, and the open source projects that shaped how I think about software."><meta property="og:url" content="https://gabeefran.co/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="gabeefranco — Gabriel Franco's notes"><meta name="twitter:description" content="Notes on computer science, systems, and the open source projects that shaped how I think about software."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/"><meta name="generator" content="Astro v7.2.10"><title>gabeefranco — Gabriel Franco&#39;s notes</title><meta name="description" content="Notes on computer science, systems, and the open source projects that shaped how I think about software. I'm Gabriel Franco — welcome."><meta property="og:type" content="website"><meta property="og:title" content="gabeefranco — Gabriel Franco's notes"><meta property="og:description" content="Notes on computer science, systems, and the open source projects that shaped how I think about software. I'm Gabriel Franco — welcome."><meta property="og:url" content="https://gabeefran.co/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/hello-world/"><meta name="generator" content="Astro v7.2.10"><title>This blog&#39;s Hello World (or whatever you want to call this site) — gabeefranco</title><meta name="description" content="A short note on why this exists and what I plan to write about here."><meta property="og:type" content="website"><meta property="og:title" content="This blog's Hello World (or whatever you want to call this site) — gabeefranco"><meta property="og:description" content="A short note on why this exists and what I plan to write about here."><meta property="og:url" content="https://gabeefran.co/posts/hello-world/"><meta property="og:image" content="https://gabeefran.co/social-cards/en/hello-world.png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="This blog's Hello World (or whatever you want to call this site) — gabeefranco"><meta name="twitter:description" content="A short note on why this exists and what I plan to write about here."><meta name="twitter:image" content="https://gabeefran.co/social-cards/en/hello-world.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/hello-world/"><meta name="generator" content="Astro v7.2.10"><title>This blog&#39;s Hello World (or whatever you want to call this site) — gabeefranco</title><meta name="description" content="A short note on why this exists and what I plan to write about here."><meta property="og:type" content="website"><meta property="og:title" content="This blog's Hello World (or whatever you want to call this site) — gabeefranco"><meta property="og:description" content="A short note on why this exists and what I plan to write about here."><meta property="og:url" content="https://gabeefran.co/posts/hello-world/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/"><meta name="generator" content="Astro v7.2.10"><title>All posts — gabeefranco</title><meta name="description" content="Everything I’ve written about computer science, systems, and open source, newest first."><meta property="og:type" content="website"><meta property="og:title" content="All posts — gabeefranco"><meta property="og:description" content="Everything I’ve written about computer science, systems, and open source, newest first."><meta property="og:url" content="https://gabeefran.co/posts/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="All posts — gabeefranco"><meta name="twitter:description" content="Everything I’ve written about computer science, systems, and open source, newest first."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/"><meta name="generator" content="Astro v7.2.10"><title>All posts — gabeefranco</title><meta name="description" content="Everything I’ve written, oldest to newest below, newest on top."><meta property="og:type" content="website"><meta property="og:title" content="All posts — gabeefranco"><meta property="og:description" content="Everything I’ve written, oldest to newest below, newest on top."><meta property="og:url" content="https://gabeefran.co/posts/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/spotify-complaining/"><meta name="generator" content="Astro v7.2.10"><title>Spotify&#39;s Time Capsule Change and the Enshittification of Software — gabeefranco</title><meta name="description" content="Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into."><meta property="og:type" content="website"><meta property="og:title" content="Spotify's Time Capsule Change and the Enshittification of Software — gabeefranco"><meta property="og:description" content="Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into."><meta property="og:url" content="https://gabeefran.co/posts/spotify-complaining/"><meta property="og:image" content="https://gabeefran.co/social-cards/en/spotify-complaining.png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Spotify's Time Capsule Change and the Enshittification of Software — gabeefranco"><meta name="twitter:description" content="Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into."><meta name="twitter:image" content="https://gabeefran.co/social-cards/en/spotify-complaining.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/spotify-complaining/"><meta name="generator" content="Astro v7.2.10"><title>Spotify&#39;s Time Capsule Change and the Enshittification of Software — gabeefranco</title><meta name="description" content="Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into."><meta property="og:type" content="website"><meta property="og:title" content="Spotify's Time Capsule Change and the Enshittification of Software — gabeefranco"><meta property="og:description" content="Spotify just removed one of its best features. Beyond a bit of complaining, I want to open a debate about what software is turning into."><meta property="og:url" content="https://gabeefran.co/posts/spotify-complaining/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/about/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/about/"><meta name="generator" content="Astro v7.2.10"><title>Sobre — gabeefranco</title><meta name="description" content="Gabriel Franco: estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do open source."><meta property="og:type" content="website"><meta property="og:title" content="Sobre — gabeefranco"><meta property="og:description" content="Gabriel Franco: estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do open source."><meta property="og:url" content="https://gabeefran.co/pt/about/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Sobre — gabeefranco"><meta name="twitter:description" content="Gabriel Franco: estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do open source."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/about/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/about/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/about/"><meta name="generator" content="Astro v7.2.10"><title>Sobre — gabeefranco</title><meta name="description" content="Gabriel Franco (gabeefranco): estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do movimento open source."><meta property="og:type" content="website"><meta property="og:title" content="Sobre — gabeefranco"><meta property="og:description" content="Gabriel Franco (gabeefranco): estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do movimento open source."><meta property="og:url" content="https://gabeefran.co/pt/about/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/"><meta name="generator" content="Astro v7.2.10"><title>gabeefranco — Anotações do Gabriel Franco</title><meta name="description" content="Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software."><meta property="og:type" content="website"><meta property="og:title" content="gabeefranco — Anotações do Gabriel Franco"><meta property="og:description" content="Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software."><meta property="og:url" content="https://gabeefran.co/pt/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="gabeefranco — Anotações do Gabriel Franco"><meta name="twitter:description" content="Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/"><meta name="generator" content="Astro v7.2.10"><title>gabeefranco — Anotações do Gabriel Franco</title><meta name="description" content="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."><meta property="og:type" content="website"><meta property="og:title" content="gabeefranco — Anotações do Gabriel Franco"><meta property="og:description" content="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."><meta property="og:url" content="https://gabeefran.co/pt/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/hello-world/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/hello-world/"><meta name="generator" content="Astro v7.2.10"><title>O Hello World desse blog (ou seja lá como você queira chamar esse site) — gabeefranco</title><meta name="description" content="Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."><meta property="og:type" content="website"><meta property="og:title" content="O Hello World desse blog (ou seja lá como você queira chamar esse site) — gabeefranco"><meta property="og:description" content="Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."><meta property="og:url" content="https://gabeefran.co/pt/posts/hello-world/"><meta property="og:image" content="https://gabeefran.co/social-cards/pt/hello-world.png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="O Hello World desse blog (ou seja lá como você queira chamar esse site) — gabeefranco"><meta name="twitter:description" content="Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."><meta name="twitter:image" content="https://gabeefran.co/social-cards/pt/hello-world.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/hello-world/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/hello-world/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/hello-world/"><meta name="generator" content="Astro v7.2.10"><title>O Hello World desse blog (ou seja lá como você queira chamar esse site) — gabeefranco</title><meta name="description" content="Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."><meta property="og:type" content="website"><meta property="og:title" content="O Hello World desse blog (ou seja lá como você queira chamar esse site) — gabeefranco"><meta property="og:description" content="Uma nota curta sobre por que isso existe e sobre o que pretendo escrever aqui."><meta property="og:url" content="https://gabeefran.co/pt/posts/hello-world/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/"><meta name="generator" content="Astro v7.2.10"><title>Todos os posts — gabeefranco</title><meta name="description" content="Tudo que já escrevi sobre ciência da computação, sistemas e open source, do mais recente ao mais antigo."><meta property="og:type" content="website"><meta property="og:title" content="Todos os posts — gabeefranco"><meta property="og:description" content="Tudo que já escrevi sobre ciência da computação, sistemas e open source, do mais recente ao mais antigo."><meta property="og:url" content="https://gabeefran.co/pt/posts/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Todos os posts — gabeefranco"><meta name="twitter:description" content="Tudo que já escrevi sobre ciência da computação, sistemas e open source, do mais recente ao mais antigo."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/"><meta name="generator" content="Astro v7.2.10"><title>Todos os posts — gabeefranco</title><meta name="description" content="Tudo que já escrevi, do mais recente para o mais antigo."><meta property="og:type" content="website"><meta property="og:title" content="Todos os posts — gabeefranco"><meta property="og:description" content="Tudo que já escrevi, do mais recente para o mais antigo."><meta property="og:url" content="https://gabeefran.co/pt/posts/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/spotify-complaining/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/spotify-complaining/"><meta name="generator" content="Astro v7.2.10"><title>A mudança na cápsula do tempo do Spotify e a bostificação do software — gabeefranco</title><meta name="description" content="Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando."><meta property="og:type" content="website"><meta property="og:title" content="A mudança na cápsula do tempo do Spotify e a bostificação do software — gabeefranco"><meta property="og:description" content="Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando."><meta property="og:url" content="https://gabeefran.co/pt/posts/spotify-complaining/"><meta property="og:image" content="https://gabeefran.co/social-cards/pt/spotify-complaining.png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="A mudança na cápsula do tempo do Spotify e a bostificação do software — gabeefranco"><meta name="twitter:description" content="Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando."><meta name="twitter:image" content="https://gabeefran.co/social-cards/pt/spotify-complaining.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/posts/spotify-complaining/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/posts/spotify-complaining/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/posts/spotify-complaining/"><meta name="generator" content="Astro v7.2.10"><title>A mudança na cápsula do tempo do Spotify e a bostificação do software — gabeefranco</title><meta name="description" content="Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando."><meta property="og:type" content="website"><meta property="og:title" content="A mudança na cápsula do tempo do Spotify e a bostificação do software — gabeefranco"><meta property="og:description" content="Spotify simplesmente removeu uma das suas melhores funcionalidades. Além de reclamar um pouco, quero abrir um debate sobre o que os softwares estão se tornando."><meta property="og:url" content="https://gabeefran.co/pt/posts/spotify-complaining/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/blogging/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/blogging/"><meta name="generator" content="Astro v7.2.10"><title>#blogging — gabeefranco</title><meta name="description" content="Tudo que já escrevi com a tag #blogging."><meta property="og:type" content="website"><meta property="og:title" content="#blogging — gabeefranco"><meta property="og:description" content="Tudo que já escrevi com a tag #blogging."><meta property="og:url" content="https://gabeefran.co/pt/tags/blogging/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#blogging — gabeefranco"><meta name="twitter:description" content="Tudo que já escrevi com a tag #blogging."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/blogging/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/blogging/"><meta name="generator" content="Astro v7.2.10"><title>#blogging — gabeefranco</title><meta name="description" content="Posts com a tag #blogging: O Hello World desse blog (ou seja lá como você queira chamar esse site)"><meta property="og:type" content="website"><meta property="og:title" content="#blogging — gabeefranco"><meta property="og:description" content="Posts com a tag #blogging: O Hello World desse blog (ou seja lá como você queira chamar esse site)"><meta property="og:url" content="https://gabeefran.co/pt/tags/blogging/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/life/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/life/"><meta name="generator" content="Astro v7.2.10"><title>#life — gabeefranco</title><meta name="description" content="Tudo que já escrevi com a tag #life."><meta property="og:type" content="website"><meta property="og:title" content="#life — gabeefranco"><meta property="og:description" content="Tudo que já escrevi com a tag #life."><meta property="og:url" content="https://gabeefran.co/pt/tags/life/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#life — gabeefranco"><meta name="twitter:description" content="Tudo que já escrevi com a tag #life."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/life/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/life/"><meta name="generator" content="Astro v7.2.10"><title>#life — gabeefranco</title><meta name="description" content="Posts com a tag #life: A mudança na cápsula do tempo do Spotify e a bostificação do software"><meta property="og:type" content="website"><meta property="og:title" content="#life — gabeefranco"><meta property="og:description" content="Posts com a tag #life: A mudança na cápsula do tempo do Spotify e a bostificação do software"><meta property="og:url" content="https://gabeefran.co/pt/tags/life/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/meta/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/meta/"><meta name="generator" content="Astro v7.2.10"><title>#meta — gabeefranco</title><meta name="description" content="Tudo que já escrevi com a tag #meta."><meta property="og:type" content="website"><meta property="og:title" content="#meta — gabeefranco"><meta property="og:description" content="Tudo que já escrevi com a tag #meta."><meta property="og:url" content="https://gabeefran.co/pt/tags/meta/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#meta — gabeefranco"><meta name="twitter:description" content="Tudo que já escrevi com a tag #meta."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/meta/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/meta/"><meta name="generator" content="Astro v7.2.10"><title>#meta — gabeefranco</title><meta name="description" content="Posts com a tag #meta: O Hello World desse blog (ou seja lá como você queira chamar esse site)"><meta property="og:type" content="website"><meta property="og:title" content="#meta — gabeefranco"><meta property="og:description" content="Posts com a tag #meta: O Hello World desse blog (ou seja lá como você queira chamar esse site)"><meta property="og:url" content="https://gabeefran.co/pt/tags/meta/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/software/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/software/"><meta name="generator" content="Astro v7.2.10"><title>#software — gabeefranco</title><meta name="description" content="Tudo que já escrevi com a tag #software."><meta property="og:type" content="website"><meta property="og:title" content="#software — gabeefranco"><meta property="og:description" content="Tudo que já escrevi com a tag #software."><meta property="og:url" content="https://gabeefran.co/pt/tags/software/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#software — gabeefranco"><meta name="twitter:description" content="Tudo que já escrevi com a tag #software."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="pt"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/pt/tags/software/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/software/"><meta name="generator" content="Astro v7.2.10"><title>#software — gabeefranco</title><meta name="description" content="Posts com a tag #software: A mudança na cápsula do tempo do Spotify e a bostificação do software"><meta property="og:type" content="website"><meta property="og:title" content="#software — gabeefranco"><meta property="og:description" content="Posts com a tag #software: A mudança na cápsula do tempo do Spotify e a bostificação do software"><meta property="og:url" content="https://gabeefran.co/pt/tags/software/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/blogging/"><meta name="generator" content="Astro v7.2.10"><title>#blogging — gabeefranco</title><meta name="description" content="Everything I’ve written tagged #blogging."><meta property="og:type" content="website"><meta property="og:title" content="#blogging — gabeefranco"><meta property="og:description" content="Everything I’ve written tagged #blogging."><meta property="og:url" content="https://gabeefran.co/tags/blogging/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#blogging — gabeefranco"><meta name="twitter:description" content="Everything I’ve written tagged #blogging."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/blogging/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/blogging/"><meta name="generator" content="Astro v7.2.10"><title>#blogging — gabeefranco</title><meta name="description" content="Posts tagged #blogging: This blog's Hello World (or whatever you want to call this site)"><meta property="og:type" content="website"><meta property="og:title" content="#blogging — gabeefranco"><meta property="og:description" content="Posts tagged #blogging: This blog's Hello World (or whatever you want to call this site)"><meta property="og:url" content="https://gabeefran.co/tags/blogging/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/life/"><meta name="generator" content="Astro v7.2.10"><title>#life — gabeefranco</title><meta name="description" content="Everything I’ve written tagged #life."><meta property="og:type" content="website"><meta property="og:title" content="#life — gabeefranco"><meta property="og:description" content="Everything I’ve written tagged #life."><meta property="og:url" content="https://gabeefran.co/tags/life/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#life — gabeefranco"><meta name="twitter:description" content="Everything I’ve written tagged #life."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/life/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/life/"><meta name="generator" content="Astro v7.2.10"><title>#life — gabeefranco</title><meta name="description" content="Posts tagged #life: Spotify's Time Capsule Change and the Enshittification of Software"><meta property="og:type" content="website"><meta property="og:title" content="#life — gabeefranco"><meta property="og:description" content="Posts tagged #life: Spotify's Time Capsule Change and the Enshittification of Software"><meta property="og:url" content="https://gabeefran.co/tags/life/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/meta/"><meta name="generator" content="Astro v7.2.10"><title>#meta — gabeefranco</title><meta name="description" content="Everything I’ve written tagged #meta."><meta property="og:type" content="website"><meta property="og:title" content="#meta — gabeefranco"><meta property="og:description" content="Everything I’ve written tagged #meta."><meta property="og:url" content="https://gabeefran.co/tags/meta/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#meta — gabeefranco"><meta name="twitter:description" content="Everything I’ve written tagged #meta."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/meta/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/meta/"><meta name="generator" content="Astro v7.2.10"><title>#meta — gabeefranco</title><meta name="description" content="Posts tagged #meta: This blog's Hello World (or whatever you want to call this site)"><meta property="og:type" content="website"><meta property="og:title" content="#meta — gabeefranco"><meta property="og:description" content="Posts tagged #meta: This blog's Hello World (or whatever you want to call this site)"><meta property="og:url" content="https://gabeefran.co/tags/meta/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/software/"><meta name="generator" content="Astro v7.2.10"><title>#software — gabeefranco</title><meta name="description" content="Everything I’ve written tagged #software."><meta property="og:type" content="website"><meta property="og:title" content="#software — gabeefranco"><meta property="og:description" content="Everything I’ve written tagged #software."><meta property="og:url" content="https://gabeefran.co/tags/software/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="#software — gabeefranco"><meta name="twitter:description" content="Everything I’ve written tagged #software."><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.svg" type="image/svg+xml"><link rel="alternate icon" href="/favicon.ico"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="canonical" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="en" href="https://gabeefran.co/tags/software/"><link rel="alternate" hreflang="pt-BR" href="https://gabeefran.co/pt/tags/software/"><meta name="generator" content="Astro v7.2.10"><title>#software — gabeefranco</title><meta name="description" content="Posts tagged #software: Spotify's Time Capsule Change and the Enshittification of Software"><meta property="og:type" content="website"><meta property="og:title" content="#software — gabeefranco"><meta property="og:description" content="Posts tagged #software: Spotify's Time Capsule Change and the Enshittification of Software"><meta property="og:url" content="https://gabeefran.co/tags/software/"><meta property="og:image" content="https://gabeefran.co/logo.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="https://gabeefran.co/logo.png"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"><script>
// Runs before paint to avoid a flash of the wrong theme.
(function () {
const stored = localStorage.getItem('theme');
@ -6,7 +6,7 @@
const dark = stored ? stored === 'dark' : prefersDark;
document.documentElement.classList.toggle('dark', dark);
})();
</script><link rel="stylesheet" href="/_astro/BaseLayout.z2Ysa6px.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
</script><link rel="stylesheet" href="/_astro/BaseLayout.C3cx7DTv.css"><script>window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };
var script = document.createElement('script');
script.defer = true;
script.src = '/_vercel/insights/script.js';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View file

@ -1,40 +1,25 @@
// Generates OG images for every post and every other page (home, posts,
// about, tags, 404) using Cloudflare Browser Run.
// Generates OG images for every post using Cloudflare Browser Run.
// Adapted from https://developers.cloudflare.com/browser-run/how-to/og-images-astro/
//
// Usage: npm run og (only missing images)
// npm run og -- --force (regenerate all)
//
// Needs CF_ACCOUNT_ID and CF_API_TOKEN (read from .env), and the
// /social-card and /page-card routes must be deployed at BASE_URL.
// /social-card route must be deployed at BASE_URL.
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { PAGES, pageCardPath, tagCardPath, tagPage, type PageKey } from '../src/lib/pages.ts';
import { join } from 'node:path';
const BASE_URL = process.env.SOCIAL_CARD_BASE_URL ?? 'https://gabeefran.co';
const CF_API = 'https://api.cloudflare.com/client/v4/accounts';
const OUTPUT_DIR = 'public/social-cards';
const POSTS_DIR = 'src/content/posts';
const LANGS = ['en', 'pt'] as const;
// 404.html is prerendered once, in English (see src/pages/404.astro).
const LANG_PAGES: Record<(typeof LANGS)[number], PageKey[]> = {
en: ['home', 'posts', 'about', '404'],
pt: ['home', 'posts', 'about'],
};
const LANGS = ['en', 'pt'];
interface Post {
lang: (typeof LANGS)[number];
lang: string;
slug: string;
title: string;
description?: string;
tags: string[];
}
interface Card {
/** Path under public/, e.g. /social-cards/en/hello-world.png */
path: string;
/** Card template route: /social-card for posts, /page-card for everything else. */
route: '/social-card' | '/page-card';
params: Record<string, string>;
}
function getFrontmatterField(content: string, field: string): string | null {
@ -42,12 +27,6 @@ function getFrontmatterField(content: string, field: string): string | null {
return match ? match[1].trim() : null;
}
/** Reads an inline tag list, e.g. `tags: ["meta", "blogging"]`. */
function getFrontmatterTags(content: string): string[] {
const list = content.match(/^tags:\s*\[([^\]]*)\]/m)?.[1] ?? '';
return [...list.matchAll(/["']([^"']+)["']/g)].map((m) => m[1]);
}
/** Posts live at src/content/posts/<lang>/<slug>.mdx (see src/content.config.ts). */
function readPosts(): Post[] {
return LANGS.flatMap((lang) => {
@ -61,34 +40,12 @@ function readPosts(): Post[] {
const slug = file.replace(/\.mdx$/, '');
const title = getFrontmatterField(raw, 'title') ?? slug;
const description = getFrontmatterField(raw, 'description') ?? undefined;
const tags = getFrontmatterTags(raw);
return { lang, slug, title, description, tags };
return { lang, slug, title, description };
})
.filter((p): p is Post => p !== null);
});
}
function listCards(posts: Post[]): Card[] {
const postCards: Card[] = posts.map((post) => {
const params: Record<string, string> = { title: post.title, author: 'Gabriel Franco' };
if (post.description) params.description = post.description;
return { path: `/social-cards/${post.lang}/${post.slug}.png`, route: '/social-card', params };
});
const pageCards: Card[] = LANGS.flatMap((lang) => {
const pages = LANG_PAGES[lang].map((key) => ({ path: pageCardPath(lang, key), meta: PAGES[lang][key] }));
const tags = [...new Set(posts.filter((p) => p.lang === lang).flatMap((p) => p.tags))].sort();
const tagPages = tags.map((tag) => ({ path: tagCardPath(lang, tag), meta: tagPage(lang, tag) }));
return [...pages, ...tagPages].map(({ path, meta }) => ({
path,
route: '/page-card' as const,
params: { title: meta.title, description: meta.description },
}));
});
return [...postCards, ...pageCards];
}
async function captureScreenshot(accountId: string, apiToken: string, pageUrl: string): Promise<ArrayBuffer> {
const res = await fetch(`${CF_API}/${accountId}/browser-run/screenshot`, {
method: 'POST',
@ -118,18 +75,23 @@ async function main() {
}
const force = process.argv.includes('--force');
const cards = listCards(readPosts());
console.log(`Found ${cards.length} cards to process\n`);
const posts = readPosts();
if (posts.length === 0) {
console.log(`No posts found in ${POSTS_DIR}.`);
return;
}
console.log(`Found ${posts.length} posts to process\n`);
let generated = 0;
let skipped = 0;
let failed = 0;
for (let i = 0; i < cards.length; i++) {
const card = cards[i];
const outPath = join('public', card.path);
const name = card.path.replace(/^\/social-cards\//, '');
const label = `[${i + 1}/${cards.length}]`;
for (let i = 0; i < posts.length; i++) {
const post = posts[i];
const name = `${post.lang}/${post.slug}.png`;
const outDir = join(OUTPUT_DIR, post.lang);
const outPath = join(outDir, `${post.slug}.png`);
const label = `[${i + 1}/${posts.length}]`;
if (!force && existsSync(outPath)) {
console.log(`${label} ${name} — skipped (exists)`);
@ -137,11 +99,13 @@ async function main() {
continue;
}
const url = `${BASE_URL}${card.route}?${new URLSearchParams(card.params)}`;
const params = new URLSearchParams({ title: post.title, author: 'Gabriel Franco' });
if (post.description) params.set('description', post.description);
const url = `${BASE_URL}/social-card?${params}`;
try {
const png = await captureScreenshot(accountId, apiToken, url);
mkdirSync(dirname(outPath), { recursive: true });
mkdirSync(outDir, { recursive: true });
writeFileSync(outPath, Buffer.from(png));
console.log(`${label} ${name} — done`);
generated++;
@ -151,8 +115,8 @@ async function main() {
}
// Stay under Browser Run rate limits.
if (i < cards.length - 1) {
await new Promise((resolve) => setTimeout(resolve, 10000));
if (i < posts.length - 1) {
await new Promise((resolve) => setTimeout(resolve, 200));
}
}

View file

@ -1,5 +1,4 @@
---
import { existsSync } from 'node:fs';
import '../styles/global.css';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
@ -9,16 +8,11 @@ interface Props {
title: string;
description: string;
lang: Lang;
/**
* Path under public/ for the OG image, e.g. /social-cards/en/hello-world.png.
* Cards are generated by scripts/generate-social-cards.ts; until one exists
* on disk we fall back to the logo.
*/
/** Path under public/ for the OG image, e.g. /social-cards/en/hello-world.png */
image?: string;
}
const { title, description, lang } = Astro.props;
const image = Astro.props.image && existsSync(`public${Astro.props.image}`) ? Astro.props.image : '/logo.png';
const { title, description, lang, image = '/logo.png' } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
@ -39,7 +33,6 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
<meta name="description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Gabriel Franco's notes" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonicalURL} />
@ -51,8 +44,6 @@ const canonicalURL = new URL(Astro.url.pathname, Astro.site);
</>
)}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={new URL(image, Astro.site)} />
<link rel="preconnect" href="https://fonts.googleapis.com" />

View file

@ -1,69 +0,0 @@
// Title and description for every non-post page, shared by the pages
// themselves and by scripts/generate-social-cards.ts (so keep this file free
// of runtime imports: the script loads it directly with Node).
import type { Lang } from './i18n';
export type PageKey = 'home' | 'posts' | 'about' | '404';
export interface PageMeta {
title: string;
description: string;
}
export const PAGES: Record<Lang, Record<PageKey, PageMeta>> = {
en: {
home: {
title: 'Building things, and figuring out how they work.',
description:
'Notes on computer science, systems, and the open source projects that shaped how I think about software.',
},
posts: {
title: 'All posts',
description: 'Everything I’ve written about computer science, systems, and open source, newest first.',
},
about: {
title: 'About',
description:
'Gabriel Franco: computer science student at PUCRS, interested in how software actually works and in the history of open source.',
},
'404': {
title: 'Page not found',
description: 'There’s nothing here. Let’s get you back home.',
},
},
pt: {
home: {
title: 'Construindo coisas e entendendo como elas funcionam.',
description:
'Notas sobre ciência da computação, sistemas e os projetos open source que moldaram a forma como penso sobre software.',
},
posts: {
title: 'Todos os posts',
description: 'Tudo que já escrevi sobre ciência da computação, sistemas e open source, do mais recente ao mais antigo.',
},
about: {
title: 'Sobre',
description:
'Gabriel Franco: estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do open source.',
},
'404': {
title: 'Página não encontrada',
description: 'Não há nada aqui. Vamos te levar de volta para o início.',
},
},
};
export function tagPage(lang: Lang, tag: string): PageMeta {
return lang === 'pt'
? { title: `#${tag}`, description: `Tudo que já escrevi com a tag #${tag}.` }
: { title: `#${tag}`, description: `Everything I’ve written tagged #${tag}.` };
}
/** Where the generated card for a page lives, relative to public/. */
export function pageCardPath(lang: Lang, key: PageKey): string {
return `/social-cards/${lang}/pages/${key}.png`;
}
export function tagCardPath(lang: Lang, tag: string): string {
return `/social-cards/${lang}/tags/${tag}.png`;
}

View file

@ -1,7 +1,6 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { getLocalizedPath, ui, type Lang } from '../lib/i18n';
import { PAGES, pageCardPath } from '../lib/pages';
// This file is prerendered once as a static /404.html and served by the host
// for any unmatched path, so we can't know at build time whether the visitor
@ -10,12 +9,7 @@ import { PAGES, pageCardPath } from '../lib/pages';
const langs: Lang[] = ['en', 'pt'];
---
<BaseLayout
title={`${PAGES.en['404'].title} — gabeefranco`}
description={PAGES.en['404'].description}
lang="en"
image={pageCardPath('en', '404')}
>
<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">
<p class="font-mono text-sm text-primary">404</p>
{langs.map((lang) => (

View file

@ -1,13 +1,13 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { useTranslations } from '../lib/i18n';
import { PAGES, pageCardPath } from '../lib/pages';
const t = useTranslations('en');
const page = PAGES.en.about;
const description =
"Gabriel Franco (gabeefranco): computer science student at PUCRS, interested in how software actually works and in the history of the open source movement.";
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="en" image={pageCardPath('en', 'about')}>
<BaseLayout title={`${t('about.title')} — ${t('site.name')}`} description={description} lang="en">
<section class="mx-10 mt-10 font-mono">
<h1 class="text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('about.title')}</h1>

View file

@ -2,17 +2,10 @@
import BaseLayout from '../layouts/BaseLayout.astro';
import HomeContent from '../components/HomeContent.astro';
import { useTranslations } from '../lib/i18n';
import { PAGES, pageCardPath } from '../lib/pages';
const t = useTranslations('en');
const page = PAGES.en.home;
---
<BaseLayout
title={`${t('site.name')} — ${t('hero.kicker')}`}
description={page.description}
lang="en"
image={pageCardPath('en', 'home')}
>
<BaseLayout title={`${t('site.name')} — ${t('hero.kicker')}`} description={t('hero.subtitle')} lang="en">
<HomeContent lang="en" />
</BaseLayout>

View file

@ -1,78 +0,0 @@
---
// OG image template for non-post pages (home, posts, about, tags, 404).
// Same look as social-card.astro, without the author line. Screenshotted by
// scripts/generate-social-cards.ts via Cloudflare Browser Run; not meant to be
// visited directly.
export const prerender = false;
const title = Astro.url.searchParams.get('title') || 'gabeefranco';
const description = Astro.url.searchParams.get('description');
---
<html>
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=JetBrains+Mono:wght@600&display=swap"
rel="stylesheet"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
position: relative;
width: 1200px;
height: 630px;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 72px;
padding-bottom: 96px;
font-family: 'Inter', system-ui, sans-serif;
background: #fbf9f6;
color: #201a14;
border-bottom: 16px solid #e8590c;
}
.brand {
position: absolute;
top: 60px;
left: 24px;
display: flex;
align-items: center;
gap: 16px;
font-family: 'JetBrains Mono', monospace;
font-size: 40px;
font-weight: 600;
}
.brand img {
height: 64px;
}
.title {
font-size: 64px;
margin-left: 24px;
font-weight: 700;
line-height: 1.1;
letter-spacing: -0.02em;
margin-bottom: 24px;
}
.description {
font-size: 28px;
line-height: 1.35;
color: #6b5f52;
margin-left: 24px;
}
</style>
</head>
<body>
<div class="brand">
<img src="/logo.png" alt="" />
<span>gabeefranco</span>
</div>
<h1 class="title">{title}</h1>
{description && <p class="description">{description}</p>}
</body>
</html>

View file

@ -1,4 +1,5 @@
---
import { existsSync } from 'node:fs';
import { render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import PostLayout from '../../layouts/PostLayout.astro';
@ -13,9 +14,12 @@ export async function getStaticPaths() {
const { post } = Astro.props;
const { Content } = await render(post);
const readingMinutes = estimateReadingMinutes(post.body ?? '');
// Generated by scripts/generate-social-cards.ts; falls back to the logo until it exists.
const socialCard = `/social-cards/${post.id}.png`;
const ogImage = existsSync(`public${socialCard}`) ? socialCard : undefined;
---
<BaseLayout title={`${post.data.title} — gabeefranco`} description={post.data.description} lang="en" image={`/social-cards/${post.id}.png`}>
<BaseLayout title={`${post.data.title} — gabeefranco`} description={post.data.description} lang="en" image={ogImage}>
<PostLayout post={post} lang="en" readingMinutes={readingMinutes}>
<Content components={{ ObservationCard }} />
</PostLayout>

View file

@ -2,12 +2,10 @@
import BaseLayout from '../../layouts/BaseLayout.astro';
import PostsContent from '../../components/PostsContent.astro';
import { useTranslations } from '../../lib/i18n';
import { PAGES, pageCardPath } from '../../lib/pages';
const t = useTranslations('en');
const page = PAGES.en.posts;
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="en" image={pageCardPath('en', 'posts')}>
<BaseLayout title={`${t('posts.title')} — ${t('site.name')}`} description={t('posts.subtitle')} lang="en">
<PostsContent lang="en" />
</BaseLayout>

View file

@ -1,13 +1,13 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import { useTranslations } from '../../lib/i18n';
import { PAGES, pageCardPath } from '../../lib/pages';
const t = useTranslations('pt');
const page = PAGES.pt.about;
const description =
'Gabriel Franco (gabeefranco): estudante de ciência da computação na PUCRS, interessado em como o software realmente funciona e na história do movimento open source.';
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="pt" image={pageCardPath('pt', 'about')}>
<BaseLayout title={`${t('about.title')} — ${t('site.name')}`} description={description} lang="pt">
<section class="mx-10 mt-10 font-mono">
<h1 class="text-3xl font-bold tracking-tight text-text sm:text-4xl">{t('about.title')}</h1>

View file

@ -2,17 +2,10 @@
import BaseLayout from '../../layouts/BaseLayout.astro';
import HomeContent from '../../components/HomeContent.astro';
import { useTranslations } from '../../lib/i18n';
import { PAGES, pageCardPath } from '../../lib/pages';
const t = useTranslations('pt');
const page = PAGES.pt.home;
---
<BaseLayout
title={`${t('site.name')} — ${t('hero.kicker')}`}
description={page.description}
lang="pt"
image={pageCardPath('pt', 'home')}
>
<BaseLayout title={`${t('site.name')} — ${t('hero.kicker')}`} description={t('hero.subtitle')} lang="pt">
<HomeContent lang="pt" />
</BaseLayout>

View file

@ -1,4 +1,5 @@
---
import { existsSync } from 'node:fs';
import { render } from 'astro:content';
import BaseLayout from '../../../layouts/BaseLayout.astro';
import PostLayout from '../../../layouts/PostLayout.astro';
@ -13,9 +14,12 @@ export async function getStaticPaths() {
const { post } = Astro.props;
const { Content } = await render(post);
const readingMinutes = estimateReadingMinutes(post.body ?? '');
// Generated by scripts/generate-social-cards.ts; falls back to the logo until it exists.
const socialCard = `/social-cards/${post.id}.png`;
const ogImage = existsSync(`public${socialCard}`) ? socialCard : undefined;
---
<BaseLayout title={`${post.data.title} — gabeefranco`} description={post.data.description} lang="pt" image={`/social-cards/${post.id}.png`}>
<BaseLayout title={`${post.data.title} — gabeefranco`} description={post.data.description} lang="pt" image={ogImage}>
<PostLayout post={post} lang="pt" readingMinutes={readingMinutes}>
<Content components={{ ObservationCard }} />
</PostLayout>

View file

@ -2,12 +2,10 @@
import BaseLayout from '../../../layouts/BaseLayout.astro';
import PostsContent from '../../../components/PostsContent.astro';
import { useTranslations } from '../../../lib/i18n';
import { PAGES, pageCardPath } from '../../../lib/pages';
const t = useTranslations('pt');
const page = PAGES.pt.posts;
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="pt" image={pageCardPath('pt', 'posts')}>
<BaseLayout title={`${t('posts.title')} — ${t('site.name')}`} description={t('posts.subtitle')} lang="pt">
<PostsContent lang="pt" />
</BaseLayout>

View file

@ -1,9 +1,8 @@
---
import BaseLayout from '../../../../layouts/BaseLayout.astro';
import PostsContent from '../../../../components/PostsContent.astro';
import { getAllTags } from '../../../../lib/posts';
import { getAllTags, getPostsByLang } from '../../../../lib/posts';
import { useTranslations } from '../../../../lib/i18n';
import { tagPage, tagCardPath } from '../../../../lib/pages';
export async function getStaticPaths() {
const tags = await getAllTags('pt');
@ -12,9 +11,13 @@ export async function getStaticPaths() {
const { tag } = Astro.params;
const t = useTranslations('pt');
const page = tagPage('pt', tag!);
const posts = (await getPostsByLang('pt')).filter((p) => p.data.tags.includes(tag!));
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="pt" image={tagCardPath('pt', tag!)}>
<BaseLayout
title={`#${tag} — ${t('site.name')}`}
description={`${t('posts.filteredBy')} #${tag}: ${posts.map((p) => p.data.title).join(', ')}`}
lang="pt"
>
<PostsContent lang="pt" tag={tag} />
</BaseLayout>

View file

@ -1,9 +1,8 @@
---
import BaseLayout from '../../../layouts/BaseLayout.astro';
import PostsContent from '../../../components/PostsContent.astro';
import { getAllTags } from '../../../lib/posts';
import { getAllTags, getPostsByLang } from '../../../lib/posts';
import { useTranslations } from '../../../lib/i18n';
import { tagPage, tagCardPath } from '../../../lib/pages';
export async function getStaticPaths() {
const tags = await getAllTags('en');
@ -12,9 +11,13 @@ export async function getStaticPaths() {
const { tag } = Astro.params;
const t = useTranslations('en');
const page = tagPage('en', tag!);
const posts = (await getPostsByLang('en')).filter((p) => p.data.tags.includes(tag!));
---
<BaseLayout title={`${page.title} — ${t('site.name')}`} description={page.description} lang="en" image={tagCardPath('en', tag!)}>
<BaseLayout
title={`#${tag} — ${t('site.name')}`}
description={`${t('posts.filteredBy')} #${tag}: ${posts.map((p) => p.data.title).join(', ')}`}
lang="en"
>
<PostsContent lang="en" tag={tag} />
</BaseLayout>