Search results

๐Ÿ• 2026-03-11 06:00 UTC

๐Ÿ“ฐ ใƒ‡ใƒใƒƒใ‚ฐใฏใ‚‚ใ†ไบบ้–“ใฎไป•ไบ‹ใงใฏใชใใชใฃใŸ (๐Ÿ‘ 93)

๐Ÿ‡ฌ๐Ÿ‡ง AI agents now handle most debugging by accessing production DBs, logs & Sentry directly. Multiple agents test hypotheses in parallel with peer review.
๐Ÿ‡ฐ๐Ÿ‡ท AI ์—์ด์ „ํŠธ๊ฐ€ ํ”„๋กœ๋•์…˜ DB, ๋กœ๊ทธ, Sentry์— ์ง์ ‘ ์ ‘๊ทผํ•ด ๋Œ€๋ถ€๋ถ„์˜ ๋””๋ฒ„๊น…์„ ์ฒ˜๋ฆฌ. ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ๊ฐ€ ๊ฐ€์„ค์„ ๋ณ‘๋ ฌ๋กœ ๊ฒ€์ฆํ•˜๊ณ  ๋ฆฌ๋ทฐ.

๐Ÿ”— zenn.dev/dinii/articles/debugg

๐Ÿ“ฐ Denoใ‹ใ‚‰Bunใซๅˆ‡ใ‚Šๆ›ฟใˆใŸใ‚‰ใ‚ทใƒณใ‚ฐใƒซใƒใ‚คใƒŠใƒชใŒ็ด„9ๅˆ†ใฎ1ใซใชใฃใŸ (๐Ÿ‘ 45)

๐Ÿ‡ฌ๐Ÿ‡ง Switching from Deno compile to Bun build --compile reduced single binary size by ~89%, making distribution much more efficient for OSS tools.
๐Ÿ‡ฐ๐Ÿ‡ท Deno์—์„œ Bun์œผ๋กœ ์ „ํ™˜ํ•˜๋‹ˆ ์‹ฑ๊ธ€ ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๊ธฐ๊ฐ€ ์•ฝ 89% ๊ฐ์†Œ. OSS ๋„๊ตฌ ๋ฐฐํฌ๊ฐ€ ํ›จ์”ฌ ํšจ์œจ์ ์œผ๋กœ ๊ฐœ์„ ๋จ.

๐Ÿ”— zenn.dev/dyoshikawa/articles/d

0

๐Ÿ• 2026-03-11 00:00 UTC

๐Ÿ“ฐ ใƒ‡ใƒใƒƒใ‚ฐใฏใ‚‚ใ†ไบบ้–“ใฎไป•ไบ‹ใงใฏใชใใชใฃใŸ (๐Ÿ‘ 71)

๐Ÿ‡ฌ๐Ÿ‡ง How AI agents now handle debugging by accessing production DBs, logs & Sentry directly, with parallel hypothesis testing and peer review
๐Ÿ‡ฐ๐Ÿ‡ท AI ์—์ด์ „ํŠธ๊ฐ€ ํ”„๋กœ๋•์…˜ DB, ๋กœ๊ทธ, Sentry์— ์ง์ ‘ ์ ‘๊ทผํ•ด ๋ณ‘๋ ฌ ๊ฐ€์„ค ๊ฒ€์ฆ๊ณผ ์ƒํ˜ธ ๋ฆฌ๋ทฐ๋กœ ๋””๋ฒ„๊น…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

๐Ÿ”— zenn.dev/dinii/articles/debugg

๐Ÿ“ฐ Denoใ‹ใ‚‰Bunใซๅˆ‡ใ‚Šๆ›ฟใˆใŸใ‚‰ใ‚ทใƒณใ‚ฐใƒซใƒใ‚คใƒŠใƒชใŒ็ด„9ๅˆ†ใฎ1ใซใชใฃใŸ (๐Ÿ‘ 36)

๐Ÿ‡ฌ๐Ÿ‡ง Switching from Deno compile to Bun build reduced single binary size by 9x for OSS tool Rulesync - exploring why the difference is so dramatic
๐Ÿ‡ฐ๐Ÿ‡ท Deno ์ปดํŒŒ์ผ์—์„œ Bun ๋นŒ๋“œ๋กœ ์ „ํ™˜ํ•ด ์‹ฑ๊ธ€ ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๊ธฐ๊ฐ€ 9๋ฐฐ ๊ฐ์†Œ - OSS ๋„๊ตฌ Rulesync์—์„œ ๊ทน์ ์ธ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ  ํƒ๊ตฌ

๐Ÿ”— zenn.dev/dyoshikawa/articles/d

0

Hongdown 0.2.0 is out! Hongdown is an opinionated formatter written in , and this release brings support, so you can now use it as a library in .js, , , and browsers.

New features:

  • Smart heading sentence case conversion with ~450 built-in proper nouns
  • SmartyPants-style typographic punctuation ("straight" โ†’ โ€œcurlyโ€)
  • External code formatter integration for code blocks
  • Directory argument support for batch formatting

Try it in the browser: https://dahlia.github.io/hongdown/

Release notes: https://github.com/dahlia/hongdown/discussions/10

1

Building CLI apps with TypeScript in 2026

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Building TypeScript command-line interfaces often involves moving beyond fragile manual argument parsing toward robust, type-safe solutions that align with the language's powerful type system. While traditional libraries provide basic structure, they often fall short when handling complex constraints like mutually exclusive options or nested subcommands, leading to runtime checks that the compiler cannot verify. Optique addresses these challenges by using functional parser composition to build CLI structures where types are inferred automatically. This approach allows for the creation of discriminated unions, ensuring that variables like server ports or client URLs are only accessible in their respective modes. Beyond basic parsing, the library handles validation for integers and specific string choices, generates context-aware shell completions for multiple environments, and integrates seamlessly with validation ecosystems like Zod and Valibot. This runtime-agnostic tool works across Node.js, Deno, and Bun, providing a consistent way to manage help text and error handling without the boilerplate of manual logic. By adopting a composable approach to parser construction, developers can ensure their command-line interfaces are not only user-friendly but also structurally sound and type-safe from the start.

Read more โ†’
1

Logging in Node.js (or Deno or Bun or edge functions) in 2026

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Effective logging is the difference between a quick fix and a 2 AM production nightmare, yet traditional JavaScript tools often swing between the fragile simplicity of console.log and the heavy overhead of complex frameworks. LogTape emerges as a zero-dependency alternative that works seamlessly across Node.js, Deno, Bun, and edge functions, addressing the inherent limitations of standard console methods by introducing hierarchical categories, sophisticated filtering, and structured logging. By utilizing sinks, developers can route logs to multiple destinationsโ€”such as rotating files, Sentry, or OpenTelemetryโ€”simultaneously while maintaining machine-readable JSON formats. One of its standout features is the support for implicit contexts via AsyncLocalStorage, which allows for seamless request tracing across asynchronous boundaries without the need for manual identifier passing. Furthermore, its library-first design ensures that package authors can include diagnostic logging without imposing unsolicited output or configuration burdens on their users. The system also accommodates production-critical needs like non-blocking I/O for high-performance environments and automated sensitive data redaction. Adopting this structured approach to logging provides the necessary visibility to debug complex systems efficiently while maintaining a lightweight and modern development workflow.

