Skip to content

Commit 5020b4a

Browse files
fix: simplified component logic and removed external scraping requests (#1784)
Co-authored-by: Salma Alam-Naylor <52798353+whitep4nth3r@users.noreply.github.com>
1 parent 364e3ed commit 5020b4a

6 files changed

Lines changed: 45 additions & 181 deletions

File tree

app/components/BlogPostFederatedArticles.vue

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
<script setup lang="ts">
22
import type { FederatedArticleInput } from '#shared/types/blog-post'
3+
import type { Author } from '#shared/schemas/blog'
34
45
const props = defineProps<{
56
headline: string
67
articles: FederatedArticleInput[]
78
}>()
89
9-
const contentKey = computed(() => props.articles.map(a => a.url).join('-'))
10-
11-
const { data: federatedArticles, status } = await useAsyncData(
12-
`federated-articles-${contentKey.value}`,
13-
() => useFederatedArticles(props.articles),
14-
{
15-
watch: [() => props.articles],
16-
default: () => [],
17-
},
10+
// Prepare authors list for the composable
11+
const authors = computed<Author[]>(() =>
12+
props.articles.map(article => ({
13+
name: article.authorHandle,
14+
blueskyHandle: article.authorHandle,
15+
})),
1816
)
17+
18+
// Fetch author profiles for avatars
19+
const { resolvedAuthors } = useBlueskyAuthorProfiles(authors.value)
20+
21+
// Merge the input data with the fetched avatars
22+
const federatedArticles = computed(() => {
23+
return props.articles.map((article, index) => {
24+
const profile = resolvedAuthors.value[index]
25+
26+
return {
27+
url: article.url,
28+
title: article.title,
29+
description: article.description,
30+
authorHandle: article.authorHandle,
31+
author: {
32+
name: profile?.name || article.authorHandle,
33+
blueskyHandle: article.authorHandle,
34+
avatar: profile?.avatar || null,
35+
profileUrl: profile?.profileUrl || null,
36+
},
37+
}
38+
})
39+
})
1940
</script>
2041

2142
<template>
@@ -24,7 +45,7 @@ const { data: federatedArticles, status } = await useAsyncData(
2445
{{ headline }}
2546
</h2>
2647
<section
27-
v-if="federatedArticles?.length"
48+
v-if="federatedArticles.length"
2849
class="grid gap-4 grid-cols-[repeat(auto-fit,minmax(14rem,1fr))] transition-[grid-template-cols]"
2950
>
3051
<a
@@ -35,12 +56,7 @@ const { data: federatedArticles, status } = await useAsyncData(
3556
:key="article.url"
3657
class="grid grid-cols-[auto_1fr] gap-x-5 no-underline hover:no-underline rounded-lg border border-border p-4 transition-shadow hover:shadow-lg hover:shadow-gray-500/50"
3758
>
38-
<AuthorAvatar
39-
v-if="article?.author"
40-
:author="article.author"
41-
size="md"
42-
class="row-span-2"
43-
/>
59+
<AuthorAvatar v-if="article.author" :author="article.author" size="md" class="row-span-2" />
4460
<div class="flex flex-col">
4561
<p class="text-lg text-fg leading-tight m-0">
4662
{{ article.title }}

app/composables/useFederatedArticles.ts

Lines changed: 0 additions & 67 deletions
This file was deleted.

app/pages/blog/alpha-release.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extension, everyone who works in the JavaScript ecosystem."
1313
date: "2026-03-03"
1414
slug: "alpha-release"
1515
description: "npmx is an open-source project built by a rapidly growing community. It's for open-source developers, and by extension, everyone who works in the JavaScript ecosystem."
16-
draft: false
16+
draft: true
1717
---
1818

1919
# Announcing npmx: a fast, modern browser for the npm registry
@@ -118,46 +118,55 @@ headline="Read more from the community"
118118
:articles="[
119119
{
120120
url: 'https://whitep4nth3r.com/blog/how-to-make-your-first-open-source-contribution/',
121+
title: 'How to Make Your First Open Source Contribution',
121122
authorHandle: 'whitep4nth3r.com',
122123
description: 'Getting involved in open source doesn\'t have to be scary! Understand how to find a great project and make your first contribution in this guide from Salma.'
123124
},
124125
{
125126
url: 'https://graphieros.github.io/graphieros-blog/blog/2026/npmx.html',
127+
title: 'vue-data-ui is on npmx npmx is on vue-data-ui',
126128
authorHandle: 'graphieros.com',
127129
description: 'Graphieros explores a minimal npm-based workflow and why it exists.'
128130
},
129131
{
130132
url: 'https://www.alexdln.com/blog/npmx-the-month',
133+
title: 'The month. npmx',
131134
authorHandle: 'alexdln.com',
132135
description: 'Alex reflects on the project, warm stories, wonderful people, and a look into the future'
133136
},
134137
{
135138
url: 'https://johnnyreilly.com/npmx-with-a-little-help-from-my-friends',
139+
title: 'npmx: With a Little Help From My Friends',
136140
authorHandle: 'johnnyreilly.com',
137141
description: 'How to contribute to npmx.dev, and thoughts on Johnny\'s experience with the project.'
138142
},
139143
{
140144
url: 'https://blog.trueberryless.org/blog/npmx/',
145+
title: 'Rising community at tomorrow's horizon',
141146
authorHandle: 'trueberryless.org',
142147
description: 'Telling the story of a newly founded community.'
143148
},
144149
{
145150
url: 'https://www.sybers.fr/blog/3mfhn5xoawz24',
151+
title: 'From a Bluesky post to my favorite open source community',
146152
authorHandle: 'sybers.fr',
147153
description: 'The best open source projects aren\'t just about great code. They\'re about the people behind them.'
148154
},
149155
{
150156
url: 'https://storybook.js.org/blog/storybook-npmx',
157+
title: 'The npm browsing experience we always wanted',
151158
authorHandle: 'storybook.js.org',
152159
description: 'We\'re huge fans of what the npmx community is building. Today\'s alpha is just the starting line, and we\'re proud to be running alongside them.'
153160
},
154161
{
155162
url: 'https://jensroemer.com/writing/open-source-whats-in-it-for-me/',
163+
title: 'Open source, what\'s in it for me?',
156164
authorHandle: 'jensroemer.com',
157165
description: 'Reflections on learning, community, and change.'
158166
},
159167
{
160168
url: 'https://paulie.codes/blog/3mfs2stugzp2v',
169+
title: 'Overcoming Imposter Syndrome: My First Open Source Contribution',
161170
authorHandle: 'paulie.codes',
162171
description: 'The most important part of open source is the people, and everyone has something valuable to bring to the table.'
163172
}

nuxt.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export default defineNuxtConfig({
157157
'/settings': { prerender: true },
158158
'/recharging': { prerender: true },
159159
// proxy for insights
160-
'/blog/**': { isr: true, prerender: true },
160+
'/blog/**': { prerender: true },
161161
'/_v/script.js': {
162162
proxy: 'https://npmx.dev/_vercel/insights/script.js',
163163
},

server/api/atproto/blog-meta.get.ts

Lines changed: 0 additions & 87 deletions
This file was deleted.

shared/types/blog-post.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import type * as app from '#shared/types/lexicons/app'
2-
import type { BlogMetaResponse } from '#shared/schemas/atproto'
3-
import type { ResolvedAuthor } from '#shared/schemas/blog'
42

53
export type CommentEmbed =
64
| { type: 'images'; images: app.bsky.embed.images.ViewImage[] }
@@ -24,16 +22,11 @@ export interface Comment {
2422
WARN: FederatedArticleInput specifics
2523
interface - All strings must be captured in single quotes in order to be parsed correctly in the MD file
2624
authorHandle - Must not contain `@` symbol prefix
27-
description - Passing an empty string `''` will fallback to the description provided by the scraped meta tags
2825
description - Any additional single quotes must be properly escaped with a `\`
2926
*/
3027
export interface FederatedArticleInput {
3128
url: string
29+
title: string
3230
authorHandle: string
33-
description?: string
34-
}
35-
36-
export type ResolvedFederatedArticle = Omit<BlogMetaResponse, 'author' | '_meta'> & {
37-
url: string
38-
author: ResolvedAuthor
31+
description: string
3932
}

0 commit comments

Comments
 (0)