From 9d345915042670421118b72517b1815cb686f92f Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Tue, 3 Mar 2026 12:14:56 -0600 Subject: [PATCH 1/3] feat: add post for migration, but add more details --- .../index.md | 55 +++++++++++++++++++ src/data/redirects.json | 3 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 content/posts/the-python-insider-blog-has-moved/index.md diff --git a/content/posts/the-python-insider-blog-has-moved/index.md b/content/posts/the-python-insider-blog-has-moved/index.md new file mode 100644 index 0000000..928961e --- /dev/null +++ b/content/posts/the-python-insider-blog-has-moved/index.md @@ -0,0 +1,55 @@ +--- +title: The Python Insider Blog Has Moved! +publishDate: '2026-03-03' +updatedDate: '2026-03-03' +author: Jacob Coffee +description: 'Python Insider now lives at blog.python.org, backed by a Git repository. All 307 posts from the Blogger era have been migrated, and old URLs redirect automatically.' +tags: + - python + - community +published: true +legacyUrl: /2026/03/the-python-insider-blog-has-moved.html +--- + +Python Insider now lives at [blog.python.org](https://blog.python.org), backed by a Git repository. All 307 posts from the Blogger era have been migrated over, and old URLs redirect to the new ones automatically. Your RSS readers should pick up the new feed without any action on your part, but if something looks off, the new feed URL is [blog.python.org/rss.xml](https://blog.python.org/rss.xml). + +## Why we moved + +Blogger worked fine for a long time, but contributing to the blog meant having a Google account and using Blogger's editor. That's a higher bar than it needs to be. The new setup is just Markdown files in a Git repo. If you can open a pull request, you can write a post. + +Posts live in `content/posts/{slug}/index.md` with YAML frontmatter for the title, date, authors, and tags. Images go right next to the post in the same directory. No special tooling required beyond a text editor. + +## Contributing + +Want to write about a Python release, core sprint, governance update, or anything else that belongs on the official Python blog? Here's the short version: + +1. Fork [python/python-insider-blog](https://github.com/python/python-insider-blog) +2. Create a new directory under `content/posts/` with your post slug +3. Add an `index.md` with your content (and optionally upload your images) +4. Open a PR + +The repo README has more detail on frontmatter fields and local development if you want to preview your post before submitting. + +## What's new on the site + +Beyond the content itself, the new site has a few features the old Blogger setup never had: + +- **[Browse all posts](/blog/)** with pagination and a tag sidebar for filtering by topic. You can also filter by [year](/blog/year/2025) to find posts from a specific period. +- **[Authors page](/authors/)** listing every contributor and how many posts they've written. Each author has their own page showing all of their posts. +- **[Tags page](/tags/)** with every tag and its post count, so you can quickly find all release announcements, security updates, or community posts. +- **Search** via the command palette — hit `Ctrl+K` (or `Cmd+K` on Mac) from any page to search across all 307+ posts instantly. +- **RSS feed** at [blog.python.org/rss.xml](https://blog.python.org/rss.xml), compatible with the old Blogger feed URL so existing subscribers don't need to change anything. +- **Dark mode** that follows your system preference. +- **Open Graph images** generated automatically for every post, so links shared on social media get proper preview cards. + +## What's under the hood + +The site is built with [Astro](https://astro.build) and deployed as fully static HTML. There's a [Keystatic](https://keystatic.com) CMS available in dev mode if you prefer a visual editor over raw Markdown, but it's entirely optional. Tailwind handles the styling. The whole thing builds and deploys through GitHub Actions. + +## Links + +- New site: [blog.python.org](https://blog.python.org) +- Repository: [github.com/python/python-insider-blog](https://github.com/python/python-insider-blog) +- RSS feed: [blog.python.org/rss.xml](https://blog.python.org/rss.xml) + +If you spot broken links, missing images, or formatting issues from the migration, [file an issue](https://github.com/python/python-insider-blog/issues) on the repo. PRs are welcome too. diff --git a/src/data/redirects.json b/src/data/redirects.json index 7076008..2a9c6cc 100644 --- a/src/data/redirects.json +++ b/src/data/redirects.json @@ -303,5 +303,6 @@ "/2020/07/upgrade-pip-20-2-changes-20-3.html": "/2020/07/upgrade-pip-20-2-changes-20-3", "/2011/04/urllib-security-vulnerability-fixed.html": "/2011/04/urllib-security-vulnerability-fixed", "/2019/05/use-two-factor-auth-to-improve-your.html": "/2019/05/use-two-factor-auth-to-improve-your", - "/2011/03/welcome-to-python-insider.html": "/2011/03/welcome-to-python-insider" + "/2011/03/welcome-to-python-insider.html": "/2011/03/welcome-to-python-insider", + "/2026/03/the-python-insider-blog-has-moved.html": "/2026/03/the-python-insider-blog-has-moved" } From af930337f89dbfeaed6715e297059b92dad81d98 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Tue, 3 Mar 2026 12:21:07 -0600 Subject: [PATCH 2/3] ui: make the showcase post more fancy, add author --- content/authors/jacob-coffee.json | 11 ++ .../{index.md => index.mdx} | 39 +++++-- src/components/showcase/ShowcaseAuthors.astro | 80 ++++++++++++++ .../showcase/ShowcasePostCards.astro | 100 ++++++++++++++++++ src/components/showcase/ShowcaseSearch.astro | 96 +++++++++++++++++ .../showcase/ShowcaseTagCloud.astro | 58 ++++++++++ 6 files changed, 378 insertions(+), 6 deletions(-) create mode 100644 content/authors/jacob-coffee.json rename content/posts/the-python-insider-blog-has-moved/{index.md => index.mdx} (70%) create mode 100644 src/components/showcase/ShowcaseAuthors.astro create mode 100644 src/components/showcase/ShowcasePostCards.astro create mode 100644 src/components/showcase/ShowcaseSearch.astro create mode 100644 src/components/showcase/ShowcaseTagCloud.astro diff --git a/content/authors/jacob-coffee.json b/content/authors/jacob-coffee.json new file mode 100644 index 0000000..ebcf9c9 --- /dev/null +++ b/content/authors/jacob-coffee.json @@ -0,0 +1,11 @@ +{ + "name": "Jacob Coffee", + "bio": "PSF Infradwre team. Litestar core developer.", + "github": "JacobCoffee", + "avatar": "https://avatars.githubusercontent.com/u/45884264", + "twitter": "_scriptr", + "bluesky": "scriptr.dev", + "mastodon": "https://fosstodon.org/@Monorepo", + "website": "https://scriptr.dev", + "featured": false +} diff --git a/content/posts/the-python-insider-blog-has-moved/index.md b/content/posts/the-python-insider-blog-has-moved/index.mdx similarity index 70% rename from content/posts/the-python-insider-blog-has-moved/index.md rename to content/posts/the-python-insider-blog-has-moved/index.mdx index 928961e..05fb2d2 100644 --- a/content/posts/the-python-insider-blog-has-moved/index.md +++ b/content/posts/the-python-insider-blog-has-moved/index.mdx @@ -11,6 +11,11 @@ published: true legacyUrl: /2026/03/the-python-insider-blog-has-moved.html --- +import ShowcasePostCards from '../../../src/components/showcase/ShowcasePostCards.astro'; +import ShowcaseTagCloud from '../../../src/components/showcase/ShowcaseTagCloud.astro'; +import ShowcaseAuthors from '../../../src/components/showcase/ShowcaseAuthors.astro'; +import ShowcaseSearch from '../../../src/components/showcase/ShowcaseSearch.astro'; + Python Insider now lives at [blog.python.org](https://blog.python.org), backed by a Git repository. All 307 posts from the Blogger era have been migrated over, and old URLs redirect to the new ones automatically. Your RSS readers should pick up the new feed without any action on your part, but if something looks off, the new feed URL is [blog.python.org/rss.xml](https://blog.python.org/rss.xml). ## Why we moved @@ -32,14 +37,36 @@ The repo README has more detail on frontmatter fields and local development if y ## What's new on the site -Beyond the content itself, the new site has a few features the old Blogger setup never had: +Beyond the content itself, the new site has a few features the old Blogger setup never had. Here's a live look: + +### Browse & filter posts + +All posts are browsable with pagination, a year filter, and a tag sidebar. Click any tag or year to narrow things down. + + + +### Every author has a page + +See who's been writing, how much they've contributed, and browse their posts individually. + + + +### Tags at a glance + +Every tag across the archive, ranked by how often it appears. Great for finding all the release announcements or security updates in one place. + + + +### Search everything + +Hit Ctrl+K (or Cmd+K on Mac) from any page to open the command palette. It searches across all 307+ posts by title, author, tags, and description. There are also keyboard chord shortcuts for quick navigation. + + + +### And more -- **[Browse all posts](/blog/)** with pagination and a tag sidebar for filtering by topic. You can also filter by [year](/blog/year/2025) to find posts from a specific period. -- **[Authors page](/authors/)** listing every contributor and how many posts they've written. Each author has their own page showing all of their posts. -- **[Tags page](/tags/)** with every tag and its post count, so you can quickly find all release announcements, security updates, or community posts. -- **Search** via the command palette — hit `Ctrl+K` (or `Cmd+K` on Mac) from any page to search across all 307+ posts instantly. - **RSS feed** at [blog.python.org/rss.xml](https://blog.python.org/rss.xml), compatible with the old Blogger feed URL so existing subscribers don't need to change anything. -- **Dark mode** that follows your system preference. +- **Dark mode** that follows your system preference (try the toggle in the header). - **Open Graph images** generated automatically for every post, so links shared on social media get proper preview cards. ## What's under the hood diff --git a/src/components/showcase/ShowcaseAuthors.astro b/src/components/showcase/ShowcaseAuthors.astro new file mode 100644 index 0000000..ff71443 --- /dev/null +++ b/src/components/showcase/ShowcaseAuthors.astro @@ -0,0 +1,80 @@ +--- +import { getCollection } from "astro:content"; +import { slugify, withBase } from "../../lib/utils"; + +const allPosts = await getCollection("posts"); +const publishedPosts = allPosts.filter((p) => p.data.published); +const allAuthors = await getCollection("authors"); + +const authorCounts = new Map(); +for (const post of publishedPosts) { + const slug = slugify(post.data.author); + authorCounts.set(slug, (authorCounts.get(slug) || 0) + 1); +} + +const authorsWithCounts = allAuthors + .map((a) => ({ + slug: a.id, + name: a.data.name, + github: a.data.github, + count: authorCounts.get(a.id) || 0, + })) + .filter((a) => a.count > 0) + .sort((a, b) => b.count - a.count); + +const topAuthors = authorsWithCounts.slice(0, 6); +const maxCount = topAuthors[0]?.count ?? 1; +--- + +
+
+
+ + + + + + Authors + {authorsWithCounts.length} contributors +
+ + View all → + +
+
+ {topAuthors.map((author) => { + const pct = Math.round((author.count / maxCount) * 100); + return ( + + {author.github ? ( + + ) : ( +
+ {author.name.charAt(0)} +
+ )} + + {author.name} + +
+
diff --git a/src/components/showcase/ShowcasePostCards.astro b/src/components/showcase/ShowcasePostCards.astro new file mode 100644 index 0000000..e4b1d04 --- /dev/null +++ b/src/components/showcase/ShowcasePostCards.astro @@ -0,0 +1,100 @@ +--- +import { getCollection } from "astro:content"; +import { formatDate, postUrl, slugify, withBase } from "../../lib/utils"; + +const allPosts = await getCollection("posts"); +const recentPosts = allPosts + .filter((p) => p.data.published) + .sort((a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime()) + .slice(0, 3); + +// Collect years from all posts for the mini sidebar +const yearSet = new Set(); +for (const post of allPosts.filter((p) => p.data.published)) { + yearSet.add(post.data.publishDate.getFullYear()); +} +const years = [...yearSet].sort((a, b) => b - a).slice(0, 8); + +// Top tags for the mini sidebar +const tagCounts = new Map(); +for (const post of allPosts.filter((p) => p.data.published)) { + for (const tag of post.data.tags) { + tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1); + } +} +const topTags = [...tagCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10); +--- + +
+
+
+ + + + + Blog + {allPosts.filter((p) => p.data.published).length} posts with filters & pagination +
+ + Browse all → + +
+ + +
diff --git a/src/components/showcase/ShowcaseSearch.astro b/src/components/showcase/ShowcaseSearch.astro new file mode 100644 index 0000000..a362c2f --- /dev/null +++ b/src/components/showcase/ShowcaseSearch.astro @@ -0,0 +1,96 @@ +--- +// Static mockup of the command palette — not interactive, just a visual preview +--- + +
+
+
+ + + + + Command Palette +
+ + Press + ⌘K + to try it + +
+ + +
+ +
+
+ + + + +
+
+ Search posts, tags, authors... +
+
+ + +
+
Go to
+ +
+ + + + + Go to Home + + G + then + H + +
+ +
+ + + + + Go to Blog + + G + then + B + +
+ +
+ + + + + Go to Tags + + G + then + T + +
+
+ + +
+ + ↑↓ + Navigate + + + + Open + + + Esc + Close + +
+
+
diff --git a/src/components/showcase/ShowcaseTagCloud.astro b/src/components/showcase/ShowcaseTagCloud.astro new file mode 100644 index 0000000..014725c --- /dev/null +++ b/src/components/showcase/ShowcaseTagCloud.astro @@ -0,0 +1,58 @@ +--- +import { getCollection } from "astro:content"; +import { withBase } from "../../lib/utils"; + +const allPosts = await getCollection("posts"); +const publishedPosts = allPosts.filter((p) => p.data.published); + +const tagCounts = new Map(); +for (const post of publishedPosts) { + for (const tag of post.data.tags) { + tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1); + } +} +const topTags = [...tagCounts.entries()] + .sort((a, b) => b[1] - a[1]) + .slice(0, 8); +const maxCount = topTags[0]?.[1] ?? 1; +--- + +
+
+
+ + + + + Tags + {tagCounts.size} total +
+ + View all → + +
+
+ {topTags.map(([tag, count]) => { + const pct = Math.round((count / maxCount) * 100); + return ( + + + {tag} + + +
From 9634604fca13212b0558a2657f73f2e1d512dc98 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Tue, 3 Mar 2026 12:41:29 -0600 Subject: [PATCH 3/3] Update content/authors/jacob-coffee.json --- content/authors/jacob-coffee.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/authors/jacob-coffee.json b/content/authors/jacob-coffee.json index ebcf9c9..fdce75b 100644 --- a/content/authors/jacob-coffee.json +++ b/content/authors/jacob-coffee.json @@ -1,6 +1,6 @@ { "name": "Jacob Coffee", - "bio": "PSF Infradwre team. Litestar core developer.", + "bio": "Python Software Foundation Staff. Litestar Maintainer.", "github": "JacobCoffee", "avatar": "https://avatars.githubusercontent.com/u/45884264", "twitter": "_scriptr",