Read more โ†’
2

Sending emails in Node.js, Deno, and Bun in 2026: a practical guide

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Sending emails in JavaScript remains a fragmented task, particularly when navigating the diverse requirements of Node.js, Deno, Bun, and edge environments. This guide explores Upyo, a cross-runtime email library that addresses these challenges through a unified, type-safe API designed for zero dependencies and provider independence. The library simplifies the transition between traditional SMTP and modern providers like Resend, SendGrid, Mailgun, or Amazon SES, ensuring that application logic remains consistent regardless of the underlying transport. Key technical insights include implementing DKIM signatures to boost deliverability, managing resources efficiently with modern JavaScript cleanup patterns, and leveraging bulk-sending optimizations for large-scale notifications. Additionally, the content examines strategies for achieving high availability through provider failover pools and integrating observability with OpenTelemetry for production monitoring. Whether you are building on standard servers or restricted edge functions, Upyo provides the architectural flexibility needed to handle complex email workflows with minimal overhead. Adopting a standardized, runtime-agnostic library for email communication significantly reduces technical debt and ensures your application remains resilient across the modern web stack.

Read more โ†’
2

BotKit์€ ActivityPub ๋ด‡์„ ๋งŒ๋“œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ Mastodon/Misskey ๋ด‡๊ณผ ๋‹ค๋ฅธ ์ ์€, ๋ด‡ ์ž์ฒด๊ฐ€ ๋…๋ฆฝ๋œ ์„œ๋ฒ„๋กœ ๋Œ์•„๊ฐ„๋‹ค๋Š” ๊ฒ๋‹ˆ๋‹ค. ํ”Œ๋žซํผ ๊ณ„์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

๊ธ€์ž ์ˆ˜ ์ œํ•œ๋„ ์—†๊ณ , API ํ˜ธ์ถœ ์ œํ•œ์— ์‹œ๋‹ฌ๋ฆด ์ผ๋„ ์—†์Šต๋‹ˆ๋‹ค.

bot.onMention = async (session, message) => {
  await message.reply(text`์•ˆ๋…•ํ•˜์„ธ์š”, ${message.actor}๋‹˜!`);
};

์—ฐํ•ฉ(federation), HTTP Signatures, ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ๊ฐ™์€ ๊ด€๋ จ ์ฒ˜๋ฆฌ๋Š” Fedify๊ฐ€ ์•Œ์•„์„œ ํ•ด์ค๋‹ˆ๋‹ค. ๋ด‡ ๋กœ์ง๋งŒ ์งœ๋ฉด ๋˜๋Š” ๊ฑฐ์ฃ .

๋ฐ .js ๋‘˜ ๋‹ค ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

https://botkit.fedify.dev/

BotKitใฏใ€ActivityPubใƒœใƒƒใƒˆใ‚’ไฝœใ‚‹ใŸใ‚ใฎTypeScriptใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏใงใ™ใ€‚ๆ—ขๅญ˜ใฎMastodon/Misskeyใƒœใƒƒใƒˆใจใฎ้•ใ„ใฏใ€ใƒœใƒƒใƒˆ่‡ชไฝ“ใŒ็‹ฌ็ซ‹ใ—ใŸใ‚ตใƒผใƒใƒผใจใ—ใฆๅ‹•ไฝœใ™ใ‚‹ใ“ใจใ€‚ใƒ—ใƒฉใƒƒใƒˆใƒ•ใ‚ฉใƒผใƒ ใฎใ‚ขใ‚ซใ‚ฆใƒณใƒˆใฏไธ่ฆใงใ™ใ€‚

ๆ–‡ๅญ—ๆ•ฐๅˆถ้™ใ‚‚ใชใ‘ใ‚Œใฐใ€APIใƒฌใƒผใƒˆๅˆถ้™ใซๆ‚ฉใพใ•ใ‚Œใ‚‹ใ“ใจใ‚‚ใ‚ใ‚Šใพใ›ใ‚“ใ€‚

bot.onMention = async (session, message) => {
  await message.reply(text`ใ“ใ‚“ใซใกใฏใ€${message.actor}ใ•ใ‚“๏ผ`);
};

ใƒ•ใ‚งใƒ‡ใƒฌใƒผใ‚ทใƒงใƒณใ€HTTP Signaturesใ€้…้€ใ‚ญใƒฅใƒผใจใ„ใฃใŸActivityPubๅ‘จใ‚Šใฎๅ‡ฆ็†ใฏFedifyใŒใ™ในใฆๅผ•ใๅ—ใ‘ใพใ™ใ€‚ใƒœใƒƒใƒˆใฎใƒญใ‚ธใƒƒใ‚ฏใ‚’ๆ›ธใใ ใ‘ใงใ™ใ€‚

Denoใงใ‚‚Node.jsใงใ‚‚ๅ‹•ใใพใ™ใ€‚

https://botkit.fedify.dev/

0

is a framework for building bots. The difference from typical Mastodon/Misskey bots? Your bot runs as its own independent serverโ€”no platform account needed.

This means no character limits, no rate limiting headaches, no API restrictions.

bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}!`);
};

The ActivityPub stuff (federation, HTTP Signatures, delivery queues) is handled by under the hood. You just write your bot logic.

Works with both and .js.

https://botkit.fedify.dev/

BotKit์€ ActivityPub ๋ด‡์„ ๋งŒ๋“œ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ Mastodon/Misskey ๋ด‡๊ณผ ๋‹ค๋ฅธ ์ ์€, ๋ด‡ ์ž์ฒด๊ฐ€ ๋…๋ฆฝ๋œ ์„œ๋ฒ„๋กœ ๋Œ์•„๊ฐ„๋‹ค๋Š” ๊ฒ๋‹ˆ๋‹ค. ํ”Œ๋žซํผ ๊ณ„์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

๊ธ€์ž ์ˆ˜ ์ œํ•œ๋„ ์—†๊ณ , API ํ˜ธ์ถœ ์ œํ•œ์— ์‹œ๋‹ฌ๋ฆด ์ผ๋„ ์—†์Šต๋‹ˆ๋‹ค.

bot.onMention = async (session, message) => {
  await message.reply(text`์•ˆ๋…•ํ•˜์„ธ์š”, ${message.actor}๋‹˜!`);
};

์—ฐํ•ฉ(federation), HTTP Signatures, ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ๊ฐ™์€ ๊ด€๋ จ ์ฒ˜๋ฆฌ๋Š” Fedify๊ฐ€ ์•Œ์•„์„œ ํ•ด์ค๋‹ˆ๋‹ค. ๋ด‡ ๋กœ์ง๋งŒ ์งœ๋ฉด ๋˜๋Š” ๊ฑฐ์ฃ .

๋ฐ .js ๋‘˜ ๋‹ค ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

https://botkit.fedify.dev/

1

is a framework for building bots. The difference from typical Mastodon/Misskey bots? Your bot runs as its own independent serverโ€”no platform account needed.

This means no character limits, no rate limiting headaches, no API restrictions.

bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}!`);
};

