chore: minor post update and script changes 02253b5d
Steve · 2026-01-12 06:39 2 file(s) · +70 −19
packages/client/scripts/publish-to-atproto.ts +69 −18
86 86
		.replace(/\s+/g, "-");
87 87
}
88 88
89 -
async function getRecentPosts(limit: number = 5): Promise<BlogPost[]> {
89 +
async function getRecentPosts(limit: number = 1): Promise<BlogPost[]> {
90 90
	const files = fs.readdirSync(CONTENT_DIR);
91 91
	const posts: BlogPost[] = [];
92 92
184 184
	return response.data.uri;
185 185
}
186 186
187 +
async function updateAtProtoDocument(
188 +
	agent: AtpAgent,
189 +
	post: BlogPost,
190 +
	atUri: string,
191 +
): Promise<void> {
192 +
	// Parse the atUri to get the repo, collection, and rkey
193 +
	// Format: at://did:plc:xxx/collection/rkey
194 +
	const uriMatch = atUri.match(/^at:\/\/([^/]+)\/([^/]+)\/(.+)$/);
195 +
	if (!uriMatch) {
196 +
		throw new Error(`Invalid atUri format: ${atUri}`);
197 +
	}
198 +
199 +
	const [, repo, collection, rkey] = uriMatch;
200 +
201 +
	const postPath = `/posts/${post.slug}`;
202 +
	const markdownContent = {
203 +
		$type: "site.standard.content.markdown",
204 +
		markdown: post.content.trim(),
205 +
	};
206 +
207 +
	const textContent = stripMarkdownForText(post.content);
208 +
209 +
	// Parse the publish date
210 +
	const publishDate = new Date(post.frontmatter.publishDate);
211 +
212 +
	const record = {
213 +
		$type: "site.standard.document",
214 +
		title: post.frontmatter.title,
215 +
		site: PUBLICATION_URI,
216 +
		path: postPath,
217 +
		content: markdownContent,
218 +
		textContent: textContent.slice(0, 10000), // Limit text content length
219 +
		publishedAt: publishDate.toISOString(),
220 +
		canonicalUrl: `${SITE_URL}${postPath}`,
221 +
		location: "main-blog",
222 +
	};
223 +
224 +
	await agent.com.atproto.repo.putRecord({
225 +
		repo: agent.session!.did,
226 +
		collection,
227 +
		rkey,
228 +
		record,
229 +
	});
230 +
}
231 +
187 232
async function main() {
188 233
	// Check for required environment variables
189 234
	const identifier = process.env.ATP_IDENTIFIER;
214 259
	}
215 260
216 261
	console.log("\nFetching recent posts...");
217 -
	const posts = await getRecentPosts(5);
262 +
	const posts = await getRecentPosts(1);
218 263
219 264
	console.log(`Found ${posts.length} recent posts\n`);
220 265
221 266
	let publishedCount = 0;
267 +
	let updatedCount = 0;
222 268
	let skippedCount = 0;
223 269
224 270
	for (const post of posts) {
225 271
		console.log(`Processing: ${post.frontmatter.title}`);
226 272
227 -
		if (post.frontmatter.atUri) {
228 -
			console.log(`  - Already has atUri, skipping\n`);
229 -
			skippedCount++;
230 -
			continue;
231 -
		}
232 -
233 273
		if (post.frontmatter.hidden) {
234 274
			console.log(`  - Post is hidden, skipping\n`);
235 275
			skippedCount++;
237 277
		}
238 278
239 279
		try {
240 -
			console.log(`  - Creating ATProto document...`);
241 -
			const atUri = await createAtProtoDocument(agent, post);
242 -
			console.log(`  - Created: ${atUri}`);
280 +
			if (post.frontmatter.atUri) {
281 +
				console.log(`  - Found existing atUri, updating document...`);
282 +
				await updateAtProtoDocument(agent, post, post.frontmatter.atUri);
283 +
				console.log(`  - Updated: ${post.frontmatter.atUri}\n`);
284 +
				updatedCount++;
285 +
			} else {
286 +
				console.log(`  - Creating ATProto document...`);
287 +
				const atUri = await createAtProtoDocument(agent, post);
288 +
				console.log(`  - Created: ${atUri}`);
243 289
244 -
			// Update the file with the new atUri
245 -
			const updatedContent = updateFrontmatterWithAtUri(post.rawContent, atUri);
246 -
			fs.writeFileSync(post.filePath, updatedContent);
247 -
			console.log(
248 -
				`  - Updated frontmatter in ${path.basename(post.filePath)}\n`,
249 -
			);
290 +
				// Update the file with the new atUri
291 +
				const updatedContent = updateFrontmatterWithAtUri(
292 +
					post.rawContent,
293 +
					atUri,
294 +
				);
295 +
				fs.writeFileSync(post.filePath, updatedContent);
296 +
				console.log(
297 +
					`  - Updated frontmatter in ${path.basename(post.filePath)}\n`,
298 +
				);
250 299
251 -
			publishedCount++;
300 +
				publishedCount++;
301 +
			}
252 302
		} catch (error) {
253 303
			console.error(`  - Error publishing: ${error}\n`);
254 304
		}
256 306
257 307
	console.log("---");
258 308
	console.log(`Published: ${publishedCount}`);
309 +
	console.log(`Updated: ${updatedCount}`);
259 310
	console.log(`Skipped: ${skippedCount}`);
260 311
}
261 312
packages/client/src/content/post/standard-site-the-publishing-gateway.mdx +1 −1
104 104
105 105
I also plan to include a link to this post as an update on my [/now](/now) page if you want to check out the implementation and leave a comment! While my main blog doesn't have comments I did write a script that will now create documents on ATProto so they should be indexed as well.
106 106
107 -
Wrapping up, this experience has been a great culmination of everything I've been prioritizing with the web, that being content publishing and sharing that content through open channels like RSS. Standard.site opens up a whole new world of possibilities for that this could look like in the near future, and takes us a step closer to a truly open web that I long to see.
107 +
Wrapping up, this experience has been a great culmination of everything I've been prioritizing with the web, that being content publishing and sharing that content through open channels like RSS. Standard.site opens up a whole new world of possibilities for what this could look like in the near future, and takes us a step closer to a truly open web that I long to see.