The ActivityPub stuff (federation, HTTP Signatures, delivery queues) is handled by under the hood. You just write your bot logic.

Works with both and .js.

https://botkit.fedify.dev/

0
2
0

Fresh์™€์˜ ์•ˆ ์ข‹์€ ์ฒซ ๋งŒ๋‚จ: @fedify/fresh ์ œ์ž‘๊ธฐ - 1

๊ฐœ๋ฐœ๊ณฐ @gaebalgom@hackers.pub

Deno ํŒ€์—์„œ ๊ฐœ๋ฐœํ•˜๋Š” Fresh ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ Fedify ํ”„๋กœ์ ํŠธ์— ํ†ตํ•ฉํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ฒช์€ ๋ฌธ์ œ์ ์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. Fresh 2.X ๋ฒ„์ „์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋ฉด์„œ ๊ธฐ์กด ์ฝ”๋“œ์™€์˜ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ณ , Fedify ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด Fresh ํ†ตํ•ฉ์„ ์œ„ํ•œ ๋ณ„๋„ ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ • ์ค‘ `node_modules` ๊ด€๋ จ ์˜ค๋ฅ˜์™€ Preact ๋ Œ๋”๋ง ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ, Fedify ๋ฏธ๋“ค์›จ์–ด ์ ์šฉ ์‹œ Vite์˜ SSR Module Runner๊ฐ€ CJS๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์•„ ์„œ๋ฒ„ ์‹คํ–‰์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. Vite ์„ค์ •์—์„œ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์ง€๋งŒ, ๋นŒ๋“œ ํ›„ ์‹คํ–‰ ์‹œ CJS ๊ด€๋ จ ๋ฌธ์ œ๊ฐ€ ๋‹ค์‹œ ๋ฐœ์ƒํ•˜์—ฌ Rollup ์˜ต์…˜์„ ์กฐ์ •ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธ€์€ Fresh์™€ Fedify๋ฅผ ํ†ตํ•ฉํ•˜๋ ค๋Š” ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ฒช์„ ์ˆ˜ ์žˆ๋Š” ์–ด๋ ค์›€์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Read more โ†’
4

Okay, so either Deno's OpenTelemetry metric โ€œhttp.server.active_requestsโ€ (docs.deno.com/runtime/fundamen) is actually cumulative over the lifetime of the process, or I have found the explanation for why I can't get the Encyclia server to behave.

Next question is what I could be doing wrong. ๐Ÿค” All it does is โ€œdeno runโ€ and everything that doesn't time out seems to return what it should.

(The middle of the graph is where I restarted Deno twice.)

Line graph showing "http_server_active_requests" over a 9 hour duration. It starts at 0, climbs to 5000 almost in a slow straight line over 3 hours, then drops back down to 0, makes a tiny, quick bump up to 100 and back down to 0, only to start climbing again, slightly slower, to 3000 over the course of about 3.5 hours

Ah, found the culprit. It was one of the spots where I told the program to do nothing later. Turns out my wording was slightly off.

Before:

return new Promise(() => {});

After:

return Promise.resolve(null);

The number of concurrent connections looks negligible now, and no more timeouts either. Calling it a success for tonight, we'll see how things look in the morning. ๐Ÿฅฑ

As underwhelming as the cause is, that journey might deserve a blog post if I find the time!

0

Okay, so either Deno's OpenTelemetry metric โ€œhttp.server.active_requestsโ€ (docs.deno.com/runtime/fundamen) is actually cumulative over the lifetime of the process, or I have found the explanation for why I can't get the Encyclia server to behave.

Next question is what I could be doing wrong. ๐Ÿค” All it does is โ€œdeno runโ€ and everything that doesn't time out seems to return what it should.

(The middle of the graph is where I restarted Deno twice.)

Line graph showing "http_server_active_requests" over a 9 hour duration. It starts at 0, climbs to 5000 almost in a slow straight line over 3 hours, then drops back down to 0, makes a tiny, quick bump up to 100 and back down to 0, only to start climbing again, slightly slower, to 3000 over the course of about 3.5 hours
0

Exciting news for developers! We've just landed a major milestone for Fedify 2.0โ€”the now runs natively on .js and , not just (#456). If you install @fedify/cli@2.0.0-dev.1761 from npm, you'll get actual JavaScript that executes directly in your runtime, no more pre-compiled binaries from deno compile. This is part of our broader transition to Optique, a new cross-runtime CLI framework we've developed specifically for Fedify's needs (#374).

This change means a more natural development experience regardless of your runtime preference. Node.js developers can now run the CLI tools directly through their familiar ecosystem, and the same goes for Bun users. While Fedify 2.0 isn't released yet, we're excited to share this progress with the communityโ€”feel free to try out the dev version and let us know how it works for you!

2
0
0

Optique 0.6.0: Shell completion support for type-safe CLI parsers

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Optique 0.6.0 introduces intelligent shell completion to type-safe command-line applications, supporting Bash, zsh, fish, PowerShell, and Nushell. Unlike traditional CLI frameworks, Optique leverages the same parser structure for both argument parsing and completion, eliminating duplicate definitions and ensuring synchronization. Setting up completion is straightforward, with users generating and sourcing a completion script for their shell. The system works automatically with all Optique parser types, offering context-aware suggestions, including file system completion and custom logic for domain-specific value parsers. Additionally, the release enhances command documentation with separate brief, description, and footer texts, and introduces a `commandLine()` message term for clearer command-line examples in help text. Existing Optique users can easily migrate by adding a `completion` option to their `run()` configuration. This release aims to make Optique-based CLIs more user-friendly without sacrificing type safety and composability, providing sophisticated runtime features while maintaining compile-time guarantees.

Read more โ†’
5

Optique 0.5.0: Enhanced error handling and message customization

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Optique 0.5.0 is now available, bringing enhancements to error handling, help text generation, and overall developer experience while maintaining full backward compatibility. The update introduces better code organization by refactoring the large `@optique/core/parser` module into three focused modules: `@optique/core/primitives`, `@optique/core/modifiers`, and `@optique/core/constructs`. Error handling is improved with automatic conversion of default value callback errors into parser-level errors, and the new `WithDefaultError` class allows for structured error messages. Customization of default values in help text is now possible via an optional third parameter to `withDefault()`, enabling descriptive text instead of actual values. Additionally, the release provides comprehensive error message customization across all parser types and combinators, allowing context-specific feedback. These improvements aim to make Optique more user-friendly, especially for building CLI applications that require clear error messages and helpful documentation, making this release a significant step forward for developers using Optique.

Read more โ†’
5
0

Upyo 0.3.0: Multi-provider resilience and deployment flexibility

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Upyo 0.3.0 introduces three new transports designed to enhance email delivery capabilities and reliability. The update focuses on multi-provider support and flexible deployment options. The new pool transport, via the `@upyo/pool` package, combines multiple email providers with routing strategies like round-robin, weighted distribution, and priority-based routing, ensuring high availability and cost optimization. Additionally, the `@upyo/resend` package integrates Resend, an email service provider known for its developer-friendly approach and intelligent batch optimization. For those needing self-hosting options, the `@upyo/plunk` package supports Plunk, offering both cloud-hosted and Docker-based self-hosted deployments. These new transports maintain Upyo's consistent API design, ensuring they can be easily integrated into existing workflows. This release expands Upyo's utility by providing more robust and adaptable email delivery solutions.

Read more โ†’
3

Optique 0.4.0 Released!

Big update for our type-safe combinatorial parser for :

  • Labeled merge groups: organize options logically
  • Rich docs: brief, description & footer support
  • @optique/temporal: new package for date/time parsing
  • showDefault: automatic default value display

The help text has never looked this good!

.js

0

Optique 0.3.0: Dependent options and flexible composition

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Optique 0.3.0 introduces several enhancements aimed at simplifying the development of complex CLI applications. This release focuses on expanding parser flexibility and refining the help system, incorporating valuable community feedback. Key updates include the introduction of required Boolean flags using the new `flag()` parser, more flexible type defaults in `withDefault()` to support union types, and an extended `or()` capacity that now supports up to 10 parsers. The `merge()` combinator has also been enhanced to work with any object-producing parser, and context-aware help is now available through the `longestMatch()` combinator. Additionally, version display support has been added to both `@optique/core` and `@optique/run`, along with structured output functions for consistent terminal formatting. These improvements collectively provide developers with more powerful tools for building intuitive and feature-rich command-line interfaces.

Read more โ†’
3

We're excited to announce the release of BotKit 0.3.0! This release marks a significant milestone as now supports .js alongside , making it accessible to a wider audience. The minimum required Node.js version is 22.0.0. This dual-runtime support means you can now choose your preferred runtime while building with the same powerful BotKit APIs.

One of the most requested features has landed: poll support! You can now create interactive polls in your messages, allowing followers to vote on questions with single or multiple-choice options. Polls are represented as ActivityPub Question objects with proper expiration times, and your bot can react to votes through the new onVote event handler. This feature enhances engagement possibilities and brings BotKit to feature parity with major platforms like Mastodon and Misskey.

// Create a poll with multiple choices
await session.publish(text`What's your favorite programming language?`, {
  class: Question,
  poll: {
    multiple: true,  // Allow multiple selections
    options: ["JavaScript", "TypeScript", "Python", "Rust"],
    endTime: Temporal.Now.instant().add({ hours: 24 }),
  },
});

// Handle votes
bot.onVote = async (session, vote) => {
  console.log(`${vote.actor} voted for "${vote.option}"`);
};

The web frontend has been enhanced with a new followers page, thanks to the contribution from Hyeonseo Kim (@gaebalgom๊ฐœ๋ฐœ๊ณฐ)! The /followers route now displays a paginated list of your bot's followers, and the follower count on the main profile page is now clickable, providing better visibility into your bot's audience. This improvement makes the web interface more complete and user-friendly.

For developers looking for alternative storage backends, we've introduced the SqliteRepository through the new @fedify/botkit-sqlite package. This provides a production-ready SQLite-based storage solution with ACID compliance, write-ahead logging (WAL) for optimal performance, and proper indexing. Additionally, the new @fedify/botkit/repository module offers MemoryCachedRepository for adding an in-memory cache layer on top of any repository implementation, improving read performance for frequently accessed data.

This release also includes an important security update: we've upgraded to 1.8.8, ensuring your bots stay secure and compatible with the latest ActivityPub standards. The repository pattern has been expanded with new interfaces and types like RepositoryGetMessagesOptions, RepositoryGetFollowersOptions, and proper support for polls storage through the KvStoreRepositoryPrefixes.polls option, providing more flexibility for custom implementations.

2
0
0

Upyo 0.2.0 Release Notes

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

Upyo 0.2.0 has been released, introducing new features to this cross-runtime email library that supports Node.js, Deno, Bun, and edge functions. The latest version expands its capabilities with Amazon SES transport support, enabling AWS Signature v4 authentication and session-based authentication. Additionally, comprehensive OpenTelemetry integration has been added, offering distributed tracing, metrics collection, and error classification without altering existing code. The OpenTelemetry transport automatically instruments email operations, tracking delivery rates and latency, and integrates with existing OpenTelemetry infrastructure. Community feedback is encouraged to further improve Upyo, whether through testing the new Amazon SES transport, implementing OpenTelemetry, or contributing to the GitHub repository. This release enhances Upyo's utility by providing more transport options and robust observability features, making it a valuable tool for developers needing reliable email sending across various environments.

Read more โ†’
4

Introducing !

A simple, cross-runtime email library that works seamlessly on , .js, , and edge functions. Zero dependencies, unified API, and excellent testability with built-in mock transport.

Switch between , , without changing your code. Available on & !

https://upyo.org/

0
2
0

deno-vite-plugin ๋””๋ฒ„๊น… 1ํŽธ

Lee Dogeon @moreal@hackers.pub

์ด ๊ธ€์€ Deno ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์—์„œ SolidStart์™€ `deno-vite-plugin`์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, `jsr:@fedify/fedify` ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž„ํฌํŠธํ•  ๋•Œ `deno task build`๊ฐ€ ์‹คํŒจํ•˜๋Š” ์ƒํ™ฉ์„ ์žฌํ˜„ํ•˜๊ณ , ์›์ธ์„ ๋ถ„์„ํ•˜์—ฌ ์ž„์‹œ ํ•ด๊ฒฐ์ฑ…์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ์˜ ์›์ธ์€ `deno info` ๋ช…๋ น์–ด๊ฐ€ `kind: asserted`์ธ ๋ชจ๋“ˆ์„ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฐ ์žˆ์—ˆ์œผ๋ฉฐ, ์ด๋ฅผ `esm`์œผ๋กœ ์ทจ๊ธ‰ํ•˜๋„๋ก ์ˆ˜์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ๊ทผ๋ณธ์ ์ธ ํ•ด๊ฒฐ์ฑ…์€ ์•„๋‹ˆ๋ฉฐ, ์ถ”๊ฐ€์ ์ธ `npm` ๊ด€๋ จ ์—๋Ÿฌ๊ฐ€ ๋‚จ์•„์žˆ์Œ์„ ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ํฌ์ŠคํŒ…์€ Deno ์ƒํƒœ๊ณ„์—์„œ Vite ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์™€ ๊ทธ ํ•ด๊ฒฐ ๊ณผ์ •์„ ๋ณด์—ฌ์ฃผ๋ฉฐ, ์œ ์‚ฌํ•œ ๋ฌธ์ œ๋ฅผ ๊ฒช๋Š” ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ ์‹ค์งˆ์ ์ธ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Read more โ†’
2

It's been 30 years we have . So much in technology has changed in that time. It's kind of amazing how much the language and the broader web helped shape the world.

post on the history of Javascript really cements this. Can't believe it's been that long. ๐Ÿ˜…

deno.com/blog/history-of-javas

0
0

Announcing LogTape 1.0.0

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

LogTape 1.0.0 has been released, marking a significant milestone for this zero-dependency logging library designed for the modern JavaScript ecosystem. This release emphasizes API stability and introduces high-performance features such as non-blocking sinks for console, stream, and file logging, along with the `fromAsyncSink()` function for integrating asynchronous logging operations. New sink integrations include packages for AWS CloudWatch Logs and Windows Event Log, enhancing LogTape's versatility. The update also brings a visually appealing console logging experience with the `@logtape/pretty` package, and seamless integration with existing Winston or Pino setups through adapter packages. Key developer experience enhancements include programmatic access to log levels and improved browser compatibility. LogTape 1.0.0 streamlines logging infrastructure with a comprehensive package ecosystem, offering specialized packages for various logging needs. This release provides a stable and mature logging solution, making it easier to manage and optimize logging in JavaScript applications.

Read more โ†’
11

LogTape 0.12.0 Release Notes

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

LogTape, a zero-dependency logging library for JavaScript and TypeScript, has released version 0.12.0 with several enhancements. The update introduces a new `trace` log level for more granular debugging and improves file sink performance through configurable buffering. A significant addition is the `@logtape/syslog` package, enabling log message transmission to syslog servers using RFC 5424. The update also includes `Logger.warning()` as an alias for `Logger.warn()` for consistency. Furthermore, all LogTape packages now share unified versioning for better compatibility. The build infrastructure has been migrated from `dnt` to `tsdown`, enhancing compatibility with modern JavaScript toolchains and improving build times. This release optimizes logging capabilities and ensures smoother integration with various JavaScript runtimes.

Read more โ†’
9

We're migrating Hackers' Pub to a pretty unconventional tech stack, and I'm honestly excited about it!

Thanks to my friend @xiniha, we're diving into , , , , and . In a world dominated by Next.js and React, this feels refreshingly different. And yes, we're sticking with instead of Node.js too.

Some might call it contrarian, but I like to think of it as exploring what's possible beyond the mainstream. Sometimes the road less traveled leads to interesting places.

7
4
1

I think I've fully adopted to writing scripts in with . ๐Ÿ˜… It can be so immensely convenient.

You can bundle hack something fairly quickly. With dependencies pinned. And most of all, still have some level of security.

Can't say the same of all my other language scripts. ๐Ÿซ 

0

Hello @hongminheeๆดช ๆฐ‘ๆ†™ (Hong Minhee) :nonbinary:

since multiple hours I was sleepless cause I wondered about how to store anything ActivityPub in

I think, I will finish this crazy code somewhen in the next days :) Would you be interested in such a thing?

If:
Tried to solve the following fully ActivityPub conformant, meaning e.g.
- multiple actors can do an action on multiple objects and it needs to be fully versioned cause Undo or Undo/Undo โ€ฆ
- so anything is RFC 6902 <-> kv where anything is ulid and the "version" for the object is the ulid of an Update/Undo etc.
- JSON Patch acknowledges the limits (e.g. size of kv values), any property is stored versioned
- strongly avoiding duplicates;
the "text properties" like contentMap are stored as cid and similar beneath each other by a numeric nilsimsa hash (though /me bad at math)
- we can query all relationships and
- additionally "where", "when", "what" questions are answered by geohash, ulid ranges or a specific hierarchic hash of as:- and our subtypes

0
1
0

Ditch the DIY Drama: Why Use Fedify Instead of Building ActivityPub from Scratch?

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

So, you're captivated by the fediverseโ€”the decentralized social web powered by protocols like ActivityPub. Maybe you're dreaming of building the next great federated app, a unique space connected to Mastodon, Lemmy, Pixelfed, and more. The temptation to dive deep and implement ActivityPub yourself, from the ground up, is strong. Total control, right? Understanding every byte? Sounds cool!

But hold on a sec. Before you embark on that epic quest, let's talk reality. Implementing ActivityPub correctly isn't just one task; it's like juggling several complex standards while riding a unicycleโ€ฆ blindfolded. Itโ€™s hard.

That's where Fedify comes in. It's a TypeScript framework designed to handle the gnarliest parts of ActivityPub development, letting you focus on what makes your app special, not reinventing the federation wheel.

This post will break down the common headaches of DIY ActivityPub implementation and show how Fedify acts as the super-powered pain reliever, starting with the very foundation of how data is represented.

Challenge #1: Data Modelingโ€”Speaking ActivityStreams & JSON-LD Fluently

At its core, ActivityPub relies on the ActivityStreams 2.0 vocabulary to describe actions and objects, and it uses JSON-LD as the syntax to encode this vocabulary. While powerful, this combination introduces significant complexity right from the start.

First, understanding and correctly using the vast ActivityStreams vocabulary itself is a hurdle. You need to model everythingโ€”posts (Note, Article), profiles (Person, Organization), actions (Create, Follow, Like, Announce)โ€”using the precise terms and properties defined in the specification. Manual JSON construction is tedious and prone to errors.

Second, JSON-LD, the encoding layer, has specific rules that make direct JSON manipulation surprisingly tricky:

  • Missing vs. Empty Array: In JSON-LD, a property being absent is often semantically identical to it being present with an empty array. Your application logic needs to treat these cases equally when checking for values. For example, these two Note objects mean the same thing regarding the name property:
    // No name property
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "โ€ฆ"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "name": [],
      "content": "โ€ฆ"
    }
  • Single Value vs. Array: Similarly, a property holding a single value directly is often equivalent to it holding a single-element array containing that value. Your code must anticipate both representations for the same meaning, like for the content property here:
    // Single value
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": "Hello"
    }
    // Equivalent to:
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Note",
      "content": ["Hello"]
    }
  • Object Reference vs. Embedded Object: Properties can contain either the full JSON-LD object embedded directly or just a URI string referencing that object. Your application needs to be prepared to fetch the object's data if only a URI is given (a process called dereferencing). These two Announce activities are semantically equivalent (assuming the URIs resolve correctly):
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // Embedded objects:
      "actor": {
        "type": "Person",
        "id": "http://sally.example.org/",
        "name": "Sally"
      },
      "object": {
        "type": "Arrive",
        "id": "https://sally.example.com/arrive",
        /* ... */
      }
    }
    // Equivalent to:
    {
      "@context":
      "https://www.w3.org/ns/activitystreams",
      "type": "Announce",
      // URI references:
      "actor": "http://sally.example.org/",
      "object": "https://sally.example.com/arrive"
    }

Attempting to manually handle all these vocabulary rules and JSON-LD variations consistently across your application inevitably leads to verbose, complex, and fragile code, ripe for subtle bugs that break federation.

Fedify tackles this entire data modeling challenge with its comprehensive, type-safe Activity Vocabulary API. It provides TypeScript classes for ActivityStreams types and common extensions, giving you autocompletion and compile-time safety. Crucially, these classes internally manage all the tricky JSON-LD nuances. Fedify's property accessors present a consistent interfaceโ€”non-functional properties (like tags) always return arrays, functional properties (like content) always return single values or null. It handles object references versus embedded objects seamlessly through dereferencing accessors (like activity.getActor()) which automatically fetch remote objects via URI when neededโ€”a feature known as property hydration. With Fedify, you work with a clean, predictable TypeScript API, letting the framework handle the messy details of AS vocabulary and JSON-LD encoding.

Challenge #2: Discovery & Identityโ€”Finding Your Actors

Once you can model data, you need to make your actors discoverable. This primarily involves the WebFinger protocol (RFC 7033). You'd need to build a server endpoint at /.well-known/webfinger capable of parsing resource queries (like acct: URIs), validating the requested domain against your server, and responding with a precisely formatted JSON Resource Descriptor (JRD). This JRD must include specific links, like a self link pointing to the actor's ActivityPub ID using the correct media type. Getting any part of this wrong can make your actors invisible.

Fedify simplifies this significantly. It automatically handles WebFinger requests based on the actor information you provide through its setActorDispatcher() method. Fedify generates the correct JRD response. If you need more advanced control, like mapping user-facing handles to internal identifiers, you can easily register mapHandle() or mapAlias() callbacks. You focus on defining your actors; Fedify handles making them discoverable.

// Example: Define how to find actors
federation.setActorDispatcher(
  "/users/{username}",
  async (ctx, username) => { /* ... */ }
);
// Now GET /.well-known/webfinger?resource=acct:username@your.domain just works!

Challenge #3: Core ActivityPub Mechanicsโ€”Handling Requests and Collections

Serving actor profiles requires careful content negotiation. A request for an actor's ID needs JSON-LD for machine clients (Accept: application/activity+json) but HTML for browsers (Accept: text/html). Handling incoming activities at the inbox endpoint involves validating POST requests, verifying cryptographic signatures, parsing the payload, preventing duplicates (idempotency), and routing based on activity type. Implementing collections (outbox, followers, etc.) with correct pagination adds another layer.

Fedify streamlines all of this. Its core request handler (via Federation.fetch() or framework adapters like @fedify/express) manages content negotiation. You define actors with setActorDispatcher() and web pages with your framework (Hono, Express, SvelteKit, etc.)โ€”Fedify routes appropriately. For the inbox, setInboxListeners() lets you define handlers per activity type (e.g., .on(Follow, ...)), while Fedify automatically handles validation, signature verification, parsing, and idempotency checks using its KV Store. Collection implementation is simplified via dispatchers (e.g., setFollowersDispatcher()); you provide logic to fetch a page of data, and Fedify constructs the correct Collection or CollectionPage with pagination.

// Define inbox handlers
federation.setInboxListeners("/inbox", "/users/{handle}/inbox")
  .on(Follow, async (ctx, follow) => { /* Handle follow */ })
  .on(Undo, async (ctx, undo) => { /* Handle undo */ });

// Define followers collection logic
federation.setFollowersDispatcher(
  "/users/{handle}/followers",
  async (ctx, handle, cursor) => { /* ... */ }
);

Challenge #4: Reliable Delivery & Asynchronous Processingโ€”Sending Activities Robustly

Sending an activity requires more than a simple POST. Networks fail, servers go down. You need robust failure handling and retry logic (ideally with backoff). Processing incoming activities synchronously can block your server. Efficiently broadcasting to many followers (fan-out) requires background processing and using shared inboxes where possible.

Fedify addresses reliability and scalability using its MessageQueue abstraction. When configured (highly recommended), Context.sendActivity() enqueues delivery tasks. Background workers handle sending with automatic retries based on configurable policies (like outboxRetryPolicy). Fedify supports various queue backends (Deno KV, Redis, PostgreSQL, AMQP). For high-traffic fan-out, Fedify uses an optimized two-stage mechanism to distribute the load efficiently.

// Configure Fedify with a persistent queue (e.g., Deno KV)
const federation = createFederation({
  queue: new DenoKvMessageQueue(/* ... */),
  // ...
});
// Sending is now reliable and non-blocking
await ctx.sendActivity({ handle: "myUser" }, recipient, someActivity);

Challenge #5: Securityโ€”Avoiding Common Pitfalls

Securing an ActivityPub server is critical. You need to implement HTTP Signatures (draft-cavage-http-signatures-12) for server-to-server authenticationโ€”a complex process. You might also need Linked Data Signatures (LDS) or Object Integrity Proofs (OIP) based on FEP-8b32 for data integrity and compatibility. Managing cryptographic keys securely is essential. Lastly, fetching remote resources risks Server-Side Request Forgery (SSRF) if not validated properly.

Fedify is designed with security in mind. It automatically handles the creation and verification of HTTP Signatures, LDS, and OIP, provided you supply keys via setKeyPairsDispatcher(). It includes key management utilities. Crucially, Fedify's default document loader includes built-in SSRF protection, blocking requests to private IPs unless explicitly allowed.

Challenge #6: Interoperability & Maintenanceโ€”Playing Nicely with Others

The fediverse is diverse. Different servers have quirks. Ensuring compatibility requires testing and adaptation. Standards evolve with new Federation Enhancement Proposals (FEPs). You also need protocols like NodeInfo to advertise server capabilities.

Fedify aims for broad interoperability and is actively maintained. It includes features like ActivityTransformers to smooth over implementation differences. NodeInfo support is built-in via setNodeInfoDispatcher().

Challenge #7: Developer Experienceโ€”Actually Building Your App

Beyond the protocol, building any server involves setup, testing, and debugging. With federation, debugging becomes harderโ€”was the message malformed? Was the signature wrong? Is the remote server down? Is it a compatibility quirk? Good tooling is essential.

Fedify enhances the developer experience significantly. Being built with TypeScript, it offers excellent type safety and editor auto-completion. The fedify CLI is a powerful companion designed to streamline common development tasks.

You can quickly scaffold a new project tailored to your chosen runtime and web framework using fedify init.

For debugging interactions and verifying data, fedify lookup is invaluable. It lets you inspect how any remote actor or object appears from the outside by performing WebFinger discovery and fetching the object's data. Fedify then displays the parsed object structure and properties directly in your terminal. For example, running:

$ fedify lookup @fedify-example@fedify-blog.deno.dev

Will first show progress messages and then output the structured representation of the actor, similar to this:

// Output of fedify lookup command (shows parsed object structure)
Person {
  id: URL "https://fedify-blog.deno.dev/users/fedify-example",
  name: "Fedify Example Blog",
  published: 2024-03-03T13:18:11.857Z, // Simplified timestamp
  summary: "This blog is powered by Fedify, a fediverse server framework.",
  url: URL "https://fedify-blog.deno.dev/",
  preferredUsername: "fedify-example",
  publicKey: CryptographicKey {
    id: URL "https://fedify-blog.deno.dev/users/fedify-example#main-key",
    owner: URL "https://fedify-blog.deno.dev/users/fedify-example",
    publicKey: CryptoKey { /* ... CryptoKey details ... */ }
  },
  // ... other properties like inbox, outbox, followers, endpoints ...
}

This allows you to easily check how data is structured or troubleshoot why an interaction might be failing by seeing the actual properties Fedify parsed.

Testing outgoing activities from your application during development is made much easier with fedify inbox. Running the command starts a temporary local server that acts as a publicly accessible inbox, displaying key information about the temporary actor it creates for receiving messages:

$ fedify inbox
โœ” The ephemeral ActivityPub server is up and running: https://<unique_id>.lhr.life/
โœ” Sent follow request to @<some_test_account>@activitypub.academy.
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Actor handle: โ”‚ i@<unique_id>.lhr.life                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚   Actor URI:  โ”‚ https://<unique_id>.lhr.life/i          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  Actor inbox: โ”‚ https://<unique_id>.lhr.life/i/inbox    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Shared inbox: โ”‚ https://<unique_id>.lhr.life/inbox      โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Web interface available at: http://localhost:8000/

You then configure your developing application to send an activity to the Actor inbox or Shared inbox URI provided. When an activity arrives, fedify inbox only prints a summary table to your console indicating that a request was received:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚     Request #: โ”‚ 2                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Activity type: โ”‚ Follow                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  HTTP request: โ”‚ POST /i/inbox                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ HTTP response: โ”‚ 202                                 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚       Details  โ”‚ https://<unique_id>.lhr.life/r/2    โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Crucially, the detailed information about the received requestโ€”including the full headers (like Signature), the request body (the Activity JSON), and the signature verification statusโ€”is only available in the web interface provided by fedify inbox. This web UI allows you to thoroughly inspect incoming activities during development.

Screenshot of the Fedify Inbox web interface showing received activities and their details.
The Fedify Inbox web UI is where you view detailed activity information.

When you need to test interactions with the live fediverse from your local machine beyond just sending, fedify tunnel can securely expose your entire local development server temporarily. This suite of tools significantly eases the process of building and debugging federated applications.

Conclusion: Build Features, Not Plumbing

Implementing the ActivityPub suite of protocols from scratch is an incredibly complex and time-consuming undertaking. It involves deep dives into multiple technical specifications, cryptographic signing, security hardening, and navigating the nuances of a diverse ecosystem. While educational, it dramatically slows down the process of building the actual, unique features of your federated application.

Fedify offers a well-architected, secure, and type-safe foundation, handling the intricacies of federation for youโ€”data modeling, discovery, core mechanics, delivery, security, and interoperability. It lets you focus on your application's unique value and user experience. Stop wrestling with low-level protocol details and start building your vision for the fediverse faster and more reliably. Give Fedify a try!

Getting started is straightforward. First, install the Fedify CLI using your preferred method. Once installed, create a new project template by running fedify init your-project-name.

Check out the Fedify tutorials and Fedify manual to learn more. Happy federating!

Read more โ†’
13
0
3
1
0

is an server framework in & . It aims to eliminate the complexity and redundant boilerplate code when building a federated server app, so that you can focus on your business logic and user experience.

The key features it provides currently are:

โ€ข Type-safe objects for Activity Vocabulary (including some vendor-specific extensions)
โ€ข client and server
โ€ข HTTP Signatures
โ€ข Middleware for handling webhooks
โ€ข protocol
โ€ข .js, , and support
โ€ข CLI toolchain for testing and debugging

If you're curious, take a look at the Fedify website! There's comprehensive docs, a demo, a tutorial, example code, and more:

fedify.dev/

0
0
0

deno-task-hooks: Git ํ›…์„ Deno ํƒœ์Šคํฌ๋กœ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ

ๆดช ๆฐ‘ๆ†™ (Hong Minhee) @hongminhee@hackers.pub

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ ์ œ๊ฐ€ ๊ฐœ๋ฐœํ•œ deno-task-hooks ํŒจํ‚ค์ง€๋ฅผ ์†Œ๊ฐœํ•ด ๋“œ๋ฆฌ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋Š” Deno ํƒœ์Šคํฌ๋ฅผ Git ํ›…์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ„๋‹จํ•˜๋ฉด์„œ๋„ ์œ ์šฉํ•œ ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋‚˜์š”?

Git์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ ํŒ€์—์„œ๋Š” ์ฝ”๋“œ ํ’ˆ์งˆ ์œ ์ง€๋ฅผ ์œ„ํ•ด ์ปค๋ฐ‹์ด๋‚˜ ํ‘ธ์‹œ ์ „์— ๋ฆฐํŠธ, ํ…Œ์ŠคํŠธ ๋“ฑ์˜ ๊ฒ€์ฆ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ž‘์—…์€ Git ํ›…์„ ํ†ตํ•ด ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ธฐ์กด ๋ฐฉ์‹์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค:

  • Git ํ›… ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํŒ€์›๋“ค๊ณผ ๊ณต์œ ํ•˜๊ธฐ ์–ด๋ ค์›€ (.git ๋””๋ ‰ํ† ๋ฆฌ๋Š” ๋ณดํ†ต ๋ฒ„์ „ ๊ด€๋ฆฌ์—์„œ ์ œ์™ธ๋จ)
  • ๊ฐ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋กœ์ปฌ์—์„œ ํ›…์„ ์ง์ ‘ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€
  • ํ›… ์Šคํฌ๋ฆฝํŠธ์˜ ์ผ๊ด€์„ฑ ์œ ์ง€๊ฐ€ ์–ด๋ ค์›€

deno-task-hooks๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Deno์˜ ํƒœ์Šคํฌ ๋Ÿฌ๋„ˆ๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. Deno ํƒœ์Šคํฌ๋Š” deno.json ํŒŒ์ผ์— ์ •์˜๋˜์–ด ๋ฒ„์ „ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ํŒ€ ์ „์ฒด๊ฐ€ ๋™์ผํ•œ Git ํ›…์„ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

deno-task-hooks์˜ ์ž‘๋™ ๋ฐฉ์‹์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค:

  1. deno.json ํŒŒ์ผ์— Git ํ›…์œผ๋กœ ์‚ฌ์šฉํ•  Deno ํƒœ์Šคํฌ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  2. hooks:install ํƒœ์Šคํฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ์ •์˜๋œ ํƒœ์Šคํฌ๋“ค์ด ์ž๋™์œผ๋กœ .git/hooks/ ๋””๋ ‰ํ† ๋ฆฌ์— ์„ค์น˜๋ฉ๋‹ˆ๋‹ค.
  3. ์ดํ›„ Git ์ž‘์—… ์‹œ ํ•ด๋‹น ํ›…์ด ํŠธ๋ฆฌ๊ฑฐ๋˜๋ฉด ์—ฐ๊ฒฐ๋œ Deno ํƒœ์Šคํฌ๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์„ค์น˜ ๋ฐ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

1. hooks:install ํƒœ์Šคํฌ ์ถ”๊ฐ€ํ•˜๊ธฐ

๋จผ์ € deno.json ํŒŒ์ผ์— hooks:install ํƒœ์Šคํฌ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

{
  "tasks": {
    "hooks:install": "deno run --allow-read=deno.json,.git/hooks/ --allow-write=.git/hooks/ jsr:@hongminhee/deno-task-hooks"
  }
}

2. Git ํ›… ์ •์˜ํ•˜๊ธฐ

Git ํ›…์€ hooks: ์ ‘๋‘์‚ฌ ๋‹ค์Œ์— ํ›… ์ด๋ฆ„(์ผ€๋ฐฅ ์ผ€์ด์Šค)์„ ๋ถ™์—ฌ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, pre-commit ํ›…์„ ์ •์˜ํ•˜๋ ค๋ฉด:

{
  "tasks": {
    "hooks:pre-commit": "deno check *.ts && deno lint"
  }
}

3. ํ›… ์„ค์น˜ํ•˜๊ธฐ

๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ •์˜๋œ ํ›…์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค:

deno task hooks:install

์ด์ œ Git ์ปค๋ฐ‹์„ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค pre-commit ํ›…์ด ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜์–ด TypeScript ํŒŒ์ผ์„ ๊ฒ€์‚ฌํ•˜๊ณ  ๋ฆฐํŠธ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ง€์›๋˜๋Š” Git ํ›… ์ข…๋ฅ˜

deno-task-hooks๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชจ๋“  Git ํ›… ํƒ€์ž…์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:

  • applypatch-msg
  • commit-msg
  • fsmonitor-watchman
  • post-update
  • pre-applypatch
  • pre-commit
  • pre-merge-commit
  • pre-push
  • pre-rebase
  • pre-receive
  • prepare-commit-msg
  • push-to-checkout
  • sendemail-validate
  • update

์ด์ 

deno-task-hooks๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ๊ฐ„ํŽธํ•œ ๊ณต์œ : Git ํ›…์„ deno.json ํŒŒ์ผ์— ์ •์˜ํ•˜์—ฌ ํŒ€ ์ „์ฒด๊ฐ€ ๋™์ผํ•œ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์„ค์ • ์šฉ์ด์„ฑ: ์ƒˆ ํŒ€์›์€ ์ €์žฅ์†Œ๋ฅผ ํด๋ก ํ•œ ํ›„ ํ•œ ๋ฒˆ์˜ ๋ช…๋ น์–ด๋กœ ๋ชจ๋“  ํ›…์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ์œ ์ง€ ๊ด€๋ฆฌ ์šฉ์ด์„ฑ: ํ›… ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜๋ฏ€๋กœ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์‰ฝ๊ฒŒ ์ถ”์ ํ•˜๊ณ  ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. Deno์˜ ์•ˆ์ „์„ฑ: Deno์˜ ๊ถŒํ•œ ๋ชจ๋ธ์„ ํ™œ์šฉํ•˜์—ฌ ํ›… ์Šคํฌ๋ฆฝํŠธ์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

deno-task-hooks๋Š” ์ž‘์€ ํŒจํ‚ค์ง€์ด์ง€๋งŒ, Git๊ณผ Deno๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ํŒ€์˜ ๊ฐœ๋ฐœ ๊ฒฝํ—˜์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ ํ’ˆ์งˆ ์œ ์ง€์™€ ๊ฐœ๋ฐœ ์›Œํฌํ”Œ๋กœ์šฐ ์ž๋™ํ™”๋ฅผ ์œ„ํ•ด ํ•œ๋ฒˆ ์‚ฌ์šฉํ•ด ๋ณด์„ธ์š”!

ํŒจํ‚ค์ง€๋Š” JSR์—์„œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, GitHub์—์„œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”ผ๋“œ๋ฐฑ๊ณผ ๊ธฐ์—ฌ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜Š

Read more โ†’
0

Data analysis in Jupyter notebooks with... TypeScript?! ๐Ÿ˜ฑ
โœ… using `fetch` and other web standards
โœ… fast dataframes with nodejs-polars
โœ… easy charts with @observablehqObservable
โœ… rich interactive UIs with JavaScript

Learn more in this detailed walkthrough ๐Ÿ‘‡
deno.com/blog/exploring-art-wi

0
0

Looking for CMS advice

Hey Web devs!

Do you have any suggestions, tips, opinions, dos, donโ€™ts about headless CMSes?

I have a growing list of small/mid non-profits and collectives asking for my help to (re)make their website. I totally want to help, but I donโ€™t have much time, especially considering that they generally have little or no fundingโ€”I would most definitely point them to @VillageOneCoopVillage One Cooperative, otherwise.

Therefore, I want a super simple and replicable solution where I can copy-paste most of the code, while providing them with a stable, fast, and modern solution. I had a look at the Headless CMS section in the Jamstack website, but I need opinions from people who actually used some of that software already.

Needs

  • I want to code and configure everything using @eleventyEleventy ๐ŸŽˆ v3.0.0
  • Admin interface () for the client to add pages and write posts
  • Static website in the front-end
  • Simple and reliable CI/CD
  • No/minimal maintenance after the first setup
  • Self-hostable (I was taking this for granted so much that I forgot to write it)
  • If it requires forge integration, it should support

Nice to have

  • Possibly using , not
  • Allowing the client to customize a bit their website through the admin interface, with a GUI
  • CMS app packaged on @yunohostYunoHost :neopossum_box:
  • No CMS vendor lock-in
  • Iโ€™d love to write as little JavaScript as possible

Absolutely not

Please, boost this and ask around! Links to videos, tutorials, and resources are welcome.

People whose perspective I would really value: @zachleatZach Leatherman :11ty: @harryfkHarry Keller @deno_landDeno @jaredwhiteJared โ€œIndie Social Webโ€ White @vanillawebThat HTML Blog & The Spicy Web @stefanStefan Bohacek @mxbckMax Bรถck @WeirdWriterRobert Kingett @deadsuperheroSean Tilley (Sorry if I am spamming you!)

0
0
0