Hashtag

#TypeScript

1,180 posts tagged with this hashtag.

@toxi@mastodon.thi.ng

So the upcoming NPM publish token changes are a potential lock-out scenario for people who're not using CI-based "Trusted Publishing" (TP) and cannot switch to "Staged Publishing" (SP) for reasons of practicality or feasibility.

github.blog/changelog/2026-07-

The first approach (TP) requires a compatible CI platform (currently only Github, Gitlab or CircleCI supported), the latter requires manual approvals by a human, for each single publishing attempt... Both approaches are seemingly per-package solutions only, meaning for a full release of my thi.ng/umbrella monorepo I'd either have to use one of the three CI platforms above and manually fill out 216 forms (one per package) to register each package for TP. Alternatively, for SP I'd have to manually approve (with 2FA) each staged package (also up to 200+ times). No batch process/approval workflows mentioned or envisioned! Just who are these people making plans like this?!

If this proposal doesn't change, then it means I (and others in similar situations) won't be able to publish my projects anymore after January 2027, when this all is planned to come into force. End of the road! Open source enclosed at the point of publishing by monopolistic infrastructure...

I understand security is important, but these problems should (MUST!) be approached & solved differently. It's simply unreasonable to force developers to figure out how to re-adapt their release tooling every few months toward ever tighter and increasingly hostile decision-making on NPM's end, without any choice in the matter...

If you can, please contribute your views to the discussion on Github:
github.com/orgs/community/disc

github.com

Upcoming changes to npm 2FA-bypass granular access tokens (GATs) · community · Discussion #201329

Alongside the npm v12 release, we're beginning to phase out the most sensitive uses of npm granular access tokens (GATs) that are configured to bypass 2FA. This post explains what's changing, when,...

@toxi@mastodon.thi.ng

So the upcoming NPM publish token changes are a potential lock-out scenario for people who're not using CI-based "Trusted Publishing" (TP) and cannot switch to "Staged Publishing" (SP) for reasons of practicality or feasibility.

github.blog/changelog/2026-07-

The first approach (TP) requires a compatible CI platform (currently only Github, Gitlab or CircleCI supported), the latter requires manual approvals by a human, for each single publishing attempt... Both approaches are seemingly per-package solutions only, meaning for a full release of my thi.ng/umbrella monorepo I'd either have to use one of the three CI platforms above and manually fill out 216 forms (one per package) to register each package for TP. Alternatively, for SP I'd have to manually approve (with 2FA) each staged package (also up to 200+ times). No batch process/approval workflows mentioned or envisioned! Just who are these people making plans like this?!

If this proposal doesn't change, then it means I (and others in similar situations) won't be able to publish my projects anymore after January 2027, when this all is planned to come into force. End of the road! Open source enclosed at the point of publishing by monopolistic infrastructure...

I understand security is important, but these problems should (MUST!) be approached & solved differently. It's simply unreasonable to force developers to figure out how to re-adapt their release tooling every few months toward ever tighter and increasingly hostile decision-making on NPM's end, without any choice in the matter...

If you can, please contribute your views to the discussion on Github:
github.com/orgs/community/disc

github.com

Upcoming changes to npm 2FA-bypass granular access tokens (GATs) · community · Discussion #201329

Alongside the npm v12 release, we're beginning to phase out the most sensitive uses of npm granular access tokens (GATs) that are configured to bypass 2FA. This post explains what's changing, when,...

@toxi@mastodon.thi.ng

Another release cycle this AM:

  • fixed yesterday's thi.ng/geom-io-obj stream parser update to also support (aka the modern IE6-like browser problem child), which in the release notes for Safari v26.4 claims[1] that ReadableStream can (finally) be iterated via for await(...) syntax, but then turns out it's still only planned for v27 [2]... 🙄
  • added async versions of all timing & benchmarking functions in thi.ng/bench to support benchmarking async functions

[1] webkit.org/blog/17862/webkit-f
[2] developer.mozilla.org/en-US/do

developer.mozilla.org

ReadableStream - Web APIs | MDN

The ReadableStream interface of the Streams API represents a readable stream of byte data. The Fetch API offers a concrete instance of a ReadableStream through the body property of a Response object.

@frontenddogma@mas.to
@toxi@mastodon.thi.ng

New release(s): Updated the thi.ng/geom-io-obj OBJ mesh parser to support stream parsing using async iterables. This allows direct piping fetch() responses to the parser.

const response = await fetch(MODEL_URL);
const objModel = await parseOBJFromStream(response.body);

Also polished and published a related small example project for it (incl. arcball camera controller, which had an update too):

Demo (Click & drag to rotate view, touchpad/mousewheel to zoom):
demo.thi.ng/umbrella/webgl-obj/

Source:
codeberg.org/thi.ng/umbrella/s

Alternatively to stream parsing, there's also a generator/co-routine based version. This can be used standalone or together with thi.ng/fibers to better control the time slicing behavior when parsing large model files (tens or hundreds of MB) and so gives fine-grained control to avoid blocking the main UI thread:

import { timeSlice } from "@thi.ng/fibers";

const response = await fetch(MODEL_URL);
const src = await response.text();
// parse in 10 millisecond time slices
const model = await timeSlice(parseOBJGenerator(src), 10).run().promise();

More background info & discussion for those interested:
codeberg.org/thi.ng/umbrella/p

Screenshot of the linked demo project, showing a gray Lambert-shaded Stanford bunny on light blue background.
ALT text

Screenshot of the linked demo project, showing a gray Lambert-shaded Stanford bunny on light blue background.

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@joonnot@hackers.pub

TypeScript(이하 타입스크립트)의 타입 시스템만으로 한국어 문법을 표현하는typed-korean을 만들면서 자모 분해와 조합을 테이블로 미리 생성해두고 사용하는 것이 계속 신경쓰여 이번에 개선 작업을 진행해보았다.

사실 이 모든 불행은 한글의 완성형 음절은 단일 코드 포인트로 표현되지만, 타입스크립트의 타입 시스템에서는 코드포인트 산술을 지원하지 않기 때문에 일어난 일이었다. 예를 들어, "먹"(U+BA39)이라는 글자를 템플릿 리터럴 타입(Template literal type)으로 아무리 쪼개봐야 "ㅁ" + "ㅓ" + "ㄱ"으로 갈라지지 않는다. 당연하지만 Uppercase 같은 intrinsic 타입도 유니코드 정규화(NFD)는 지원하지 않는다.

즉, 음절 <> 자모 매핑은 반드시 어딘가에 존재해야 했고 손으로 쓸게 아니라면 이런 경우 항상 코드 생성이 대체로 옳고 이번에도 그랬다.

지금까지는 등록된 동사나 명사 기준으로 어휘에서 필요한 엔트리만 생성하는 방식을 사용했었다. 아무래도 완성형 한글을 전부 생성하기엔 양도 많거니와 불요한 데이터가 많을 것이라는 생각에 테이블을 작게 유지하려는 의도 때문이었는데, 시간이 지나 다시 확인해보니 숨은 비용이 두 개나 있었다.

  1. 코드 생성 스크립트가 활용 엔진의 복제본이 됨
  2. 어휘의 단일 진실 공급원(Source of Truth)이 두개가 됨

예를 들어 어떤 초성_중성_종성 조합이 필요한지 알아내려면 각 어간의 활용을 시뮬레이션해야 한다. 모음 조화/축약, ㄹ탈락, ㅂ/ㄷ/ㅅ/ㅎ/르 불규칙 등 타입 레벨로 구현한 규칙을 런타임 코드로 한 번 더 작성한 셈이다. 타입 엔진에 규칙을 추가할 때마다 시뮬레이터도 고쳐야 하고, 빠뜨리면 의문의 never가 튀어나오는 등의 문제가 발생할 수 있었다.

또한, 기존 코드 구조에서 어휘는 scripts/vocabulary.tssrc/vocabulary/에 어휘를 정의했어야 했는데 이 자체로 이미 중복이었다. 만약 src에만 동사를 추가하면 조용히 깨지게 된다.

앞서 언급했던 것 처럼 테이블을 작게 유지한 이유는 컴파일 비용을 줄이기 위함이었다. 하지만 지레짐작만 하고 실제로 측정하지는 않아서 실제 비용이 어떻게 되는지 확인을 해보았고, 측정은 한글 음절 전체 11,172자 분해 테이블과 조합 테이블을 실제로 생성해서 tsc --extendedDiagnostics를 실행하는 방식으로 측정했다.[1]

구성 Check time 메모리
현재 프로젝트 전체 (baseline) 0.12s 136MB
전체 JamoTable 11,172개 + ComposeTable 1,995개 0.50s 199MB

프로퍼티 이름 조회 자체는 Map 기반이라 엔트리 수와 무관하게 O(1)이지만, 파일을 파싱하고 심볼 테이블을 구성하는 비용은 엔트리 수에 비례해서 증가한다. 다만 그 비례 상수가 작아서(11,172개 기준 +0.4초) 실용적으로는 감내할 만한 수준이었다.

조합 테이블은 더 좋은 발견이 있었는데, 활용 엔진이 음절에 삽입하는 종성은 결국 ㄴ, ㄹ, ㅂ, ㅆ(+null)[2] 다섯 슬롯(현재 4개 활성 + 예약)이다.[3] 그러니 19초성 × 21중성 × 5종성 = 1,995개를 무조건 다 생성하면 시뮬레이터 200줄을 통째로 제거할 수 있다.

테이블 뒤집기

하지만 전체 테이블로 전환하고 측정해보니까 tsc 메모리가 136MB에서 479MB로 증가한 것을 확인했고, 이는 사전 벤치마크(+60MB)보다 훨씬 커진 수치다. 참고로 사전 벤치마크의 JamoTable도 지금과 동일한 { 초; 중; 종 } 객체 값 형태였다 — 차이는 테이블이 아니라 측정 범위로, 사전 벤치마크는 테이블과 조회 몇 개만 있는 단독 파일이었지만 프로젝트에서는 활용 엔진과 타입 테스트가 이 무거운 객체 타입들을 대량으로 인스턴스화하면서 비용이 증폭됐다. 프로파일링 결과 범인은 테이블 엔트리 수가 아니라 값의 모양이었다.

"먹": { 초: "ㅁ"; 중: "ㅓ"; 종: "ㄱ" }을 예시로 생각해보면 이 값 하나하나가 tsc 입장에서는 자기만의 심볼 테이블을 가진 익명 객체 타입인데 문제는 그게 11,172개가 있다는 것이다.

지금은 제거되었지만, 완성형 한글 음운 구조를 조회하기 위해 JamoTable이라는 테이블을 두었었고 아래와 같은 형태였다.

JamoTable
 "가": { 초: "ㄱ"; 중: "ㅏ"; 종: null } 
 "각": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄱ" }
 "갂": { 초: "ㄱ"; 중: "ㅏ"; 종: "ㄲ" }
 ...
 "힣": { 초: "ㅎ"; 중: "ㅣ"; 종: "ㅎ" }

음절 -> 자모 객체로 표현하면 총 비용은 객체 타입 11,172개(각각 심볼 테이블 + 멤버 3개)가 된다. 하지만 자모 -> 그 자모를 가지는 음절의 유니언(union)으로 표현하면 이 비용을 줄일 수 있다. 이렇게 하면 프로퍼티 심볼이 11,172개에서 68개로 줄고, 음절 리터럴 타입은 어차피 tsc에서 intern하기 때문에 union 멤버로 3번 참조돼도 추가 비용이 거의 없을 것이라 생각했다.

type ChoTable = { "": "" | "" | /* 588개 */; /* 19키 */ };
type JungTable = { "": /* 532개 */; /* 21키 */ };
type JongTable = { NULL: /* 399개 */; "": /* 399개 */; /* 28키 */ };

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];

type Decomp<C extends string> = {
: Find<ChoTable, C>;
: Find<JungTable, C>;
: Find<JongTable, C> extends "NULL" ? null : Find<JongTable, C>;
};

이렇게 타입을 정의하면 매핑은 다음과 같이 표현된다:

ChoTable (19개)
"ㄱ": "가" | "각" | ... (588개)
"ㄲ": ...
...
"ㅎ": ...

JungTable (21개)
"ㅏ": "가" | "낙" | ... (532개)
...
"ㅣ": ...

JongTable (28개)
NULL: "가" | "개" | ... (399개)
"ㄱ": ...
...
"ㅎ": ...

이렇게 하면 "먹"이라는 문자열 리터럴 타입은 tsc 내부에서 한 번만 만들어지고, 세 union이 전부 그 하나를 가리킨다. 객체 타입 11,172개와 프로퍼티 심볼 11,172개가 통째로 사라지고, 남는건 어차피 만들어야 했던 리터럴 타입들 뿐이다.

조회는 mapped type으로 뒤집으면 그만이다.

type Find<T, C extends string> =
  { [K in keyof T]: C extends T[K] ? K : never }[keyof T];
// Find<ChoTable, "먹"> = "ㅁ"

키 68개에 대한 union 멤버십 검사인데, 생각보다 빠르게 측정이 되었다.

진단 객체 값 테이블 역방향 union 감소
Check time 0.92s 0.26s 72%
Memory 479MB 188MB 61%

추가로 기존에 받침 없는 음절을 표현하기 위해 OpenSyllable이라는 유니언 타입을 두었었는데[4] 이 변경으로 인해 굳이 유지할 필요도 없어졌고, 최종적으로 처음 136MB 대비 +50MB 수준으로 전체 한글 음절을 커버하게 되었다.

Union도 비싸다

사실 문자열 리터럴 타입은 길이와 무관하게 타입 객체 1개로 취급할 수 있기 때문에 union을 통째로 한 줄짜리 문자열로 합쳐버리면 더 줄일 수 있다.

예를 들어, 다음과 같이 표현하면 union의 맴버는 한 음절에 대해 588개 씩 유지를 해야 한다.

"ㄱ": "가" | "각" | "갂" | ...

하지만 `"ㄱ": "가각갂갃간갅..." 처럼 표현한다면 한 음절에 대해 문자열 리터럴을 한개만 들고 있어도 된다. 또한 이 경우 음절이 전부 한 글자라 부분문자열 매칭이 곧 멤버십 검사가 된다.

type Find<T, C extends string> =
  { [K in keyof T]: T[K] extends `${string}${C}${string}` ? K : never }[keyof T];

사실 이렇게 하면 함정이 하나 있는데, 한글이 아닌 입력에서 Findnever를 반환할 때의 처리다. Find의 결과를 소비하는 쪽이 이런 형태였는데:

type Decomp<C extends string> =
  Find<ChoTable, C> extends infer Cho extends string
    ? {: Cho; /* ... */ }
    : never;

never는 모든 타입에 할당 가능하기 때문에 never extends infer Cho extends string은 참 분기로 빠지고, Decomp<"A">가 기대했던 never가 아니라 { 초: never; ... }가 되어버린다. 실제로 측정 중에 밟은 함정이다. 그래서 [Find<...>] extends [never] ? never : ...처럼 튜플 감싸기가 필수로 들어가야 한다.

이렇게 수정하고 tsc --extendedDiagnostics로 측정한 결과는 다음과 같이 나왔다.

측정 변경 전 변경 후 변화
생성 파일 263KB 99KB -62%
Memory 188MB 177MB -6%
Check time 0.26s 0.26s 동일

파일은 거진 3분의 1로 줄었는데 메모리는 11MB밖에 안 줄었다. 테이블 단독 벤치마크(테이블 + 조회 몇 개만 있는 단독 파일)에서는 극적이었는데:

구성 (단독 파일) Memory baseline 대비
빈 파일 (baseline) 80MB
역방향 union 테이블 104MB +24MB
문자열 blob 테이블 81MB +1.4MB

프로젝트 전체에서는 이미 테이블이 지배적인 비용으로 작용하지 않기 때문이 아닌가 싶다. 남은 ~40MB는 조회나 lib 타입 체크 같은 기저 비용이라 여기서 더 뭔가를 줄이는건 불필요해보였고 딱히 생각도 나지 않아 이 정도로 만족하기로 했다.

최종 스코어보드. 어휘 기반 최소 테이블에서 출발해 세 단계를 거쳤다.

단계 Check time Memory 커버리지
어휘 기반 (원점) 0.12s 136MB 등록 어휘만
전체 테이블 (객체 값) 0.92s 479MB 11,172음절 전체
역방향 union 0.26s 188MB
문자열 blob 0.26s 177MB

  1. 물론 마우스를 올려 hover tooltip을 렌더링하거나 자동완성 목록을 나열하는 경우와 같은 체감 성능은 해당 명령으로 측정하기엔 한계가 명확함. ↩︎

  2. 받침 없이 재조합 ↩︎

  3. 정확히 은 종성으로 삽입되지 않고, 향후 관형형 지원을 위해 여유분으로 남겨둔 상태다. / 불규칙의 Compose<"르", ...>에서 은 초성이고 현재 지원 어미에서도 관형형 -(으)ㄹ는 미구현 상태임. ↩︎

  4. JongTable["NULL"] 타입으로 표현됨. ↩︎

@teleclimber@social.tchncs.de

Turns out it wasn't 7, it was TS6. I accidentally upgraded to TS7 today when I upgraded all packages for the ds-dev frontend and yeah, no workie.

"It’s worth calling out that workflows that use Vue, MDX, Astro, Svelte, and others will likely not yet be able to leverage TypeScript 7."

devblogs.microsoft.com/typescr

devblogs.microsoft.com

Announcing TypeScript 7.0 - TypeScript

Today we are proud to announce the availability of TypeScript 7, a 10x faster native port of TypeScript! Since its early days, TypeScript has promised to

@teleclimber@social.tchncs.de

Spent nearly two hours upgrading Dropserver's frontend packages for ds-host. Between TypeScript 7 and Tailwind 4 it was a mess. What a glorious waste of time.

Tailwind was the biggest problem. Gah I am so over it. Want to go back to native CSS with minimal processing tooling.

@pcdevil@mastodon.social

👋 Hi, I'm looking for work!

🚀 I am...
- a detail oriented senior engineer with 15 years of experience
- proficient with & , , , TDD
- experienced with , Ember.js, GCP, Terraform

🔎 I'm looking for:
- a collaborative environment between eng + product & design teams
- a based (onsite) or a Germany / EU-based (remote) company
- ability to learn and grow

🚫 no crypto, big oil, gambling, gen-ai, web3

🙇 boost appreciated!

@pcdevil@mastodon.social

👋 Hi, I'm looking for work!

🚀 I am...
- a detail oriented senior engineer with 15 years of experience
- proficient with & , , , TDD
- experienced with , Ember.js, GCP, Terraform

🔎 I'm looking for:
- a collaborative environment between eng + product & design teams
- a based (onsite) or a Germany / EU-based (remote) company
- ability to learn and grow

🚫 no crypto, big oil, gambling, gen-ai, web3

🙇 boost appreciated!

@singingwolfboy@fosstodon.org

I'm getting ready to post a new module on , but the module is written in . Do I need to compile it to JavaScript before uploading it to npm? I know that recent versions of Node can run `*.ts` files directly, stripping types automatically, but I'm not sure if that means I can upload the `*.ts` files directly to npm these days.

It's my first time publishing a library written in TS. Can anyone give me some guidance? Happy to share the actual code, if that would help.

@hongminhee@hollo.social

Upyo 0.5.0 is out: a cross-runtime email library for and , one Transport API across SMTP, JMAP, Mailgun, SendGrid, SES, Resend, Plunk, and now Lettermint.

This release makes failed sends structured (category, retryable, HTTP status, Retry-After) instead of just a string, adds a retry transport with backoff and jitter, and brings OAuth 2.0 to SMTP for Gmail and Outlook.

https://github.com/dahlia/upyo/discussions/29

github.com

Upyo 0.5.0: Structured errors, automatic retries, and OAuth 2.0 · dahlia/upyo · Discussion #29

Upyo is a cross-runtime email library for JavaScript that provides a unified API for sending email across Node.js, Deno, Bun, and edge functions. It supports SMTP, JMAP, and providers such as Mailg...

@hongminhee@hollo.social

Upyo 0.5.0 is out: a cross-runtime email library for and , one Transport API across SMTP, JMAP, Mailgun, SendGrid, SES, Resend, Plunk, and now Lettermint.

This release makes failed sends structured (category, retryable, HTTP status, Retry-After) instead of just a string, adds a retry transport with backoff and jitter, and brings OAuth 2.0 to SMTP for Gmail and Outlook.

https://github.com/dahlia/upyo/discussions/29

github.com

Upyo 0.5.0: Structured errors, automatic retries, and OAuth 2.0 · dahlia/upyo · Discussion #29

Upyo is a cross-runtime email library for JavaScript that provides a unified API for sending email across Node.js, Deno, Bun, and edge functions. It supports SMTP, JMAP, and providers such as Mailg...

@hongminhee@hollo.social

Upyo 0.5.0 is out: a cross-runtime email library for and , one Transport API across SMTP, JMAP, Mailgun, SendGrid, SES, Resend, Plunk, and now Lettermint.

This release makes failed sends structured (category, retryable, HTTP status, Retry-After) instead of just a string, adds a retry transport with backoff and jitter, and brings OAuth 2.0 to SMTP for Gmail and Outlook.

https://github.com/dahlia/upyo/discussions/29

github.com

Upyo 0.5.0: Structured errors, automatic retries, and OAuth 2.0 · dahlia/upyo · Discussion #29

Upyo is a cross-runtime email library for JavaScript that provides a unified API for sending email across Node.js, Deno, Bun, and edge functions. It supports SMTP, JMAP, and providers such as Mailg...

@frontenddogma@mas.to
@hongminhee@hollo.social

2.2.0 is out!

The headline is two new packages:

@logtape/lint adds lint rules for ESLint v8/v9 (flat config), Oxlint, and Deno Lint that catch common logging mistakes before they reach production: template literal interpolation in message arguments, eager property evaluation where lazy is needed, unawaited async log callbacks, and missing meta sink configuration.

@logtape/testing gives you createLogRecorder() and domain-aware assertion helpers, replacing the hand-rolled array-sink boilerplate that every project ends up writing.

Other highlights:

  • context: true on Express/Hono/Koa/Elysia middleware handles request ID generation, x-request-id header propagation, and implicit context. One option instead of several moving parts.

  • Seven performance optimizations on the enabled-logging hot path

  • New logtape.org website

Full release notes: https://github.com/dahlia/logtape/discussions/179

github.com

LogTape 2.2.0: Lint rules, testing utilities, and request context · dahlia/logtape · Discussion #179

LogTape is a logging library for JavaScript and TypeScript that works across Deno, Node.js, Bun, and browsers. It's built around structured logging, has zero dependencies, and is designed to work a...

@hongminhee@hollo.social

2.2.0 is out!

The headline is two new packages:

@logtape/lint adds lint rules for ESLint v8/v9 (flat config), Oxlint, and Deno Lint that catch common logging mistakes before they reach production: template literal interpolation in message arguments, eager property evaluation where lazy is needed, unawaited async log callbacks, and missing meta sink configuration.

@logtape/testing gives you createLogRecorder() and domain-aware assertion helpers, replacing the hand-rolled array-sink boilerplate that every project ends up writing.

Other highlights:

  • context: true on Express/Hono/Koa/Elysia middleware handles request ID generation, x-request-id header propagation, and implicit context. One option instead of several moving parts.

  • Seven performance optimizations on the enabled-logging hot path

  • New logtape.org website

Full release notes: https://github.com/dahlia/logtape/discussions/179

github.com

LogTape 2.2.0: Lint rules, testing utilities, and request context · dahlia/logtape · Discussion #179

LogTape is a logging library for JavaScript and TypeScript that works across Deno, Node.js, Bun, and browsers. It's built around structured logging, has zero dependencies, and is designed to work a...

@hongminhee@hollo.social

2.2.0 is out!

The headline is two new packages:

@logtape/lint adds lint rules for ESLint v8/v9 (flat config), Oxlint, and Deno Lint that catch common logging mistakes before they reach production: template literal interpolation in message arguments, eager property evaluation where lazy is needed, unawaited async log callbacks, and missing meta sink configuration.

@logtape/testing gives you createLogRecorder() and domain-aware assertion helpers, replacing the hand-rolled array-sink boilerplate that every project ends up writing.

Other highlights:

  • context: true on Express/Hono/Koa/Elysia middleware handles request ID generation, x-request-id header propagation, and implicit context. One option instead of several moving parts.

  • Seven performance optimizations on the enabled-logging hot path

  • New logtape.org website

Full release notes: https://github.com/dahlia/logtape/discussions/179

github.com

LogTape 2.2.0: Lint rules, testing utilities, and request context · dahlia/logtape · Discussion #179

LogTape is a logging library for JavaScript and TypeScript that works across Deno, Node.js, Bun, and browsers. It's built around structured logging, has zero dependencies, and is designed to work a...

@hongminhee@hollo.social

2.2.0 is out!

The headline is two new packages:

@logtape/lint adds lint rules for ESLint v8/v9 (flat config), Oxlint, and Deno Lint that catch common logging mistakes before they reach production: template literal interpolation in message arguments, eager property evaluation where lazy is needed, unawaited async log callbacks, and missing meta sink configuration.

@logtape/testing gives you createLogRecorder() and domain-aware assertion helpers, replacing the hand-rolled array-sink boilerplate that every project ends up writing.

Other highlights:

  • context: true on Express/Hono/Koa/Elysia middleware handles request ID generation, x-request-id header propagation, and implicit context. One option instead of several moving parts.

  • Seven performance optimizations on the enabled-logging hot path

  • New logtape.org website

Full release notes: https://github.com/dahlia/logtape/discussions/179

github.com

LogTape 2.2.0: Lint rules, testing utilities, and request context · dahlia/logtape · Discussion #179

LogTape is a logging library for JavaScript and TypeScript that works across Deno, Node.js, Bun, and browsers. It's built around structured logging, has zero dependencies, and is designed to work a...

@haskman@functional.cafe

Announcing the June !

Our first talk is Type-level Programming in , presented by @abnv!

Like always, meet fellow FP heads, have great conversations, all skill levels welcome!

RSVP hasgeek.com/fpindia/bangalore-

hasgeek.com

Bangalore FP June 2026 meetup

Bangalore FP June 2026 meetup

@manlycoffee@techhub.social
@hongminhee@hollo.social

Optique 1.1.0 is out.

The headline is the new @optique/discover package: point it at a directory of files and it builds a full command tree, with typed handlers and help/completion included automatically.

Also new: value parsers for file sizes, CSS colors, semver strings, JSON, and KEY=VALUE pairs; seq() for ordered positional grammars; negatableFlag() for --color/--no-color patterns; async Zod/Valibot helpers.

https://github.com/dahlia/optique/discussions/834

github.com

Optique 1.1.0: Command discovery, value parsers, and ordered grammars · dahlia/optique · Discussion #834

Optique 1.1.0 is the first feature release after the stable 1.0.0 baseline. The largest addition is @optique/discover, a package for organizing larger CLIs as file-based command modules with typed ...

@hongminhee@hollo.social

Optique 1.1.0 is out.

The headline is the new @optique/discover package: point it at a directory of files and it builds a full command tree, with typed handlers and help/completion included automatically.

Also new: value parsers for file sizes, CSS colors, semver strings, JSON, and KEY=VALUE pairs; seq() for ordered positional grammars; negatableFlag() for --color/--no-color patterns; async Zod/Valibot helpers.

https://github.com/dahlia/optique/discussions/834

github.com

Optique 1.1.0: Command discovery, value parsers, and ordered grammars · dahlia/optique · Discussion #834

Optique 1.1.0 is the first feature release after the stable 1.0.0 baseline. The largest addition is @optique/discover, a package for organizing larger CLIs as file-based command modules with typed ...

@hongminhee@hollo.social

Optique 1.1.0 is out.

The headline is the new @optique/discover package: point it at a directory of files and it builds a full command tree, with typed handlers and help/completion included automatically.

Also new: value parsers for file sizes, CSS colors, semver strings, JSON, and KEY=VALUE pairs; seq() for ordered positional grammars; negatableFlag() for --color/--no-color patterns; async Zod/Valibot helpers.

https://github.com/dahlia/optique/discussions/834

github.com

Optique 1.1.0: Command discovery, value parsers, and ordered grammars · dahlia/optique · Discussion #834

Optique 1.1.0 is the first feature release after the stable 1.0.0 baseline. The largest addition is @optique/discover, a package for organizing larger CLIs as file-based command modules with typed ...

@manlycoffee@techhub.social

I have finally released version 1.0 of hyperguard library that I have written 4 years ago, but has been sitting in version 0.1, 0.2, and finally 0.3 without any update since.

Version 1 improved the API, and some refactoring was made to remove the reliance of the `any` type.

Anyways, check it out. github.com/shovon/hyperguard

github.com

GitHub - shovon/hyperguard: Supercharge your TypeScript type guards with this dead simple object validation library

Supercharge your TypeScript type guards with this dead simple object validation library - shovon/hyperguard

@v2editor@mastodon.social · Reply to v2 Editor
@v2editor@mastodon.social · Reply to v2 Editor
@toxi@mastodon.thi.ng · Reply to Eniko Fox

@eniko @TomF @Moosader If you want to go even more meta, here's the repo for a workshop I ran with design students at Augsburg uni a few years ago to build a TIC-80 inspired fantasy console ourselves:

github.com/thi-ng/fantasy-cons

Written in TypeScript, includes custom DSL, runs in the browser, includes six demos (incl. bitmap font editor). More details in readme

Animated GIF of screenshots of the six bundled demos for the custom fantasy console...
ALT text

Animated GIF of screenshots of the six bundled demos for the custom fantasy console...

@jnkrtech@treehouse.systems

I’ve come up with yet another TypeScript feature that I may make a feature request for, but which will never be accepted because it’s too niche: I want to disable implicit coercion of uninferred type variables to `unknown`.

When writing nontrivial libraries I often end up in situations where type inference can’t keep up with type checking, and manual type annotations become necessary. This is fine; if I’ve done my job right (and I usually do) the annotations can’t cause unsafe type coercions, and will give a static type error if they’re filled in wrong. I don’t think manual type annotations are that bad or a thing to minimize in general anyway.

The problem is that if the type annotation is needed on a generic parameter, and it’s left off, the parameter will be inferred as `unknown`, usually resulting in a chain reaction of unknowns percolating through multiple types, until finally I get a type error way down the line when something tries to pass an unknown into something which expects the proper type. This isn’t a source of type unsafety, but it is a terrible dev experience. It means that errors are reported far away from their source and painstaking trial and error are needed to work out the location where the annotation that will “fix” things needs to be added.

IMO TypeScript’s biggest strength is that it can be used to write extremely expressive libraries, but a lack of control over type inference massively holds this back. This is one of the cases where it shows up most infuriatingly.

@jnkrtech@treehouse.systems

Here’s my nuclear hot take:

First-class support for TypeScript in nodejs was a bad thing, because the “types as comments” approach means that the syntax of types can no longer evolve. There are plenty of features that TypeScript could add (if its authors so wished) and some of them would benefit from new keywords in type syntax.

I like TypeScript and don’t think it’s a bad language at all, but I think it could be better if it had avoided success for longer. The language is still evolving and improving but major potential avenues are now cut off.

@toxi@mastodon.thi.ng

The new version of thi.ng/geom-sdf is automatically preprocessing the vertices given for 2D polygons & polylines to remove any coincident and colinear ones (using Douglas-Peucker algorithm). This avoids some degenerate cases, but can also speed up the SDF evaluation of converted shapes in some other cases...

Thanks to @made for reporting the issue! 🙏

(To clarify: This package is for converting 2D shapes/geometries/SVG to composable SDF JavaScript/TypeScript functions, not for shader-based SDF use cases. For the latter, the thi.ng/shader-ast-stdlib package provides similar SDF functions/operators, for use with thi.ng/shader-ast and transpilation to GLSL)

Some examples:

thi.ng logo as SDF:
demo.thi.ng/umbrella/geom-sdf-

SVG smiley deformation:
demo.thi.ng/umbrella/geom-sdf-

demo.thi.ng

geom-sdf-path · @thi.ng/umbrella

@toxi@mastodon.thi.ng

Recently, at the library...

"Have you got their new book 'Silk switch system problem'?"
"No. Is that the sequel to 'Equiconnected nanosky oasis'?"
"What's that?"
"Oh, you've never read the 'Magnetic haze cycle' series? That's just too bad. It's full of cool ideas like the ultra-iridescent opcode sentinel, infraconnected division boundary, or even beige frontier mirror..."
"Dude!"
"Yeah, it's real porcelain ultra-peak! Absolutely life changing epoch omnicurve vision!"
"I did like 'Supraviolet ring department'..."
"Well, in that case, I'd recommend 'Macroluminous shimmer facet' instead. It's a good intro to all the abundant assembly craft."

In preparation for some name/passphrase generator and LLM-poisoning projects/tools, I updated my online procedural text editor to be able to export generator specs/recipes directly as TypeScript source code for easy integration into your own projects...

The above generator is here (the entire recipe is part of this super long URL):

demo.thi.ng/umbrella/procedura

More project & syntax info here:
thi.ng/proctext

thi.ng

Extensible procedural text generation engine with dynamic, mutable state, indirection, randomizable & recursive variable expansions

@toxi@mastodon.thi.ng

thi.ng/column-store is an in-memory database with customizable column types, extensible query engine, bitfield indexing for query acceleration, JSON serialization with optional RLE compression.

The new version introduces support for arbitrarily nested queries and merging of sub-query results using a choice of AND (intersection/constraint), OR (union/alternative) or NAND/NOR (negated versions) semantics.

docs.thi.ng/umbrella/column-st

Also without query nesting, each individual query term's results can be merged as union now. The previous behavior only allowed for term result intersections, with each subsequent term further narrowing the total result set. This behavior limited the types of compound queries possible and therefore required multiple separate queries and additional user effort to merge results manually. Well, no more! :)

docs.thi.ng/umbrella/column-st

Another (intentional) side effect: Since queries are defined declaratively, creating complex queries is much easier (and legible) now via composition and re-use of predefined sub-queries. The support for nesting also simplifies the creation of user-defined query DSLs (domain specific languages).

As before, for columns with bitmap indexing enabled, most of the query operators are extremely fast since only bit masks need to be combined and no actual row or column data is being visited. The latter is only necessary for predicate-based matchXXX() operators...

docs.thi.ng

@thi.ng/column-store

Documentation for @thi.ng/column-store

@heisedeveloper@social.heise.de
@ppcland@mastodon.social

Fedify 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:

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

https://fedify.dev/

@ppcland@mastodon.social
@toxi@mastodon.thi.ng

Triggered by a recent feature proposal[1], I went ahead and polished & published a closely related, already work-in-progress (but still private) feature in thi.ng/rdom to support something I call "bare lists"[2]. I've started working on this for another project last year, but needed to do more testing (which I think have sufficiently done by now).

These "bare" lists are managed reactive control components which attach items directly to the list's parent DOM element instead of first creating a wrapper/container element for the items and so avoid introducing additional nesting.

There're many use cases where this additional nesting was a real problem with the earlier approach, e.g. in containers with CSS grid or flex layout, tables, or generally situations where we want to have static & reactive list items as true siblings...

The new version of thi.ng/rdom is technically a breaking change (sorry!), but the actual changes required (for you) are tiny and purely limited to the $list() and $klist() component function calls, which are now accepting a parameter object instead of positional args for the different possible behaviors. Of course, lists with item wrapper elements can still be created too, just as before (but via new args).

I've updated & tested all existing examples impacted by this change and also created a new fully commented example project (example #187) to illustrate these "bare" lists in situ (check the DOM inspector to see the shallow structure and how updates are applied):

Demo:
demo.thi.ng/umbrella/rdom-bare

Source code:
codeberg.org/thi.ng/umbrella/s

[1] github.com/thi-ng/umbrella/discussions/562
[2] My use of "list" here is generic, not limited to <ul> or <ol>...

Screenshot of the linked example project, showing a grid of red & blue boxes with randomly chosen name. Further below is a table of the same items.
ALT text

Screenshot of the linked example project, showing a grid of red & blue boxes with randomly chosen name. Further below is a table of the same items.

@jobsfordevelopers@mastodon.world
@jnkrtech@treehouse.systems

What are people’s tools of choice for generating static documentation for TypeScript? Looking for something that will create linked markdown files based on classes with TSDoc annotations on all of the methods.

@pcdevil@mastodon.social

👋 Hi, I'm looking for work!

🚀 I am...
- a detail oriented senior engineer with 15 years of experience
- proficient with & , , , TDD
- experienced with , Ember.js, GCP, Terraform

🔎 I'm looking for:
- a collaborative environment between eng + product & design teams
- a based (onsite) or a Germany / EU-based (remote) company
- ability to learn and grow

🚫 no crypto, big oil, gambling, gen-ai, web3

🙇 boost appreciated!

@jnkrtech@treehouse.systems · Reply to jnkrtech

I would describe a significant number of ESLint rules as primarily passive-aggressive.

I never want to see no-explicit-any enabled. If I use `any` it’s because I have a good reason. It’s obvious that something unsafe is happening! I used the keyword that makes unsafe things happen! Putting an eslint-ignore above it is redundant. The best explanation I have for why someone might enable this rule is that they want to annoy other devs who they feel are over-using unsafe patterns, but don’t want to engage in a productive conversation about this.

Want to know a great rule? no-unsafe-type-assertion. Sometimes `as` is safe and sometimes it is not. This is exactly when it should be required to add a comment, drawing attention to unsafety when it might slip by unnoticed.

ESLint configurations should assume good intent. I want rules that make invisible problems visible, not rules which nag other devs for not writing code in my exact style. Approximating a neutral third party via a blessed tool configuration is not a substitute for healthy communication.

@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@hongminhee@hollo.social

Every library I maintain uses Twoslash. I still haven't regretted it, even when Fedify's docs take nearly ten minutes to build. That wait is annoying. I keep paying it.

For a TypeScript library, the type signature often does most of the explaining. I used to write sentences describing what a function returns. Now I'd rather let show the compiler's answer inline. That removes one common way my docs used to go stale.

twoslash.netlify.app

Twoslash

Markup for generating rich type information in your documentations ahead of time.

@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world
@jnkrtech@treehouse.systems

It feels like there should be a counterpart to linked lists, which pre-compute their right fold for some given function and store it in each cons cell. For the most basic case, imagine that a list always knows its length, as a constant time operation. It seems odd to make a list always know this one particular thing, and it seems odd to not have a list which has this ability without requiring users to create an extra custom wrapper.

What would such a thing be called? FoldList? AmortizedList? I’m imagining (TypeScript) `AmoList<{length: number}, T>` being the type of a list of Ts that computes its length, and that leftmost type parameter being dictated by the fold functions that are passed into the list’s constructor.

Has anyone seen examples of this before?

@toxi@mastodon.thi.ng

🚀 — Just pushed the new version of thi.ng/hiccup-carbon-icons (now a much larger collection of 2200+ icons, mentioned yesterday[1]) and some other smaller updates/additions to other packages...

This is the last release before switching all packages to the recently released TypeScript 6.0, support for which will likely require some restructuring & refactoring and hopefully will be less painful than it might look so far (I'm also waiting for some dependencies to update their TS type definitions, which are currently breaking, e.g. github.com/serialport/node-ser, used for thi.ng/axidraw)

I also added some new async operators for thi.ng/transducers-async to simplify some stream processing tasks (e.g. collecting and/or consuming stdout/stderr of a child process by rechunking the stream for line-based processing), for example:

```
import { rechunk } from "@thi.ng/transducers-async";
import { spawn } from "child_process";

// launch child process
const child = spawn("ls", ["-l"]);

// split child's stdout into single lines
for await(let line of rechunk(/\r?\n/g, child.stdout)) {
console.log("output", line);
}
```

[1] mastodon.thi.ng/@toxi/11642201

mastodon.thi.ng

Karsten Schmidt (@toxi@mastodon.thi.ng)

Attached: 1 image It's been 4.5 years since I last updated the https://thi.ng/hiccup-carbon-icons collection and synced it with the upstream repo, i.e. IBM's Carbon design system. Spent a few hours today updating the icons to the current version, filtering out a hundred unnecessary ones (e.g. obsolete brand logos, IBM product/service related icons etc.) and updated the converter & code generator[1] to produce more concise outputs, then manually cleaned up the structure for dozens of them (in addition to optimizing/minimizing the SVG sources via the `svgo` CLI). The new set has exactly 2222 icons in https://thi.ng/hiccup format (SVG expressed as nested JS arrays). These icons can be used in any context where https://thi.ng/hiccup format is supported, i.e. both for static HTML/SVG generation and/or interactive scenarios. A contact sheet of the full collection (the attached image only shows a tiny selection of this): https://demo.thi.ng/umbrella/hiccup-carbon-icons/ For tree-shaking purposes each icon is defined in its own source file, e.g. the Mastodon logo can be then imported like so: `import { MASTODON } from "@thi.ng/hiccup-carbon-icons"` Example icon definition: https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/hiccup-carbon-icons/src/logo-mastodon.ts The new version is still unreleased, but the readme already contains up-to-date information and small usage examples (incl. links to live example projects to see usage in situ). [1] Converter/codegen tool: https://codeberg.org/thi.ng/umbrella/src/branch/develop/packages/hiccup-carbon-icons/tools/convert-icons.ts #ThingUmbrella #UI #Design #SVG #Icons #OpenSource

@jobsfordevelopers@mastodon.world
@jobsfordevelopers@mastodon.world

Commander.jsの.conflicts().implies()は、排他的な組み合わせをランタイムではちゃんと検出してくれます。

でも.opts()の型は賢くならず、戻り値は結局string | undefinedのままです。どのオプションが同時に使えないのかを、TypeScriptは知りません。

このズレをパーサーコンビネータでどう型に落とし込めるか、Yargsとの比較も含めて書きました。後半では、環境変数・設定ファイル・対話プロンプトまで同じ型保証を広げる話もしています。

https://zenn.dev/hongminhee/articles/6ba2a6247ec0c4

zenn.dev

Commander.jsの.conflicts()が型に反映されない問題をパーサーコンビネータで解決する——Optique 1.0

Commander.jsの.conflicts().implies()は、排他的な組み合わせをランタイムではちゃんと検出してくれます。

でも.opts()の型は賢くならず、戻り値は結局string | undefinedのままです。どのオプションが同時に使えないのかを、TypeScriptは知りません。

このズレをパーサーコンビネータでどう型に落とし込めるか、Yargsとの比較も含めて書きました。後半では、環境変数・設定ファイル・対話プロンプトまで同じ型保証を広げる話もしています。

https://zenn.dev/hongminhee/articles/6ba2a6247ec0c4

zenn.dev

Commander.jsの.conflicts()が型に反映されない問題をパーサーコンビネータで解決する——Optique 1.0

@hongminhee@hollo.social

I wrote about a problem that's been bugging me with .js and : .conflicts() and .implies() enforce constraints at runtime, but the type you get back is still a flat object with every field optional. The compiler has no idea which options belong together.

The post walks through what happens when you express the same constraints in the parser structure instead, and how turns that into a discriminated union where each branch carries only its own fields.

Second half covers a less obvious question: what happens when values come from env vars, config files, or prompts instead of argv, and whether the constraints should still hold across all of them.

https://hackers.pub/@hongminhee/2026/optique-10-discriminated-unions-for-cli

hackers.pub

From five optional fields to a discriminated union: CLI parsing with Optique 1.0

Traditional CLI libraries like Commander.js and Yargs often suffer from a gap between runtime validation and TypeScript type safety, where mutually exclusive options are typed as flat collections of optional fields. This disconnect forces developers to rely on manual type narrowing or risky non-null assertions, even when the underlying validator knows exactly which inputs are incompatible. Optique 1.0 addresses this by utilizing parser combinators to generate precise discriminated unions that reflect the true structure of the command-line interface. By modeling options as structural components rather than independent flags, the library ensures the compiler accurately represents available fields, effectively eliminating the need for boilerplate validation logic. The 1.0 release expands this philosophy to include environment variables, configuration files, and interactive prompts, treating all input sources as a single unified problem. It enforces consistent validation across every layer, ensuring that constraints defined for the CLI are never bypassed by values arriving from the environment or filesystem. This approach is essential for building robust, type-safe command-line tools that remain maintainable as their complexity and configuration sources grow.

@hongminhee@hackers.pub

You've probably written something like this in Commander.js.

import { Command, Option } from "@commander-js/extra-typings";

const program = new Command()
  .addOption(
    new Option("--token <token>", "API token").conflicts([
      "username", "password", "oauthClientId", "oauthClientSecret",
    ]),
  )
  .addOption(
    new Option("--username <username>", "Basic auth username").conflicts([
      "token", "oauthClientId", "oauthClientSecret",
    ]),
  )
  .addOption(
    new Option("--password <password>", "Basic auth password").conflicts([
      "token", "oauthClientId", "oauthClientSecret",
    ]),
  )
  .addOption(
    new Option("--oauth-client-id <id>", "OAuth client id").conflicts([
      "token", "username", "password",
    ]),
  )
  .addOption(
    new Option("--oauth-client-secret <secret>", "OAuth client secret")
      .conflicts(["token", "username", "password"]),
  );

program.parse();
const options = program.opts();

It compiles. It runs. Commander.js rejects --token abc --username alice with the conflict error you'd expect.

Look at what TypeScript thinks options is, though.

{
  token?: string | undefined;
  username?: string | undefined;
  password?: string | undefined;
  oauthClientId?: string | undefined;
  oauthClientSecret?: string | undefined;
}

Five independent optional fields. Nothing in that type says token, basic auth, and OAuth are three separate worlds. The .conflicts() chains are runtime instructions to a validator. They never touch the type. When your code reaches in and uses options, you still have to narrow by hand. Is token set? If not, can I assume username and password are both there? If you get that branching wrong, the compiler has nothing to say about it.

if (options.token != null) {
  useBasicAuth(options.username!);
}

The gap between the validator knows and the type knows is what pushed me to start building Optique. It was originally a side project for a CLI I was writing, and it's grown into something people use in earnest. A few days ago I tagged 1.0.0. The part that matters most to me is that the same parser structure now covers environment variables, config files, and prompts instead of stopping at argv.

I'll assume you've used Commander.js or Yargs before. I don't want to pretend they're bad; they're mature tools with real users. My goal is to show where they stop, and what's on the other side of that line.

Runtime checks aren't type-level knowledge

The obvious first objection to everything I just said is that Commander.js's .conflicts() isn't new. It's been there for years. Yargs has it too, along with .implies() on both sides. You can declare that --token conflicts with --username, and Yargs will even let you declare that --username implies --password so the two are required together. These aren't missing features.

On current versions, Commander.js 14 with @commander-js/extra-typings 14 handles the simple case correctly. Passing --token abc --username alice produces option '--token <token>' cannot be used with option '--username <username>', which is exactly the message the user needs.

Commander.js doesn't give you a type that reflects any of this, though. The Option.conflicts() method in extra-typings returns the Option instance unchanged. There's no generic parameter threading through the chain, accumulating which options are mutually exclusive with which others. So .opts() comes back as five optional fields, and if you write the snippet above, nothing stops you. The non-null assertion will be there in production, waiting for the input where the runtime let both through because they're actually compatible, or for the refactor that moves this code somewhere the invariant no longer holds.

Commander.js also has no way to mark a group of options as required together. If you pass --username alice and forget --password, Commander.js runs happily; the user gets a half-configured basic auth at best. .implies() exists, but it's about setting values (“if --free-drink is passed, set --drink to small“), not about requiring co-occurrence.

Yargs is stranger. It has .conflicts() and .implies(), and .implies() does enforce co-occurrence: --username without --password fails at runtime. But the interaction between the two gets confusing fast. I tried --token abc --username alice with both wired up. What Yargs told the user was:

Missing dependent arguments:
 username -> password

That's the .implies() talking. Yargs checks implies before conflicts, so the real issue (token and username are mutually exclusive) stays buried behind an unrelated complaint about a password the user never mentioned. If you add --password too, then you finally get the mutually-exclusive error. For the user on the receiving end, this is the kind of message that makes them file a bug against you.

The Yargs result type is worth seeing as well:

{
  [x: string]: unknown;
  oauthClientId: string | undefined;
  "oauth-client-id": string | undefined;
  // …the other options, each of them in both kebab- and camel-cased forms
}

The index signature [x: string]: unknown means any typo on a property access silently becomes unknown. I tried parsed.tokenn and TypeScript accepted it; the value came back undefined at runtime. Each option also shows up under both kebab-case and camelCase keys. None of this has anything to do with the exclusivity constraints I declared. It's just what happens when parser output is typed as a loose dictionary.

This is less about missing features than about where the features stop. Once you cross into the return type of .opts() or .parseSync(), the constraints are gone. The compiler sees whatever shape the signature promised, and that shape doesn't know what you declared.

Types that know which branch you picked

Here's the same CLI in Optique.

import { object, or } from "@optique/core/constructs";
import { constant, option } from "@optique/core/primitives";
import { string } from "@optique/core/valueparser";
import { run } from "@optique/run";

const parser = or(
  object({
    auth: constant("token" as const), 
    token: option("--token", string({ metavar: "TOKEN" })),
  }),
  object({
    auth: constant("basic" as const), 
    username: option("--username", string({ metavar: "USER" })),
    password: option("--password", string({ metavar: "PASS" })),
  }),
  object({
    auth: constant("oauth" as const), 
    clientId: option("--oauth-client-id", string({ metavar: "ID" })),
    clientSecret: option("--oauth-client-secret", string({ metavar: "SECRET" })),
  }),
);

const parsed = run(parser);

The shape of the code is different. Instead of declaring each option in isolation and then chaining constraints between them, you describe three complete parsers, one per auth method, and pass them to or(). Each branch is an object() that lists the options belonging to that branch. The constant() calls are discriminators; they don't consume input, they just tag the result.

The type parsed gets is:

  | { readonly auth: "token"; readonly token: string }
  | { readonly auth: "basic"; readonly username: string; readonly password: string }
  | { readonly auth: "oauth"; readonly clientId: string; readonly clientSecret: string }

That's a discriminated union. When you consume the parsed value, TypeScript knows which fields are available based on auth:

switch (parsed.auth) {
  case "token":
    await callApiWithToken(parsed.token);
    break;
  case "basic":
    await callApiWithBasic(parsed.username, parsed.password);
    break;
  case "oauth":
    await callApiWithOauth(parsed.clientId, parsed.clientSecret);
    break;
}

Inside the "token" case, parsed.username is a type error. Inside "basic", parsed.token is a type error. Every field inside its branch is plain string, not string | undefined, so no non-null assertions are asked for. If you add a fourth auth method next year and forget to update the switch, the compiler complains.

The runtime errors follow the parser shape too. A token-plus-username mix fails as a conflict: "--token" "abc" and "--username" "alice" cannot be used together. A basic-auth branch without its password fails as missing input: Missing option --password. No check-ordering coincidences.

I want to be clear that this idea isn't mine. Parser combinators have been a standard technique in functional programming for decades, and Haskell's optparse-applicative has been applying them to CLI parsing since 2012. TypeScript's conditional types and discriminated union inference happen to be strong enough that this style of API doesn't ask you to write types by hand. You compose parsers, and the types work out.

I started on Optique while trying to express this kind of structure in Fedify's CLI. The closest tool for the shape of problem I had was Cliffy, but it didn't fit[1]. Commander.js and Yargs couldn't express it the way I wanted either. So here we are.

CLI arguments are one place values come from; there are others

So far this example is unrealistically argv-only. Real CLIs pull some values from environment variables (GITHUB_TOKEN, DATABASE_URL, AWS_REGION), some from config files because nobody wants to retype seventeen flags on every invocation, and some from interactive prompts because secrets shouldn't sit in shell history.

On Commander.js or Yargs, each of those sources is usually a separate mechanism. Commander.js has .env() on options, which is fine for that one dimension. Config files get a separate library, or a hand-rolled loader at the top of main(). Interactive prompts are Inquirer.js, wired in somewhere. Each has its own validation path, and reconciling precedence between them is your problem.

In 1.0, Optique treats these four sources as one problem.

One parser, four sources

Take the auth example again, but think about where each value really comes from in practice. API tokens come from environment variables; nobody types GITHUB_TOKEN on the command line. Passwords should be prompted, not left in shell history. OAuth client credentials get saved to a config file because they're project-scoped and you want them versioned (the client secret less so, but let's keep the example simple).

Here's how you'd wire that up in Optique 1.0.

import { object, or } from "@optique/core/constructs";
import { constant, option } from "@optique/core/primitives";
import { string } from "@optique/core/valueparser";
import { bindEnv, createEnvContext } from "@optique/env";
import { bindConfig, createConfigContext } from "@optique/config";
import { prompt } from "@optique/inquirer";
import { runAsync } from "@optique/run";
import { z } from "zod";

const envCtx = createEnvContext({ prefix: "MYAPP_" });
const cfgCtx = createConfigContext({
  schema: z.object({
    oauth: z.object({
      clientId: z.string().optional(),
      clientSecret: z.string().optional(),
    }).optional(),
  }),
});

const parser = or(
  object({
    auth: constant("token" as const),
    token: bindEnv( 
      option("--token", string()),
      { context: envCtx, key: "TOKEN", parser: string() },
    ),
  }),
  object({
    auth: constant("basic" as const),
    username: option("--username", string()),
    password: prompt( 
      option("--password", string()),
      { type: "password", message: "Password:", mask: true },
    ),
  }),
  object({
    auth: constant("oauth" as const),
    clientId: bindConfig( 
      option("--oauth-client-id", string()),
      { context: cfgCtx, key: (c) => c?.oauth?.clientId },
    ),
    clientSecret: bindConfig( 
      option("--oauth-client-secret", string()),
      { context: cfgCtx, key: (c) => c?.oauth?.clientSecret },
    ),
  }),
);

const parsed = await runAsync(parser, { contexts: [envCtx, cfgCtx] });

The parser structure hasn't changed. It's still three branches, each an object() of required fields. What changed is that each field is now wrapped with one or more of bindEnv(), bindConfig(), and prompt(). These wrappers don't alter what a field means; they describe where to look for its value if argv didn't supply one.

Resolution order follows wrapper nesting from the inside out. Whatever the user put on the command line wins, then the environment variable, then the config file, then the prompt. If the user gave --token explicitly, MYAPP_TOKEN is ignored for this run. If they didn't but it's set in the environment, the prompt never fires. You can stack all four on a single option if you want; a common pattern is prompt(bindEnv(bindConfig(option(…), …), …), …), which gives you CLI then env then config then prompt on one value.

The inferred type is unchanged from the pure-argv version above. The branches are still discriminated by auth. Every field in the selected branch is still string, not string | undefined. The type system has no idea that some of these values took a detour through the filesystem or a TTY before they got to you.

A small related feature is fail<T>(). Sometimes a value shouldn't be exposed as a CLI flag at all; maybe it's a secret that should only come from config or env. bindConfig(fail<string>(), { … }) expresses that. The parser has no CLI surface for the field, but it still participates in the type, and it still feeds the config value into the result.

The “express constraints through structure” idea earns its keep here. Teams who've wanted this combination on Commander.js or Yargs have historically had to stitch it together: .env() here, a config loader there, an Inquirer.js block inside the action handler, then a pile of if-statements reconciling what to believe when two sources disagree. The reconciliation code is where the bugs live. bindEnv(bindConfig(…)) is that reconciliation, but written once and tested once instead of re-implemented per CLI.

Constraints that don't leak

There's a subtler problem that I didn't fully appreciate until late in the 0.x cycle. Consider this:

option("--port", integer({ min: 1024, max: 65535 }))

At the CLI, the parser rejects --port 80. Good. Now wrap it in bindEnv():

bindEnv(
  option("--port", integer({ min: 1024, max: 65535 })),
  { context: envCtx, key: "PORT", parser: integer() },
)

In 0.x, if the user left --port off and set PORT=80 in the environment, the value 80 would flow through untouched. The env-level parser here is integer() without bounds, so it accepted. The CLI-level parser's constraints never ran on values that didn't arrive via argv. Config files had the same hole: a constraint written into the CLI option could be silently bypassed by a different source.

This isn't the sort of bug that shows up in the tests you'd normally write. It shows up when somebody sets an environment variable in production and a value that should've been rejected sails through to the rest of the application.

1.0 adds a Parser.validateValue() method that fallback paths use. Environment values, config values, and defaults are now re-validated against the CLI parser's constraints on their way in. The rule is consistent: if a value wouldn't be accepted from argv, it's not accepted from anywhere else either.

I'd always described Optique as a “parse, don't validate” library. The phrase is shorthand for an approach where you don't run a separate validation pass after parsing; the parser itself rejects invalid input up front. 0.x mostly delivered on that for argv. 1.0 extends it to every source a value can enter from.

When Optique isn't the right choice

If your CLI has four flags and no subcommands, use Commander.js. You'll be done faster, your bundle will be smaller, and whoever reviews the PR won't have to learn a new mental model. Optique pays off once you have nontrivial structure: mutually exclusive groups, co-required options, values that arrive from multiple sources, subcommands with per-subcommand option sets. Below that complexity bar, its abstractions are overhead you're paying for no return.

If you have a large Commander.js codebase that works, don't port it. The path from imperative configuration to parser combinators isn't a three-hour rewrite, and the bug you introduce during the rewrite is rarely worth the cleaner types afterward. I'd reach for Optique on a new CLI, or on a new subcommand being added to an existing app, not on a retroactive migration.

If you need a specific Commander.js or Yargs plugin that does something exotic, Optique's ecosystem is smaller. I expect that to change. I shouldn't pretend it isn't smaller today.

There's a more uncomfortable question too. If your CLI is complex enough to benefit from Optique, maybe the CLI itself has too many knobs. Optique helps you build a TV remote where every button is correctly wired and no two conflict, but it doesn't ask whether the remote should have that many buttons in the first place. If you find yourself reaching for deeply nested or() trees, consider simplifying the interface before modeling it more precisely.

I think about this sometimes. Some interfaces genuinely need cockpit-level density: database admin tools, deployment pipelines, build systems. Optique is at its best when the complexity is real. When it's accumulated through feature creep, no parser library will save you.

1.0 means I can stop adding footnotes

Through most of 0.x, recommending Optique to anyone required footnotes. The env package isn't stable yet. The prompt API might change. runWithConfig is on the way out, use X for now. This constraint doesn't carry across env boundaries, so double-check. The library worked, but the surface I was asking people to commit to was moving.

That's what 1.0 changes for me. I can send someone the docs link without a page of caveats first.

Documentation is at optique.dev. The 1.0 announcement and changelog are on GitHub. Issues and discussions are the place to tell me where the sharp edges still are.


  1. Two reasons. Cliffy is Deno-only, which rules it out for a CLI that needs to ship on Node.js and Bun. And even in Deno, Cliffy's API is declarative in roughly the same way as Yargs: options and constraints are declared against a runtime validator, not composed into types. The limits we've just been walking through on Commander.js and Yargs show up in Cliffy too, in a different dialect. ↩︎

@hongminhee@hollo.social

1.0.0 is out! If you build tools with , it might be worth a look.

I started it because I wanted a TypeScript CLI parser that felt more like optparse-applicative than the usual builder-style APIs. You build up small typed parsers, compose them, and TypeScript infers the result. It handles subcommands, option dependencies, shell completion, and man pages, and it runs on , .js, and .

For 1.0 I added @optique/env, so env vars can fill in missing flags, and @optique/inquirer, so missing values can fall back to Inquirer.js prompts. I also cleaned up a lot of awkward API edges and fixed a long backlog of completion bugs across five shells.

Packages are on JSR and npm.

https://github.com/dahlia/optique/discussions/796

github.com

Optique 1.0.0: environment variables, interactive prompts, and 1.0 API cleanup · dahlia/optique · Discussion #796

Optique is a type-safe combinatorial CLI parser for TypeScript, inspired by Haskell's optparse-applicative and TypeScript's Zod. It takes a functional approach: you compose small, typed parsers int...

@jobsfordevelopers@mastodon.world
@hongminhee@hollo.social

1.0.0 is out! If you build tools with , it might be worth a look.

I started it because I wanted a TypeScript CLI parser that felt more like optparse-applicative than the usual builder-style APIs. You build up small typed parsers, compose them, and TypeScript infers the result. It handles subcommands, option dependencies, shell completion, and man pages, and it runs on , .js, and .

For 1.0 I added @optique/env, so env vars can fill in missing flags, and @optique/inquirer, so missing values can fall back to Inquirer.js prompts. I also cleaned up a lot of awkward API edges and fixed a long backlog of completion bugs across five shells.

Packages are on JSR and npm.

https://github.com/dahlia/optique/discussions/796

github.com

Optique 1.0.0: environment variables, interactive prompts, and 1.0 API cleanup · dahlia/optique · Discussion #796

Optique is a type-safe combinatorial CLI parser for TypeScript, inspired by Haskell's optparse-applicative and TypeScript's Zod. It takes a functional approach: you compose small, typed parsers int...

@hongminhee@hollo.social

1.0.0 is out! If you build tools with , it might be worth a look.

I started it because I wanted a TypeScript CLI parser that felt more like optparse-applicative than the usual builder-style APIs. You build up small typed parsers, compose them, and TypeScript infers the result. It handles subcommands, option dependencies, shell completion, and man pages, and it runs on , .js, and .

For 1.0 I added @optique/env, so env vars can fill in missing flags, and @optique/inquirer, so missing values can fall back to Inquirer.js prompts. I also cleaned up a lot of awkward API edges and fixed a long backlog of completion bugs across five shells.

Packages are on JSR and npm.

https://github.com/dahlia/optique/discussions/796

github.com

Optique 1.0.0: environment variables, interactive prompts, and 1.0 API cleanup · dahlia/optique · Discussion #796

Optique is a type-safe combinatorial CLI parser for TypeScript, inspired by Haskell's optparse-applicative and TypeScript's Zod. It takes a functional approach: you compose small, typed parsers int...

@jobsfordevelopers@mastodon.world
@debacle@framapiaf.org · Reply to Delta Chat

@delta @pixelschubsi @adbenitez

I absolutely agree, that "a cross-platform mass-user focused app with a consistent UX across the platforms" is missing desperately in the / ecosystem.

There are really good clients for Jabber, but none of them fits above description.

AFAIK, both / by @snikket_im and by @ProcessOne try to close that gap.

Still, I prefer the approach of Delta building on and , instead of or . .

@toxi@mastodon.thi.ng

Added, updated & simplified the growing collection of darkroom-related calculators and super happy how elegant and concise the code has turned out, making it super easy to add more of them in the future.

I think it's also another great, if minimal, example to illustrate how otherwise completely separate thi.ng/umbrella packages can seamlessly compose/combine to enable a reactive dataflow UI, all without the need for any virtual DOMs and/or completely over-the-top frameworks like React & co. It's also doing so via mostly JS-native data structures for declaring the UI (plain objects/arrays/iterables) and various constructs directly managing the reactive value streams, thus providing a lot more finegrained control over UI updates/timing/throttling). Any value changes done by the user only trigger specific, pin-point calculations which then result in equally specific UI updates to show new results. Any user action only ever triggers the minimum amount of work needed to reflect the new state.

Calculators:
demo.thi.ng/umbrella/darkroom-

Source code:
codeberg.org/thi.ng/umbrella/s

The attached images show the source code of the entire main app (UI root) and one of the calculators...

Ps. Please let me know if you'd like to see more of these posts in the future. I'm tempted to launch season 2 of (see link below for 30 previous mini projects/tutorials) — but since this is very time consuming to produce & document these projects/examples, and because there has been _very little feedback_ to these previous projects/posts, I first need to gauge interest... Thank you! 🫶

codeberg.org/thi.ng/umbrella#h

Commented TypeScript source code of the linked example project's main UI component
ALT text

Commented TypeScript source code of the linked example project's main UI component

TypeScript source code of the entire reactive "dilution volume" calculator module of the linked example project
ALT text

TypeScript source code of the entire reactive "dilution volume" calculator module of the linked example project

@toxi@mastodon.thi.ng

tl;dr Using thi.ng/column-store to accelerate tag intersection queries by a factor of 880x...

Working on the static website generator/export plugin for my personal knowledge tool has been one of the main projects this past month. A key part of this setup is tagging, not just simple flat keywords/categories, but actually treating tags as sets. The system doesn't just allow browsing content by a single tag, but also supports adding (or removing) tags to narrow or widen the current topic. E.g. The combination of "3d + geometry + typescript" would select only works which have all of these three tags...

In the local version of my tool there's no limit to the number of tags (and it also supports tag negation), but for the static site generation I have to limit the set size (due to combinatoric explosion) and pre-compute all possible permutations, then create HTML documents for each these individual combinations which actually produce results.

So far I'm having ~400 unique tags in use, meaning if I want to aim for a max set size of 3, there're theoretically ~64,000,000 possibilities to check[1]! For the roughly 3500 content items used for testing, a naive JS approach to filter the result array and only retain items matching the entire current permutation is so extremely slow, that I stopped the process after 3.5 minutes just for the first 250k (aka 0.4%) of the 64 million permutations, i.e. at that rate the full process would have taken ~15 hours, pretty slow for a SSG... :)

Naive approach 🫣:

```
permutation = ["3d", "geometry", "typescript"]
results.filter(item => permutation.every(tag => item.tags.includes(tag)))
```

But since I'm using thi.ng/column-store as my database, such queries can be optimized by a few magnitudes, since here these intersection queries are applied only to bitfields (explained in the pkg readme). This results in all 64+ million permutations being processed in just 62 seconds (1+ million per second). Quite the difference, i.e. ~880x faster than the above approach!

Also, of these 64 million initial possibilities, there're fewer unique ones (excluding duplicates and ignoring ordering), and currently only ~24,000 are actually producing a result. Still, that's 24,000 index pages to generate & host and it's, of course, far, far too much!

So I will have to also spend more effort curating and severely reducing the tag vocabulary, at least the subset used for the website. On the other hand, I think this system will really help with browsing this large body/archive of work much more meaningfully than the boring single-tag/category approach most websites are offering. And it will do so without any backend (other than file hosting)...

[1] Permutations = 400 + 400^2 + 400^3

thi.ng

In-memory column store database with customizable column types, extensible query engine, bitfield indexing for query acceleration, JSON serialization with optional RLE compression

@zeab@fosstodon.org

Interesting to see combinator conditions on for CLI.

This is something that's hard to do in any CLI library. Easier with typed languages, but still can be complex. Very cool to see with and their approach leveraging the type system. 😎

optique.dev/why

optique.dev

Why Optique? | Optique

Discover how Optique brings functional composition to TypeScript CLI development, enabling truly reusable parser components that other libraries can't match through configuration-based approaches.

@0x4d6165@transfem.social

I often hear people complain about nestjs and say it's "not idiomatic typescript" and it's just "spring boot in node" but I'm curious what folks who have written nestjs for a while think of it, not just the haters. And for people who don't like it, how do you structure your applications?

@0x4d6165@transfem.social

I often hear people complain about nestjs and say it's "not idiomatic typescript" and it's just "spring boot in node" but I'm curious what folks who have written nestjs for a while think of it, not just the haters. And for people who don't like it, how do you structure your applications?

@PolyWolf@treehouse.systems

As of this morning, I have been let go from my current position. 3 years of experience with / & , effectively a lot more with due to all the hobby projects. Looking for something with any of those, pretty good at learning on-the-job too, either Remote, in NYC, or on United States' east coast. Resume available upon request.

@PolyWolf@treehouse.systems

As of this morning, I have been let go from my current position. 3 years of experience with / & , effectively a lot more with due to all the hobby projects. Looking for something with any of those, pretty good at learning on-the-job too, either Remote, in NYC, or on United States' east coast. Resume available upon request.

@SocketSecurity@fosstodon.org
@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@0x4d6165@transfem.social

typescript nerds: am I missing something obvious or is this something actually missing in typescript?

So I have an array of objects that I'm trying to .map() over. Each object in the array has a field of type Foo | undefined. I want the array of all objects where the field is Foo so I can then .map() over the array with the safe assumption every object has a field with a valid Foo object. Filtering like this .filter((i) => i.foo) still results in the typing being Foo | undefined.

@jnkrtech@treehouse.systems

I’ve become convinced that using zod + a strongly-typed API client layer to share types between frontend and backend is bad, actually. It makes tight coupling way too easy, especially when trying to release backwards-compatible changes.

I’m facing my second multi-day change due to someone building on a shared model which doesn’t separate “write” types from “read” types. The result is that, without reworking a whole mess of models, I can’t add an optional property to a backend response without making a host of changes to the frontend (which should not be aware of the backend change at all). Sure, this could be avoided with care, but the ergonomics of the system push people so hard towards doing the wrong thing.

Manual DTOs are the way to go, preferably with a generated OpenAPI client for the frontend.

@nemin@ohai.social

Hi,

I'm Nemin, a programmer from Hungary. I first became interested in coding at around age eight, when my late grandfather lent me his Enterprise 128k and a wonderful little book, that taught BASIC in a way even kids could easily grasp.

I work at a multinational as a Full-Stack Engineer (#python / ).

Off-work I'm interested in , the , and a niche series from the '90. When I'm not bashing keys, I enjoy a lot.

@fabio@manganiello.eu

After Madblog, how many of you would like #ActivityPub and #Indieweb support to come to GPSTracker too?

This is an idea that I’ve been flirting with for a while.

Like many Millennials, 10-15 years ago I was into the Foursquare-mania. It was the age where pubs would offer discount to their Foursquare mayor and where people used to share their Foursquare stats and compete on how many badges they had collected.

Then Foursquare decided to pivot its platform towards the business-side instead, the check-in app was spun off into Swarm, it gradually lost users but it gained trackers, and by now I think only 1-2 of my contacts (out of >100 in the golden age) still use it.

By now I don’t think anyone has filled that gap; there isn’t any social media built around networks that share and recommend their check-ins.

#GPSTracker already supports a lot of tracking, timeline and check-in features, synchronization of geo events with mobile devices, and even stats with arbitrary aggregations (by country, time range, city, region etc.). Plus some features that Foursquare never implemented (like searching for checkins on the timeline by simply selecting an area on the map).

#Microformats already support location tags through the h-adr class, although they are rarely used. Both #Webmentions and ActivityPub could send check-in activities as permalinks to pages with those tags. And the #OpenStreetMap APIs could do the heavylifting of retrieving POIs in in a certain lat/long box.

The only hurdle would be implementing the protocols under the hood, as both the Webmentions and Pubby libraries are in #Python while #GPSTracker is in #Typescript. But it could be a good chance to start writing multi-language bindings for those libraries.

Let me know if it’s something that you would use, or even self-host, and if you know if there’s anything in the Fediverse that already fills this niche.

manganiello.eu

Fabio's Space

@fabio@manganiello.eu

After Madblog, how many of you would like #ActivityPub and #Indieweb support to come to GPSTracker too?

This is an idea that I’ve been flirting with for a while.

Like many Millennials, 10-15 years ago I was into the Foursquare-mania. It was the age where pubs would offer discount to their Foursquare mayor and where people used to share their Foursquare stats and compete on how many badges they had collected.

Then Foursquare decided to pivot its platform towards the business-side instead, the check-in app was spun off into Swarm, it gradually lost users but it gained trackers, and by now I think only 1-2 of my contacts (out of >100 in the golden age) still use it.

By now I don’t think anyone has filled that gap; there isn’t any social media built around networks that share and recommend their check-ins.

#GPSTracker already supports a lot of tracking, timeline and check-in features, synchronization of geo events with mobile devices, and even stats with arbitrary aggregations (by country, time range, city, region etc.). Plus some features that Foursquare never implemented (like searching for checkins on the timeline by simply selecting an area on the map).

#Microformats already support location tags through the h-adr class, although they are rarely used. Both #Webmentions and ActivityPub could send check-in activities as permalinks to pages with those tags. And the #OpenStreetMap APIs could do the heavylifting of retrieving POIs in in a certain lat/long box.

The only hurdle would be implementing the protocols under the hood, as both the Webmentions and Pubby libraries are in #Python while #GPSTracker is in #Typescript. But it could be a good chance to start writing multi-language bindings for those libraries.

Let me know if it’s something that you would use, or even self-host, and if you know if there’s anything in the Fediverse that already fills this niche.

manganiello.eu

Fabio's Space

@hongminhee@hollo.social

Optique just crossed 600 GitHub stars!

For those unfamiliar: is a parsing library for that takes a parser combinator approach, inspired by Haskell's optparse-applicative. The core idea is “parse, don't validate”—you express constraints like mutually exclusive options or dependent flags through types, and TypeScript infers the rest automatically. No runtime validation boilerplate needed.

It started as something I built out of frustration while working on Fedify, an ActivityPub framework, when no existing CLI library could express the constraints I needed in a type-safe way. Apparently I wasn't the only one who felt that way.

Thank you all for the support.

https://github.com/dahlia/optique

Screenshot of the GitHub repository page for dahlia/optique. The repository header shows a fork count of 7 and a star count of 601. The navigation tabs show Code, Issues (312), Pull requests, Discussions, Actions, and Security. The current branch is main, with the latest commit hash 9b28b85 made 18 minutes ago. The About section on the right reads “type-safe combinatorial CLI parser for TypeScript” with a link to optique.dev.
ALT text

Screenshot of the GitHub repository page for dahlia/optique. The repository header shows a fork count of 7 and a star count of 601. The navigation tabs show Code, Issues (312), Pull requests, Discussions, Actions, and Security. The current branch is main, with the latest commit hash 9b28b85 made 18 minutes ago. The About section on the right reads “type-safe combinatorial CLI parser for TypeScript” with a link to optique.dev.

@hongminhee@hollo.social

Optique just crossed 600 GitHub stars!

For those unfamiliar: is a parsing library for that takes a parser combinator approach, inspired by Haskell's optparse-applicative. The core idea is “parse, don't validate”—you express constraints like mutually exclusive options or dependent flags through types, and TypeScript infers the rest automatically. No runtime validation boilerplate needed.

It started as something I built out of frustration while working on Fedify, an ActivityPub framework, when no existing CLI library could express the constraints I needed in a type-safe way. Apparently I wasn't the only one who felt that way.

Thank you all for the support.

https://github.com/dahlia/optique

Screenshot of the GitHub repository page for dahlia/optique. The repository header shows a fork count of 7 and a star count of 601. The navigation tabs show Code, Issues (312), Pull requests, Discussions, Actions, and Security. The current branch is main, with the latest commit hash 9b28b85 made 18 minutes ago. The About section on the right reads “type-safe combinatorial CLI parser for TypeScript” with a link to optique.dev.
ALT text

Screenshot of the GitHub repository page for dahlia/optique. The repository header shows a fork count of 7 and a star count of 601. The navigation tabs show Code, Issues (312), Pull requests, Discussions, Actions, and Security. The current branch is main, with the latest commit hash 9b28b85 made 18 minutes ago. The About section on the right reads “type-safe combinatorial CLI parser for TypeScript” with a link to optique.dev.

@toxi@mastodon.thi.ng

It's Friday, spring is here (a bit too early) — it feels like a good day to share another minute recording of a variation of my Actiniaria piece which I worked on last spring and think also captures that much needed spirit...

See for more context...

(Note: Sadly Firefox still doesn't respect the Rec2020 color profile in the video, please download the video or use Chrome or Safari for full viewing pleasure...)

1 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from generated gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones...
ALT text

1 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from generated gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 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:

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

https://fedify.dev/

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

@smallcircles@social.coop · Reply to 🫧 Social coding commons

@fedify @hongminhee I would be delighted if contributors would take a peek at the fediverse development curated list and propose a PR on how best to incorporate the changes to the project, now that the various packages have been modularized. That would be very helpful. And create an issue if the current list format is no good fit.

delightful.coding.social/delig

@david_megginson @ben @nlnet

delightful.coding.social

delightful fediverse development

Delightful curated lists of free software, open science and information sources.

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

"Fedify 2.0.0 está aqui!

Esta é a maior atualização da história do Fedify. Destaques:

**Arquitetura modular** – O pacote monolítico `@fedify/fedify` foi dividido em pacotes independentes e focados: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger` e outros. Pacotes menores, imports mais limpos e a possibilidade de estender o ActivityPub com tipos de vocabulário personalizados.

**Painel de depuração em tempo real** – O novo pacote `@fedify/debugger` oferece um dashboard ao vivo em `/__debug__/` que mostra todo o tráfego de federação: traces, detalhes das atividades, verificação de assinaturas e logs correlacionados. Basta envolver seu objeto `Federation` e pronto.

**Suporte a relay do ActivityPub** – Suporte nativo a relays via `@fedify/relay` e o comando CLI `fedify relay`. Compatível com os protocolos Mastodon-style e LitePub-style (FEP-ae0c).

**Entrega ordenada de mensagens** – A nova opção `orderingKey` resolve o problema do "post zumbi", quando um `Delete` chega antes do seu `Create`. Atividades com a mesma chave são entregues garantidamente na ordem FIFO.

**Tratamento de falhas permanentes** – `setOutboxPermanentFailureHandler()` permite reagir quando uma inbox remota retorna 404 ou 410, possibilitando limpar seguidores inacessíveis em vez de tentar reenviar indefinidamente.

Outras novidades incluem negociação de conteúdo no nível do middleware, `@fedify/lint` para regras compartilhadas de linting, `@fedify/create` para scaffolding rápido de projetos, arquivos de configuração para a CLI, suporte nativo à CLI em Node.js/Bun e diversos fixes de bugs.

Esta versão conta com contribuições significativas de participantes do OSSCA da Coreia. Agradecemos imensamente a todos envolvidos!

Trata-se de uma release major com breaking changes. Consulte o guia de migração antes de atualizar.

Notas completas da release: github.com/fedify-dev/fedify/d

"

@fediverse @tecnologia @academicos @internet (pode seguir para acompanhar os assuntos ou marcar para amplificar a postagem até no tb)

@fedify hollo.social/@fedify/019c8521-

hollo.social

**Fedify 2.0.0 is here!** Thi…

**Fedify 2.0.0 is here!** This is the biggest release in Fedify's history. Here are the highlights: - **Modular architecture** — The monolithic `@fedify/fedify` package has been broken up into focused, independent packages: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger`, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types. - **Real-time debug dashboard** — The new `@fedify/debugger` package gives you a live dashboard at `/__debug__/` showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your `Federation` object and you're done. - **ActivityPub relay support** — First-class relay support via `@fedify/relay` and the `fedify relay` CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c). - **Ordered message delivery** — The new `orderingKey` option solves the “zombie post” problem where a `Delete` arrives before its `Create`. Activities sharing the same key are guaranteed to be delivered in FIFO order. - **Permanent failure handling** — `setOutboxPermanentFailureHandler()` lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever. Other changes include content negotiation at the middleware level, `@fedify/lint` for shared linting rules, `@fedify/create` for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes. This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved! This is a major release with breaking changes—please check the migration guide before upgrading. Full release notes: https://github.com/fedify-dev/fedify/discussions/580 #Fedify #ActivityPub #fediverse #fedidev #TypeScript

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

"Fedify 2.0.0 está aqui!

Esta é a maior atualização da história do Fedify. Destaques:

**Arquitetura modular** – O pacote monolítico `@fedify/fedify` foi dividido em pacotes independentes e focados: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger` e outros. Pacotes menores, imports mais limpos e a possibilidade de estender o ActivityPub com tipos de vocabulário personalizados.

**Painel de depuração em tempo real** – O novo pacote `@fedify/debugger` oferece um dashboard ao vivo em `/__debug__/` que mostra todo o tráfego de federação: traces, detalhes das atividades, verificação de assinaturas e logs correlacionados. Basta envolver seu objeto `Federation` e pronto.

**Suporte a relay do ActivityPub** – Suporte nativo a relays via `@fedify/relay` e o comando CLI `fedify relay`. Compatível com os protocolos Mastodon-style e LitePub-style (FEP-ae0c).

**Entrega ordenada de mensagens** – A nova opção `orderingKey` resolve o problema do "post zumbi", quando um `Delete` chega antes do seu `Create`. Atividades com a mesma chave são entregues garantidamente na ordem FIFO.

**Tratamento de falhas permanentes** – `setOutboxPermanentFailureHandler()` permite reagir quando uma inbox remota retorna 404 ou 410, possibilitando limpar seguidores inacessíveis em vez de tentar reenviar indefinidamente.

Outras novidades incluem negociação de conteúdo no nível do middleware, `@fedify/lint` para regras compartilhadas de linting, `@fedify/create` para scaffolding rápido de projetos, arquivos de configuração para a CLI, suporte nativo à CLI em Node.js/Bun e diversos fixes de bugs.

Esta versão conta com contribuições significativas de participantes do OSSCA da Coreia. Agradecemos imensamente a todos envolvidos!

Trata-se de uma release major com breaking changes. Consulte o guia de migração antes de atualizar.

Notas completas da release: github.com/fedify-dev/fedify/d

"

@fediverse @tecnologia @academicos @internet (pode seguir para acompanhar os assuntos ou marcar para amplificar a postagem até no tb)

@fedify hollo.social/@fedify/019c8521-

hollo.social

**Fedify 2.0.0 is here!** Thi…

**Fedify 2.0.0 is here!** This is the biggest release in Fedify's history. Here are the highlights: - **Modular architecture** — The monolithic `@fedify/fedify` package has been broken up into focused, independent packages: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger`, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types. - **Real-time debug dashboard** — The new `@fedify/debugger` package gives you a live dashboard at `/__debug__/` showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your `Federation` object and you're done. - **ActivityPub relay support** — First-class relay support via `@fedify/relay` and the `fedify relay` CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c). - **Ordered message delivery** — The new `orderingKey` option solves the “zombie post” problem where a `Delete` arrives before its `Create`. Activities sharing the same key are guaranteed to be delivered in FIFO order. - **Permanent failure handling** — `setOutboxPermanentFailureHandler()` lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever. Other changes include content negotiation at the middleware level, `@fedify/lint` for shared linting rules, `@fedify/create` for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes. This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved! This is a major release with breaking changes—please check the migration guide before upgrading. Full release notes: https://github.com/fedify-dev/fedify/discussions/580 #Fedify #ActivityPub #fediverse #fedidev #TypeScript

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

"Fedify 2.0.0 está aqui!

Esta é a maior atualização da história do Fedify. Destaques:

**Arquitetura modular** – O pacote monolítico `@fedify/fedify` foi dividido em pacotes independentes e focados: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger` e outros. Pacotes menores, imports mais limpos e a possibilidade de estender o ActivityPub com tipos de vocabulário personalizados.

**Painel de depuração em tempo real** – O novo pacote `@fedify/debugger` oferece um dashboard ao vivo em `/__debug__/` que mostra todo o tráfego de federação: traces, detalhes das atividades, verificação de assinaturas e logs correlacionados. Basta envolver seu objeto `Federation` e pronto.

**Suporte a relay do ActivityPub** – Suporte nativo a relays via `@fedify/relay` e o comando CLI `fedify relay`. Compatível com os protocolos Mastodon-style e LitePub-style (FEP-ae0c).

**Entrega ordenada de mensagens** – A nova opção `orderingKey` resolve o problema do "post zumbi", quando um `Delete` chega antes do seu `Create`. Atividades com a mesma chave são entregues garantidamente na ordem FIFO.

**Tratamento de falhas permanentes** – `setOutboxPermanentFailureHandler()` permite reagir quando uma inbox remota retorna 404 ou 410, possibilitando limpar seguidores inacessíveis em vez de tentar reenviar indefinidamente.

Outras novidades incluem negociação de conteúdo no nível do middleware, `@fedify/lint` para regras compartilhadas de linting, `@fedify/create` para scaffolding rápido de projetos, arquivos de configuração para a CLI, suporte nativo à CLI em Node.js/Bun e diversos fixes de bugs.

Esta versão conta com contribuições significativas de participantes do OSSCA da Coreia. Agradecemos imensamente a todos envolvidos!

Trata-se de uma release major com breaking changes. Consulte o guia de migração antes de atualizar.

Notas completas da release: github.com/fedify-dev/fedify/d

"

@fediverse @tecnologia @academicos @internet (pode seguir para acompanhar os assuntos ou marcar para amplificar a postagem até no tb)

@fedify hollo.social/@fedify/019c8521-

hollo.social

**Fedify 2.0.0 is here!** Thi…

**Fedify 2.0.0 is here!** This is the biggest release in Fedify's history. Here are the highlights: - **Modular architecture** — The monolithic `@fedify/fedify` package has been broken up into focused, independent packages: `@fedify/vocab`, `@fedify/vocab-runtime`, `@fedify/vocab-tools`, `@fedify/webfinger`, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types. - **Real-time debug dashboard** — The new `@fedify/debugger` package gives you a live dashboard at `/__debug__/` showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your `Federation` object and you're done. - **ActivityPub relay support** — First-class relay support via `@fedify/relay` and the `fedify relay` CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c). - **Ordered message delivery** — The new `orderingKey` option solves the “zombie post” problem where a `Delete` arrives before its `Create`. Activities sharing the same key are guaranteed to be delivered in FIFO order. - **Permanent failure handling** — `setOutboxPermanentFailureHandler()` lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever. Other changes include content negotiation at the middleware level, `@fedify/lint` for shared linting rules, `@fedify/create` for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes. This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved! This is a major release with breaking changes—please check the migration guide before upgrading. Full release notes: https://github.com/fedify-dev/fedify/discussions/580 #Fedify #ActivityPub #fediverse #fedidev #TypeScript

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0をリリースしました!

Fedify史上最大のリリースです。主な変更点をご紹介します:

  • モジュラーアーキテクチャ — これまでのモノリシックな@fedify/fedifyパッケージを、@fedify/vocab@fedify/vocab-runtime@fedify/vocab-tools@fedify/webfingerなど、独立したパッケージに分割しました。バンドルサイズの削減、インポートの整理に加え、カスタム語彙型によるActivityPubの拡張も可能になりました。
  • リアルタイムデバッグダッシュボード — 新しい@fedify/debuggerパッケージにより、/__debug__/パスにライブダッシュボードを表示できます。連合トラフィックのトレース、アクティビティの詳細、署名検証、ログまで一目で確認できます。既存のFederationオブジェクトをラップするだけで使えます。
  • ActivityPubリレーサポート@fedify/relayパッケージとfedify relayCLIコマンドで、リレーサーバーをすぐに立ち上げることができます。Mastodon方式とLitePub方式の両方に対応しています(FEP-ae0c)。
  • 順序保証メッセージ配信 — 新しいorderingKeyオプションにより、「ゾンビ投稿」問題を解決しました。DeleteCreateより先に到着してしまう問題がなくなります。同じキーを共有するアクティビティはFIFO順序が保証されます。
  • 永続的な配信失敗の処理setOutboxPermanentFailureHandler()で、リモートのインボックスが404や410を返した際に対応できるようになりました。到達不能なフォロワーの整理などが可能です。

その他にも、ミドルウェアレベルでのコンテンツネゴシエーション、@fedify/lint@fedify/create、CLI設定ファイル、ネイティブNode.js/Bun CLIサポート、多数のバグ修正などが含まれています。

今回のリリースには、韓国のOSSCA(オープンソースコントリビューションアカデミー)参加者の皆さんからの多大な貢献が含まれています。ご協力いただいた全ての方に感謝いたします!

破壊的変更を含むメジャーリリースです。アップグレード前にマイグレーションガイドを必ずご確認ください。

リリースノート全文: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0을 릴리스했습니다!

Fedify 역사상 가장 큰 릴리스입니다. 주요 변경 사항을 소개합니다:

  • 모듈형 아키텍처 — 기존의 단일 @fedify/fedify 패키지를 @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger 등 독립적인 패키지들로 분리했습니다. 번들 크기가 줄어들고, 임포트가 깔끔해지며, 커스텀 어휘 타입으로 ActivityPub을 확장할 수도 있습니다.
  • 실시간 디버그 대시보드 — 새로운 @fedify/debugger 패키지로 /__debug__/ 경로에 라이브 대시보드를 띄울 수 있습니다. 연합 트래픽의 트레이스, 액티비티 상세, 서명 검증, 로그까지 한눈에 확인할 수 있습니다. 기존 Federation 객체를 감싸기만 하면 됩니다.
  • ActivityPub 릴레이 지원@fedify/relay 패키지와 fedify relay CLI 명령어로 릴레이 서버를 바로 띄울 수 있습니다. Mastodon 방식과 LitePub 방식 모두 지원합니다(FEP-ae0c).
  • 순서 보장 메시지 전달 — 새로운 orderingKey 옵션으로 “좀비 포스트” 문제를 해결합니다. DeleteCreate보다 먼저 도착하는 문제가 더 이상 발생하지 않습니다. 같은 키를 공유하는 액티비티는 FIFO 순서가 보장됩니다.
  • 영구 전달 실패 처리setOutboxPermanentFailureHandler()로 원격 인박스가 404나 410을 반환할 때 대응할 수 있습니다. 도달 불가능한 팔로워를 정리하는 등의 처리가 가능합니다.

이 외에도 미들웨어 수준의 콘텐츠 협상, @fedify/lint, @fedify/create, CLI 설정 파일, 네이티브 Node.js/Bun CLI 지원, 다수의 버그 수정 등이 포함되어 있습니다.

이번 릴리스에는 한국 OSSCA (오픈소스 컨트리뷰션 아카데미) 참가자분들의 큰 기여가 담겨 있습니다. 참여해 주신 모든 분께 감사드립니다!

브레이킹 체인지가 포함된 메이저 릴리스입니다. 업그레이드 전에 마이그레이션 가이드를 꼭 확인해 주세요.

전체 릴리스 노트: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

Fedify 2.0.0 is here!

This is the biggest release in Fedify's history. Here are the highlights:

  • Modular architecture — The monolithic @fedify/fedify package has been broken up into focused, independent packages: @fedify/vocab, @fedify/vocab-runtime, @fedify/vocab-tools, @fedify/webfinger, and more. Smaller bundles, cleaner imports, and the ability to extend ActivityPub with custom vocabulary types.
  • Real-time debug dashboard — The new @fedify/debugger package gives you a live dashboard at /__debug__/ showing all your federation traffic: traces, activity details, signature verification, and correlated logs. Just wrap your Federation object and you're done.
  • ActivityPub relay support — First-class relay support via @fedify/relay and the fedify relay CLI command. Supports both Mastodon-style and LitePub-style relay protocols (FEP-ae0c).
  • Ordered message delivery — The new orderingKey option solves the “zombie post” problem where a Delete arrives before its Create. Activities sharing the same key are guaranteed to be delivered in FIFO order.
  • Permanent failure handlingsetOutboxPermanentFailureHandler() lets you react when a remote inbox returns 404 or 410, so you can clean up unreachable followers instead of retrying forever.

Other changes include content negotiation at the middleware level, @fedify/lint for shared linting rules, @fedify/create for quick project scaffolding, CLI config files, native Node.js/Bun CLI support, and many bug fixes.

This release includes significant contributions from Korea's OSSCA participants. Huge thanks to everyone involved!

This is a major release with breaking changes—please check the migration guide before upgrading.

Full release notes: https://github.com/fedify-dev/fedify/discussions/580

github.com

Fedify 2.0.0: Modular architecture, debug dashboard, and relay support · fedify-dev/fedify · Discussion #580

Fedify is a TypeScript framework for building ActivityPub servers that participate in the fediverse. It reduces the complexity and boilerplate typically required for ActivityPub implementation whil...

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

Latest harvest of "Light Streaks" — generative photography (see start of thread for context and an explanation of the technique...)

Again, all of these variations are still from the exact same system and choice of five randomly chosen functions. The only variable between them is the initial random seed number. Exposure here is between 5-10 billion iterations... I'm amazed by just how varied the outcomes are, still regularly encountering directions I haven't seen before...

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of abstract light streaks created by an IFS fractal.

Fedify 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:

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

https://fedify.dev/

Fedify 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:

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

https://fedify.dev/

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number. There seem to be several families of outcomes produced, in this post a selection of textures & sparklers...

The sub-atomic fabric of space time?

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

More variations of "Light Streaks" — generative photography... A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems). See start of thread for context and an explanation of the technique...

All of the variations in this post and the following ones are from the exact same system and choice of functions. The only variable here is the random seed number. There seem to be several families of outcomes produced, in this post a selection of "auroras"...

Each image is the result of around 2-4 billion iterations of light capture. Original resolution is 5120x5120 pixels. I will post a fullsize image later...

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

@corpsmoderne@mamot.fr

Hey people, is there a way to not declare a variable here and still specify the argument type on the call site?

what I have:

function foo(arg: Bar) { ... };

const arg : Bar = { ... };
foo(arg);

what I want:
foo({ ... } : Bar), // but that's not the syntax...

(note: that's typically a question LLM's are good at but I chose to value human interaction and not AI slop)

@toxi@mastodon.thi.ng

Light Streaks — generative photography

A small selection of long-exposures of randomly generated IFS (aka Iterated Function Systems), a family of very oldskool primitive/trivial fractal functions, but which can produce a fairly wide variety of outcomes. Each image is the result of billions of iterations of a single particle being iteratively transformed (meaning the particle's current position is used as the input for computing its next position etc.) For each iteration & position a tiny amount of light is being captured, slowly revealing an image, just like a negative does in analog film photography.

Some of these images have been "exposed" (aka computed) for up to 30 mins. The smaller the amount of light captured per iteration, the smoother (less grainy) the outcome...

(For the more technical: This is one of these projects where a floating point pixel buffer _really_ makes all the difference! My exposure rate is only 0.001 per pixel per frame, some of the images use even weaker settings... That means for a pixel to become fully white is has to be visited at least 1000 times [or more])

Made with thi.ng/matrices (matrix transformations) and thi.ng/pixel ("film" capture)...

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal. The streaks have a strong halo effect like lasers in a foggy atmosphere
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal. The streaks have a strong halo effect like lasers in a foggy atmosphere

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

Simulated monochrome photograph of light streaks created by an IFS fractal.
ALT text

Simulated monochrome photograph of light streaks created by an IFS fractal.

@zeab@fosstodon.org

Interesting to see combinator conditions on for CLI.

This is something that's hard to do in any CLI library. Easier with typed languages, but still can be complex. Very cool to see with and their approach leveraging the type system. 😎

optique.dev/why

optique.dev

Why Optique? | Optique

Discover how Optique brings functional composition to TypeScript CLI development, enabling truly reusable parser components that other libraries can't match through configuration-based approaches.

@toxi@mastodon.thi.ng

🎉 Just pushed a new version of the thi.ng/column-store database and query engine which adds support for new column types (fixed-size n-dimensional int/uint/float vectors) and RLE (run-length encoding) compression support for more column types. I also updated/extended the readme and started adding/porting more tests...

Related to these changes is that thi.ng/rle-pack now also offers the `encodeSimple()`/`decodeSimple()` functions which work for arrays of any type. This is in addition to the more advanced bitwise RLE packing offered so far (but only available for integer arrays). The readme for that package also has more code examples now...

Happy Coding! :)

thi.ng

Binary run-length encoding packer w/ flexible repeat bit widths

@jaredwhite@indieweb.social

🚨 Danger! Danger! 🚨

I've become aware that 's next big release 7.0 (not the latest 6.0 beta) is full-on Copilot slop coded. PRs are basically just a few people using outrageously long comment threads to bark out orders like a sociopath, whereby Copilot slavishly extrudes out more code.

This is gross and disturbing. 😬

I will *never* use TypeScript 7+, even if it's "faster" due to being "written" in Go.

I guess this means, one day, I will never use TypeScript.

@toxi@mastodon.thi.ng

Random tip & tidbit about unit conversions: I've been sourcing materials for a larger contact printing setup for my kallitype process, incl. getting a much heavier ultra-clear glass plate than what I've been using so far.

Using the thi.ng/units converter with its Lisp-like domain specific language, I can easily compute the following, freely mixing compatible units with complete ease. Using the S-expression DSL is optional. There's also a normal TypeScript/JavaScript API...

```
// weight in kilograms of 48cm x 35cm x 8mm plate
(kg (* 48cm 35cm 8mm glass))
// 3.36

// or use a DIN paper size preset
(kg (* (area din_a3) 8mm glass))
// 2.4948

// calculate force
(newton (* 48cm 35cm 8mm glass earth_gravity))
32.86191

// calculate PSI (pounds per square inch) of the plate on a smaller area
// here for a 6x4" print area example
(psi (/ (* 48cm 35cm 8mm glass earth_gravity) (* 6in 4in)))
// 0.30782

// compare with a simple picture frame
(psi (/ (* 24cm 30cm 2mm glass earth_gravity) (* 6in 4in)))
// 0.03298

// ...the thicker plate causes ~10x more pressure. q.e.d.
```

Maybe someone else finds that useful. The package readme contains a lot more information about possibilities, predefined constants and examples...

thi.ng

Extensible SI unit creation, conversions, quantities & calculations (incl. ~170 predefined units & constants)

Fedify 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:

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

https://fedify.dev/

@toxi@mastodon.thi.ng

— This week I've been working on extracting, refactoring & generalizing the minimal column store database I've been using for my personal knowledge/media management toolset, and I'm happy to share it with the world now:

thi.ng/column-store

This is an in-memory column store database with:

- Customizable column storage types with configurable min/max cardinality, support for optional and/or tuple-values, default values
- Support for custom column type implementations
- Optional dictionary encoding of column values (memory & filesize saving)
- Powerful extensible multi-term query engine with built-in OR/AND/NOR/NAND operators and predicate-based matchers (column, row, partial row). Queries can be pre-built and then executed as standard JS iterables
- Optional bitfield indexing for dramatic query acceleration (esp. for complex multi-term queries)
- Dynamic adding/removing of columns
- JSON serialization with optional RLE compression (in my PKM dataset with ~20k items, the RLE compressed version is only 29% of the normal JSON serialization)

I hope the readme and code examples give a decent overview for now... I've been using the overall system for a couple of years now, but this new packaged version is still marked as _alpha_. Everything's still being worked on.

Also, for those wondering what's the point of this all and why not using SQLite etc. — I find there're many use cases for a which a pure JSON-based approach is more than sufficient (without requiring extra tools and interfacing layers). The structure/storage model and the bitfield optimizations enable very fast query performance (compared to other JSON db's I've tried in the past)...

(Including all dependencies [only some other thi.ng packages], the entire DB package is ~6KB brotli'd, 19KB uncompressed...)

TypeScript code example from the package readme (too long for alt text, link to original: https://github.com/thi-ng/umbrella/tree/develop/packages/column-store#basic-usage)
ALT text

TypeScript code example from the package readme (too long for alt text, link to original: https://github.com/thi-ng/umbrella/tree/develop/packages/column-store#basic-usage)

@toxi@mastodon.thi.ng

Simulated Cyanotype Chemigrams...

Lately I've been revisiting my old fluid sim toolset which started out as part of my toxiclibs Java libraries (2007/8, based on Jos Stam's research, also previously mentioned in this thread[1]), then ported & expanded it for in 2016, then ported again to TypeScript/GLSL (via thi.ng/shader-ast in 2019) and been messing around with it on & off ever since... Fluidsims are just so mesmerizing to work/play with and can be taken into so many interesting directions!

I also always loved the watercolor cover designs by Gabriella Holmström for The Memoir[2] series on Hypnus Records and wanted to create similar abstract structures/constellation, albeit with simulated fluids... Stills/snapshots, but showing traces of their creation process.

Attached are a few variations of this system (already collected again hundreds which I have to still curate). Each piece is starting with just 4 drops in always the exact same locations (diamond-shaped layout in the center), but each variation is evolving differently due to randomized concentrations and simulation coefficients, therefore resulting in many different diffusion behaviors and outcomes... Some of the pieces which exhibit more viscous fingering[3] almost remind me of Hokusai's Great Wave[4]...

I will be offering sets of unique prints/cards of these via my shop soon. Also still researching feasibility of integrating interactively created variations in the shop (also for other artworks/collections of mine).

[1] mastodon.thi.ng/@toxi/11580242
[2] youtube.com/@Hypnusrecords/vid, for example: youtube.com/watch?v=efdfYJODiuA
[3] en.wikipedia.org/wiki/Saffman%
[4] en.wikipedia.org/wiki/The_Grea

A 3x3 grid of complex abstract shapes created via fluid simulations as described in the post. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)
ALT text

A 3x3 grid of complex abstract shapes created via fluid simulations as described in the post. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)

@senesens@tilde.zone

I think I will forever suck at configuring tsconfig.json. Every-time I look at it, it seems to have different semantics.

For example, am I correct to understand that path remaps in tsconfig.json never actually changed the import paths during transpilation? I've literally used this feature in every package I'd written ha, not this time around. Come again next week.

A face in dream.

@pcdevil@mastodon.social

👋 I'm looking for a Senior Engineer job!

🚀 I am...
- a detail oriented senior engineer with 15 years of experience
- proficient with and , , , TDD
- experienced with , Ember.js, GCP, Terraform

🔎 I'm looking for:
- a collaborative environment between engineering + product & design teams
- a Germany / EU-based remote-first company
- ability to learn and grow

🚫 no crypto, web3, big oil, gen-ai, gambling

🙇 boost appreciated!

@pcdevil@mastodon.social

👋 I'm looking for a Senior Engineer job!

🚀 I am...
- a detail oriented senior engineer with 15 years of experience
- proficient with and , , , TDD
- experienced with , Ember.js, GCP, Terraform

🔎 I'm looking for:
- a collaborative environment between engineering + product & design teams
- a Germany / EU-based remote-first company
- ability to learn and grow

🚫 no crypto, web3, big oil, gen-ai, gambling

🙇 boost appreciated!

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

Some more variations curated this AM... in love with these shapes & process!

(See start of this thread for context...)

A 3x3 grid of complex abstract shapes created via fluid simulations as described at the start of this thread. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)
ALT text

A 3x3 grid of complex abstract shapes created via fluid simulations as described at the start of this thread. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)

@toxi@mastodon.thi.ng

Simulated Cyanotype Chemigrams...

Lately I've been revisiting my old fluid sim toolset which started out as part of my toxiclibs Java libraries (2007/8, based on Jos Stam's research, also previously mentioned in this thread[1]), then ported & expanded it for in 2016, then ported again to TypeScript/GLSL (via thi.ng/shader-ast in 2019) and been messing around with it on & off ever since... Fluidsims are just so mesmerizing to work/play with and can be taken into so many interesting directions!

I also always loved the watercolor cover designs by Gabriella Holmström for The Memoir[2] series on Hypnus Records and wanted to create similar abstract structures/constellation, albeit with simulated fluids... Stills/snapshots, but showing traces of their creation process.

Attached are a few variations of this system (already collected again hundreds which I have to still curate). Each piece is starting with just 4 drops in always the exact same locations (diamond-shaped layout in the center), but each variation is evolving differently due to randomized concentrations and simulation coefficients, therefore resulting in many different diffusion behaviors and outcomes... Some of the pieces which exhibit more viscous fingering[3] almost remind me of Hokusai's Great Wave[4]...

I will be offering sets of unique prints/cards of these via my shop soon. Also still researching feasibility of integrating interactively created variations in the shop (also for other artworks/collections of mine).

[1] mastodon.thi.ng/@toxi/11580242
[2] youtube.com/@Hypnusrecords/vid, for example: youtube.com/watch?v=efdfYJODiuA
[3] en.wikipedia.org/wiki/Saffman%
[4] en.wikipedia.org/wiki/The_Grea

A 3x3 grid of complex abstract shapes created via fluid simulations as described in the post. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)
ALT text

A 3x3 grid of complex abstract shapes created via fluid simulations as described in the post. The images have a monochromatic blue tint (the underlying simulation is just producing a grayscale image)

@ghalldev@mastodon.social

Today marks 7 months of unemployment and I am very much down to the wire.

I am a full-stack & backend web developer, fluent in TypeScript, with experience building data-focused applications and both SQLite and Postrges databases.

I’m located in the northeast United States and have experience working and successfully collaborating with small, remote teams.

Boosts are appreciated. 🙏

@ghalldev@mastodon.social

Today marks 7 months of unemployment and I am very much down to the wire.

I am a full-stack & backend web developer, fluent in TypeScript, with experience building data-focused applications and both SQLite and Postrges databases.

I’m located in the northeast United States and have experience working and successfully collaborating with small, remote teams.

Boosts are appreciated. 🙏

@ghalldev@mastodon.social

Today marks 7 months of unemployment and I am very much down to the wire.

I am a full-stack & backend web developer, fluent in TypeScript, with experience building data-focused applications and both SQLite and Postrges databases.

I’m located in the northeast United States and have experience working and successfully collaborating with small, remote teams.

Boosts are appreciated. 🙏

@ghalldev@mastodon.social

Today marks 7 months of unemployment and I am very much down to the wire.

I am a full-stack & backend web developer, fluent in TypeScript, with experience building data-focused applications and both SQLite and Postrges databases.

I’m located in the northeast United States and have experience working and successfully collaborating with small, remote teams.

Boosts are appreciated. 🙏

@ghalldev@mastodon.social

Today marks 7 months of unemployment and I am very much down to the wire.

I am a full-stack & backend web developer, fluent in TypeScript, with experience building data-focused applications and both SQLite and Postrges databases.

I’m located in the northeast United States and have experience working and successfully collaborating with small, remote teams.

Boosts are appreciated. 🙏

@toxi@mastodon.thi.ng
Screenrecording of a Terminal/command line app displaying four animated area charts (in red, green, blue, gray) overlapping each other and blended together using additive colors.
ALT text

Screenrecording of a Terminal/command line app displaying four animated area charts (in red, green, blue, gray) overlapping each other and blended together using additive colors.

@toxi@mastodon.thi.ng

Also new in : The new thi.ng/text-format-image package provides conversion/formatting for bitmap output for CLI/Terminal apps, currently only via the widely supported iTerm2 format (see readme for details). Supports JPG/PNG (possibly others, depending on terminal used) as well as thi.ng/pixel pixel buffers (e.g. for dynamically generated images/visualizations)

Ps. The above relies on extended ANSI sequences to submit bitmap data to the terminal. If you're after actual text/character-based image conversion, you can alternatively use the functions provided in thi.ng/text-canvas:

github.com/thi-ng/umbrella/tre

Screenshot of a CLI/Terminal with the code example from the thi.ng/text-format-image readme and the resulting image output as part of the normal flow...
ALT text

Screenshot of a CLI/Terminal with the code example from the thi.ng/text-format-image readme and the resulting image output as part of the normal flow...

@toxi@mastodon.thi.ng

New example to create a parametric, grid layout-based calibration sheet for black and white photography development. The sheet includes different swatches and gradients to measure results/responses of different exposure times and developer solutions/processes. The sheet also includes a placeholder for a custom test image to be added later...

All sheet components are parametric and use a grid layout from which cells/boxes are obtained and then used to dynamically compute/adapt component geometries...

demo.thi.ng/umbrella/calibrati

(Right click on the image and choose "Save image as..." to download it...)

Source code:
github.com/thi-ng/umbrella/blo

Made with (mostly) these packages: thi.ng/geom, thi.ng/layout, thi.ng/hiccup-canvas and thi.ng/transducers

Generated grayscale calibration sheet as discussed in the post. The top part of the image has three rows of grayscale swatches in different gradations, followed by a row of opposing grayscale gradients with 10% markings. Below is a column of two radial gradients: the first one white to black, the other inverted, both with 10% markings (as hemi-arcs). On the right, four bands of vertical gradients, each with a superimposed low contrast checkerboard pattern. The remaining space is reserved for an arbitrary test image to be added later.
ALT text

Generated grayscale calibration sheet as discussed in the post. The top part of the image has three rows of grayscale swatches in different gradations, followed by a row of opposing grayscale gradients with 10% markings. Below is a column of two radial gradients: the first one white to black, the other inverted, both with 10% markings (as hemi-arcs). On the right, four bands of vertical gradients, each with a superimposed low contrast checkerboard pattern. The remaining space is reserved for an arbitrary test image to be added later.

@LAYERED@oldbytes.space

Originally, I just wanted a few SF Symbol icons for my Admin. And then somehow it got completely out of hand. The result is a that provides all 6,984 SF Symbols from Apple's Mac App in version 7 as React components. The screenshot shows the interactive preview page that comes with the package.

Here you can find a live demo of that webpage:

sfsymbolslib.layered.work

@deobald@fantastic.earth

dear people (especially anyone who does ts on gnome/gtk/adw apps) ... is jest the testing tool i want in 2026?

i don't want the new hotness. i want the boring thing that's guaranteed to work. think junit

@yth@mstdn.social

I have been looking for a programming language for simple (cross platform) CLI tools for a long time. Professionally I use , which I accept now as the safest choice for serious enterprise stuff. I have tried but after a long stint I have decided to say goodbye to the Javacript ecosystem for anything but Frontend. Now on and , leaning towards the latter. I won’t consider (sorry). I could just use Java for everything. Anyone want to weigh in?

@toxi@mastodon.thi.ng

Welcome to ! For the next few weeks I'll be posting some projects & experiments related to this just spontaneously made up hashtag. If you've got something related to interesting text-based art/experiments, patterns, ASCII-art, ANSI-art etc. please share — the more, the merrier...

To start with, here's an experiment from a few years ago to demonstrate some capabilities of thi.ng/text-canvas and thi.ng/shader-ast to create a raymarching renderer outputting images in text mode (with customizable character sets to represent luminance).

Demo:
demo.thi.ng/umbrella/ascii-ray

Commented source code:
github.com/thi-ng/umbrella/blo

Hotkeys:

- c = toggle color on/off
- t = toggle theme switch
- space = toggle update

WebGL version of the same scene (using an almost identical TypeScript shader source, only here transpiled to GLSL and using slightly different colors):
demo.thi.ng/umbrella/shader-as

Screenrecording of the linked demo, showing a rotating infinite 3D grid of colorful cube-like structures with smooth intersections. Every few seconds the animation cycles between different character sets used to represent the rendered frames as text.
ALT text

Screenrecording of the linked demo, showing a rotating infinite 3D grid of colorful cube-like structures with smooth intersections. Every few seconds the animation cycles between different character sets used to represent the rendered frames as text.

@hongminhee@hollo.social

0.9.0 is here!

This release brings /await support to parsers. Now you can validate input against external resources—databases, APIs, Git repositories—directly at parse time, with full type safety.

The new @optique/git package showcases this: validate branch names, tags, and commit SHAs against an actual Git repo, complete with shell completion suggestions.

Other highlights:

  • Hidden option support for deprecated/internal flags
  • Numeric choices in choice()
  • Security fix for shell completion scripts

Fully backward compatible—your existing parsers work unchanged.

https://github.com/dahlia/optique/discussions/75

github.com

Optique 0.9.0: Async parsers and Git reference validation · dahlia/optique · Discussion #75

We're excited to announce Optique 0.9.0! This release brings two major features: full async/await support for parsers and a new @optique/git package for validating Git references against actual rep...

@hongminhee@hollo.social

0.9.0 is here!

This release brings /await support to parsers. Now you can validate input against external resources—databases, APIs, Git repositories—directly at parse time, with full type safety.

The new @optique/git package showcases this: validate branch names, tags, and commit SHAs against an actual Git repo, complete with shell completion suggestions.

Other highlights:

  • Hidden option support for deprecated/internal flags
  • Numeric choices in choice()
  • Security fix for shell completion scripts

Fully backward compatible—your existing parsers work unchanged.

https://github.com/dahlia/optique/discussions/75

github.com

Optique 0.9.0: Async parsers and Git reference validation · dahlia/optique · Discussion #75

We're excited to announce Optique 0.9.0! This release brings two major features: full async/await support for parsers and a new @optique/git package for validating Git references against actual rep...

@hongminhee@hollo.social

0.9.0 is here!

This release brings /await support to parsers. Now you can validate input against external resources—databases, APIs, Git repositories—directly at parse time, with full type safety.

The new @optique/git package showcases this: validate branch names, tags, and commit SHAs against an actual Git repo, complete with shell completion suggestions.

Other highlights:

  • Hidden option support for deprecated/internal flags
  • Numeric choices in choice()
  • Security fix for shell completion scripts

Fully backward compatible—your existing parsers work unchanged.

https://github.com/dahlia/optique/discussions/75

github.com

Optique 0.9.0: Async parsers and Git reference validation · dahlia/optique · Discussion #75

We're excited to announce Optique 0.9.0! This release brings two major features: full async/await support for parsers and a new @optique/git package for validating Git references against actual rep...

@ferrata@hachyderm.io

I think I've rested enough to start blogging again. What do you think I should write about next?

  • Extending vitest fixtures with TS0 (0%)
  • Creating Playwright test suite1 (100%)
  • Building a Playwright reports site with GH actions0 (0%)
  • Building docs site with Starlight and Decap CMS0 (0%)
@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@hongminhee@hollo.social

Released Vertana 0.1.0—agentic for /.

Instead of just passing text to an , it autonomously gathers context from linked pages and references to produce translations that actually understand what they're .

github.com

GitHub - dahlia/vertana: LLM-powered agentic translation library for JavaScript/TypeScript

LLM-powered agentic translation library for JavaScript/TypeScript - dahlia/vertana

@AdamRGrey@aleph.land

me: how do i check if my object is of a given type?
typescript:
> oh we don't have a way for that, you write a function :)
```typescript
function isOfTargetType(obj: any): obj is TargetType{
return obj !== undefined
}
```

...wasn't this THE WHOLE POINT of ?? Are we any better off than just writing regular-ass javascript?

@toxi@mastodon.thi.ng

My art, but not my video[1]. The piece is ASCII-SCAPE (2022), a pure text-only version of my C-SCAPE [2] multi-cellular automata piece in which several "organisms" are co-evolving in the same space and forming infinitely changing patterns/structures:

art.thi.ng/ascii-scape/
(Reload for random variations)

The following keyboard shortcuts are available:

- space : toggle simulation updates (pause/play)
- r : randomize environment (within current sim)
- x : start/stop recording (export as text file, max. 100k lines)
- f : toggle scroll speed (fast/slow)
- Use browser text zoom to adjust resolution

Made with ❤️ and thi.ng/cellular & thi.ng/text-canvas

[1] Sorry, someone posted it on twitter back then, don't have the source anymore. Please ping me if you are/know the author.

[2] see for more info/examples

Short video of a B&W variation of ASCII-SCAPE running on a super-widescreen curved monitor. After a few seconds, the camera is moving much closer to the screen to only show a close-up of a handful of text characters making up the complex, vertically scrolling and evolving larger pattern.
ALT text

Short video of a B&W variation of ASCII-SCAPE running on a super-widescreen curved monitor. After a few seconds, the camera is moving much closer to the screen to only show a close-up of a handful of text characters making up the complex, vertically scrolling and evolving larger pattern.

@shye@deadrobots.social

I'm thinking of learning React/NextJS/Typescript. Is this a good idea?
I know HTML and CSS like the back of my hand, and half know Javascript (and PHP). I've been building websites on and off for 25 years.
A year ago I started putting thought and research into creating my own CMS for the flexibility (and having a hobby project).
I started learning Laravel, mostly because 10 years ago I had wanted to learn it, though I never got around to it. Plus I figured I would be able to pick it up quite easily, already having an understanding of how PHP works.
But over this last year, I've not been able to engage with learning it, wondering if there is any point learning something (getting on a bit now) that still leads to a clunky PHP app that needs constant maintainence.
I figure instead, I could use NextJs for the frontend, and a headless flexible open source data management / cms for the backend.
I would think it would take me at least a year of learning and practice to become adequate enough. So, I'm trying to decide if this is where I should put my energy - or if there is something else I should be putting focus on, if I'm going to start properly learning something new to me.

@mauve@mastodon.mauve.moe
@toxi@mastodon.thi.ng

A little present (to some of you)... Been meaning to release these recent additions before the holidays, but only getting around to it now. The most important new things are these:

thi.ng/units now includes a Lisp-like formula DSL to combine, calculate and convert quantities and units in a much concise manner than via the normal TypeScript API (see attached examples)

thi.ng/pixel-io-tiff is a new package (only 2.6KB) to provide TIFF image format parsing and EXIF/GPS metadata extraction (without having to parse the image fully). Also includes format conversions for thi.ng/pixel buffers (grayscale 8/16bit, RGB 24/32bit), but only supports most common TIFF features (e.g. tiles, strips, uncompressed or deflate). Supports multiple sub-images... Write support will be released early next year

thi.ng/math now has conversions to/from fractions, using "continued fractions" for best possible precision (also includes recursion-free implementations of GCD & LCM).

thi.ng/binary now provides `DATAVIEW`, a JS-native DataView-like API tailored for using `Uint8Array` or vanilla JS numeric arrays (assuming the array contains u8 values) and accessors for signed/unsigned 8-64bit word sizes and little/big endian ordering.

See main readme for other recent updates:
github.com/thi-ng/umbrella?tab

Screenshot of a section of the thi.ng/units package readme giving an overview of the new formula DSL provided. The included code examples show how to:

- compute weight in grams of A4 paper with 320 grams per square meter
- compute weight in kg of 1/2 inch thick 200x300mm glass plate
- same as previous but using the `glass` density preset 

Direct link: https://github.com/thi-ng/umbrella/tree/develop/packages/units#domain-specific-language
ALT text

Screenshot of a section of the thi.ng/units package readme giving an overview of the new formula DSL provided. The included code examples show how to: - compute weight in grams of A4 paper with 320 grams per square meter - compute weight in kg of 1/2 inch thick 200x300mm glass plate - same as previous but using the `glass` density preset Direct link: https://github.com/thi-ng/umbrella/tree/develop/packages/units#domain-specific-language

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

Fedify 1.10.0: Observability foundations for the future debug dashboard

Fedify is a framework for building servers that participate in the . It reduces the complexity and boilerplate typically required for ActivityPub implementation while providing comprehensive federation capabilities.

We're excited to announce 1.10.0, a focused release that lays critical groundwork for future debugging and observability features. Released on December 24, 2025, this version introduces infrastructure improvements that will enable the upcoming debug dashboard while maintaining full backward compatibility with existing Fedify applications.

This release represents a transitional step toward Fedify 2.0.0, introducing optional capabilities that will become standard in the next major version. The changes focus on enabling richer observability through OpenTelemetry enhancements and adding prefix scanning capabilities to the key–value store interface.

Enhanced OpenTelemetry instrumentation

Fedify 1.10.0 significantly expands OpenTelemetry instrumentation with span events that capture detailed ActivityPub data. These enhancements enable richer observability and debugging capabilities without relying solely on span attributes, which are limited to primitive values.

The new span events provide complete activity payloads and verification status, making it possible to build comprehensive debugging tools that show the full context of federation operations:

  • activitypub.activity.received event on activitypub.inbox span — records the full activity JSON, verification status (activity verified, HTTP signatures verified, Linked Data signatures verified), and actor information
  • activitypub.activity.sent event on activitypub.send_activity span — records the full activity JSON and target inbox URL
  • activitypub.object.fetched event on activitypub.lookup_object span — records the fetched object's type and complete JSON-LD representation

Additionally, Fedify now instruments previously uncovered operations:

  • activitypub.fetch_document span for document loader operations, tracking URL fetching, HTTP redirects, and final document URLs
  • activitypub.verify_key_ownership span for cryptographic key ownership verification, recording actor ID, key ID, verification result, and the verification method used

These instrumentation improvements emerged from work on issue #234 (Real-time ActivityPub debug dashboard). Rather than introducing a custom observer interface as originally proposed in #323, we leveraged Fedify's existing OpenTelemetry infrastructure to capture rich federation data through span events. This approach provides a standards-based foundation that's composable with existing observability tools like Jaeger, Zipkin, and Grafana Tempo.

Distributed trace storage with FedifySpanExporter

Building on the enhanced instrumentation, Fedify 1.10.0 introduces FedifySpanExporter, a new OpenTelemetry SpanExporter that persists ActivityPub activity traces to a KvStore. This enables distributed tracing support across multiple nodes in a Fedify deployment, which is essential for building debug dashboards that can show complete request flows across web servers and background workers.

The new @fedify/fedify/otel module provides the following types and interfaces:

import { MemoryKvStore } from "@fedify/fedify";
import { FedifySpanExporter } from "@fedify/fedify/otel";
import {
  BasicTracerProvider,
  SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-base";

const kv = new MemoryKvStore();
const exporter = new FedifySpanExporter(kv, {
  ttl: Temporal.Duration.from({ hours: 1 }),
});

const provider = new BasicTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

The stored traces can be queried for display in debugging interfaces:

// Get all activities for a specific trace
const activities = await exporter.getActivitiesByTraceId(traceId);

// Get recent traces with summary information
const recentTraces = await exporter.getRecentTraces({ limit: 100 });

The exporter supports two storage strategies depending on the KvStore capabilities. When the list() method is available (preferred), it stores individual records with keys like [prefix, traceId, spanId]. When only cas() is available, it uses compare-and-swap operations to append records to arrays stored per trace.

This infrastructure provides the foundation for implementing a comprehensive debug dashboard as a custom SpanExporter, as outlined in the updated implementation plan for issue #234.

Optional list() method for KvStore interface

Fedify 1.10.0 adds an optional list() method to the KvStore interface for enumerating entries by key prefix. This method enables efficient prefix scanning, which is useful for implementing features like distributed trace storage, cache invalidation by prefix, and listing related entries.

interface KvStore {
  // ... existing methods
  list?(prefix?: KvKey): AsyncIterable<KvStoreListEntry>;
}

When the prefix parameter is omitted or empty, list() returns all entries in the store. This is useful for debugging and administrative purposes. All official KvStore implementations have been updated to support this method:

  • MemoryKvStore — filters in-memory keys by prefix
  • SqliteKvStore — uses LIKE query with JSON key pattern
  • PostgresKvStore — uses array slice comparison
  • RedisKvStore — uses SCAN with pattern matching and key deserialization
  • DenoKvStore — delegates to Deno KV's built-in list() API
  • WorkersKvStore — uses Cloudflare Workers KV list() with JSON key prefix pattern

While list() is currently optional to give existing custom KvStore implementations time to add support, it will become a required method in Fedify 2.0.0 (tracked in issue #499). This migration path allows implementers to gradually adopt the new capability throughout the 1.x release cycle.

The addition of list() support was implemented in pull request #500, which also included the setup of proper testing infrastructure for WorkersKvStore using Vitest with @cloudflare/vitest-pool-workers.

NestJS 11 and Express 5 support

Thanks to a contribution from Cho Hasang (@crohasang), the @fedify/nestjs package now supports NestJS 11 environments that use Express 5. The peer dependency range for Express has been widened to ^4.0.0 || ^5.0.0, eliminating peer dependency conflicts in modern NestJS projects while maintaining backward compatibility with Express 4.

This change, implemented in pull request #493, keeps the workspace catalog pinned to Express 4 for internal development and test stability while allowing Express 5 in consuming applications.

What's next

Fedify 1.10.0 serves as a stepping stone toward the upcoming 2.0.0 release. The optional list() method introduced in this version will become required in 2.0.0, simplifying the interface contract and allowing Fedify internals to rely on prefix scanning being universally available.

The enhanced instrumentation and FedifySpanExporter provide the foundation for implementing the debug dashboard proposed in issue #234. The next steps include building the web dashboard UI with real-time activity lists, filtering, and JSON inspection capabilities—all as a separate package that leverages the standards-based observability infrastructure introduced in this release.

Depending on the development timeline and feature priorities, there may be additional 1.x releases before the 2.0.0 migration. For developers building custom KvStore implementations, now is the time to add list() support to prepare for the eventual 2.0.0 upgrade. The implementation patterns used in the official backends provide clear guidance for various storage strategies.

Acknowledgments

Special thanks to Cho Hasang (@crohasang) for the NestJS 11 compatibility improvements, and to all community members who provided feedback and testing for the new observability features.

For the complete list of changes, bug fixes, and improvements, please refer to the CHANGES.md file in the repository.

github.com

fedify/CHANGES.md at main · fedify-dev/fedify

ActivityPub server framework in TypeScript. Contribute to fedify-dev/fedify development by creating an account on GitHub.

@hongminhee@hollo.social

Here's a API design challenge I'm working on: adding async support to (CLI argument parser) without breaking the existing sync API.

The tricky part is combinators—when you compose parsers with object() or or(), the combined parser should automatically become async if any child parser is async, but stay sync if all children are sync. This “mode propagation” needs to work at both type level and runtime.

I've prototyped two approaches and documented findings. If you've tackled similar dual-mode API designs, I'd love to hear how you approached it.

https://github.com/dahlia/optique/issues/52

github.com

Support both sync and async modes for `Parser` and `ValueParser` · Issue #52 · dahlia/optique

I'm glad to see https://optique.dev/concepts/completion#custom-value-parser-suggestions but in some cases it may not be ideal to force the values to be retrieved synchronously. It would be nice to ...

@hongminhee@hollo.social

Here's a API design challenge I'm working on: adding async support to (CLI argument parser) without breaking the existing sync API.

The tricky part is combinators—when you compose parsers with object() or or(), the combined parser should automatically become async if any child parser is async, but stay sync if all children are sync. This “mode propagation” needs to work at both type level and runtime.

I've prototyped two approaches and documented findings. If you've tackled similar dual-mode API designs, I'd love to hear how you approached it.

https://github.com/dahlia/optique/issues/52

github.com

Support both sync and async modes for `Parser` and `ValueParser` · Issue #52 · dahlia/optique

I'm glad to see https://optique.dev/concepts/completion#custom-value-parser-suggestions but in some cases it may not be ideal to force the values to be retrieved synchronously. It would be nice to ...

@hongminhee@hollo.social

Here's a API design challenge I'm working on: adding async support to (CLI argument parser) without breaking the existing sync API.

The tricky part is combinators—when you compose parsers with object() or or(), the combined parser should automatically become async if any child parser is async, but stay sync if all children are sync. This “mode propagation” needs to work at both type level and runtime.

I've prototyped two approaches and documented findings. If you've tackled similar dual-mode API designs, I'd love to hear how you approached it.

https://github.com/dahlia/optique/issues/52

github.com

Support both sync and async modes for `Parser` and `ValueParser` · Issue #52 · dahlia/optique

I'm glad to see https://optique.dev/concepts/completion#custom-value-parser-suggestions but in some cases it may not be ideal to force the values to be retrieved synchronously. It would be nice to ...

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

A short video of another related old experiment, here showing a few random variations (4-5 secs each) using a low discrepancy sequence to iteratively create Voronoi patterns reminiscent of quasi-crystal lattices...

Made with thi.ng/lowdisc and thi.ng/geom-voronoi

Demo:
demo.thi.ng/umbrella/quasi-lat

Source code (minimal code, more comments than code):
github.com/thi-ng/umbrella/blo

Ps. Also check out @hamoid's recent Voronoi work (which just made me look for this video 😉)...

10 variations of colorful Voronoi patterns iteratively created by enumerating a 2D low discrepancy sequence to place more and more points. The resulting cells are colored based on their area (using a color picked from a predefined gradient)
ALT text

10 variations of colorful Voronoi patterns iteratively created by enumerating a 2D low discrepancy sequence to place more and more points. The resulting cells are colored based on their area (using a color picked from a predefined gradient)

@torb@hachyderm.io

I thought I was really going to like Vue on the account that reactivity contered on data variables/signals(ish) would mean less footguns than React.

But holy world, Vue silently adding Proxies to absolutely everything without telling you is a giant footgun in itself that makes if often *very* difficult to work with native APIs.

Combine this with the runtime running stuff the origin of the errors are difficult to track down since you can't just follow the call stack.

I literally fixed it by adding toRaw a bunch of places.

All this would have been fixed easily if Vue's TypeScript types would have *made explicit when things are in Proxies or not!*

I find it frankly unbelievable that they don't. It's downright unserious.

PLEASE DON'T LIE WITH YOUR TYPESCRIPT TYPES!

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

Recursive polygon subdivision, part 2

Here the seed polygon (40-gon) is recursively cut using sweeping perpendicular lines and the resulting number of polygons varies greatly depending on the position of these cuts (combined with a configured minimum poly target area). The area of each polygon is mapped to a color from a predefined gradient.

Live demo (slowed down to better observe the algorithm):
demo.thi.ng/umbrella/poly-subd

Commented source code:
github.com/thi-ng/umbrella/blo

2/2

Looping animation of a randomized abstract composition of temporarily hundreds of small polygons, created by animated perpendicular sweep lines recursively cutting the circular seed polygon (40-gon). The area/size of each individual poly is mapped to a color from a gradient, with small polys in orange/yellow/pink and large ones a deep blue
ALT text

Looping animation of a randomized abstract composition of temporarily hundreds of small polygons, created by animated perpendicular sweep lines recursively cutting the circular seed polygon (40-gon). The area/size of each individual poly is mapped to a color from a gradient, with small polys in orange/yellow/pink and large ones a deep blue

@toxi@mastodon.thi.ng

Recursive polygon subdivision inspired by thin-section mineralogy...

(The area of each polygon is mapped to a color from a gradient. Made with thi.ng/geom, see next message for example & source code...)

1/2

Stop frame animation of a randomized abstract composition of initially thousands of small polygons, slowly converging into only a handful of larger cells/shards. The animation shows the recursive subdivision process in reverse order, i.e. the larger cells at the end are actually some of the first polygons created by randomly slicing the seed polygon (a circular 40-gon). The area/size of each individual poly is mapped to a color from a gradient, with small polys in orange/yellow/pink and large ones a deep blue
ALT text

Stop frame animation of a randomized abstract composition of initially thousands of small polygons, slowly converging into only a handful of larger cells/shards. The animation shows the recursive subdivision process in reverse order, i.e. the larger cells at the end are actually some of the first polygons created by randomly slicing the seed polygon (a circular 40-gon). The area/size of each individual poly is mapped to a color from a gradient, with small polys in orange/yellow/pink and large ones a deep blue

@3v1n0@fosstodon.org

After years of beautiful native apps written using bindings for python, rust, JS and many other...

The GObject introspection system is proving again how great it is, welcoming a new member to the family: !

Bindings for writing native apps with and

Hopefully even more web developers will be able to write applications with the tools they know the best!

Read more at: eugeniodepalo.github.io/gtkx/

Also check it out the (source) reddit thread reddit.com/comments/1pkzd6f

reddit.com

Reddit - The heart of the internet

@3v1n0@fosstodon.org

After years of beautiful native apps written using bindings for python, rust, JS and many other...

The GObject introspection system is proving again how great it is, welcoming a new member to the family: !

Bindings for writing native apps with and

Hopefully even more web developers will be able to write applications with the tools they know the best!

Read more at: eugeniodepalo.github.io/gtkx/

Also check it out the (source) reddit thread reddit.com/comments/1pkzd6f

reddit.com

Reddit - The heart of the internet

@arendjr@mstdn.social
@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@toxi@mastodon.thi.ng

Neither nor seemingly support 1D LUTs, which would have been too easy and useful for my preparation tool... Instead they both insist on using only 3D LUTs. Converting 1D to 3D takes a bit more effort, but thanks to thi.ng/transducers, it's still very easy...

Syntax color highlighted TypeScript source code:

```
import {
	cycle,
	map,
	normRange,
	permutations,
	str,
	take,
	transduce,
} from "@thi.ng/transducers";

// LUT size (number of samples per axis)
const N = 9;

// example curve of N samples in [0,1] range
// (the curve here is y = x^1.2, i.e. a basic darken effect)
const curve = [...map((x) => (x ** 1.2).toFixed(4), normRange(N - 1))];

// compute cartesian product to produce RGB tuples
const lut = permutations(curve, curve, curve);

// alternatively, create LUT which also converts to grayscale...
// const lut = take(N * N * N, cycle(map((x) => [x, x, x], curve)));

// convert LUT samples to .cube format
// (flip order of each tuple since red channel needs change fastest)
const cube = transduce(
	map((x) => x.reverse().join(" ")),
	str("\n"),
	lut
);

// output LUT with header
console.log(`TITLE "example"
LUT_3D_SIZE ${N}
DOMAIN_MIN 0 0 0
DOMAIN_MAX 1 1 1
${cube}
`);
```
ALT text

Syntax color highlighted TypeScript source code: ``` import { cycle, map, normRange, permutations, str, take, transduce, } from "@thi.ng/transducers"; // LUT size (number of samples per axis) const N = 9; // example curve of N samples in [0,1] range // (the curve here is y = x^1.2, i.e. a basic darken effect) const curve = [...map((x) => (x ** 1.2).toFixed(4), normRange(N - 1))]; // compute cartesian product to produce RGB tuples const lut = permutations(curve, curve, curve); // alternatively, create LUT which also converts to grayscale... // const lut = take(N * N * N, cycle(map((x) => [x, x, x], curve))); // convert LUT samples to .cube format // (flip order of each tuple since red channel needs change fastest) const cube = transduce( map((x) => x.reverse().join(" ")), str("\n"), lut ); // output LUT with header console.log(`TITLE "example" LUT_3D_SIZE ${N} DOMAIN_MIN 0 0 0 DOMAIN_MAX 1 1 1 ${cube} `); ```

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social · Reply to BotKit by Fedify :botkit:

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

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.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@toxi@mastodon.thi.ng

— Earlier today, I published thi.ng/arcball, a small new package providing an intuitive click & drag 3D camera view controller which is completely agnostic from any UI/drawing/rendering framework. The library simply provides the (quaternion) maths to translate gesture events into rotations and then computes a view matrix (presumably for WebGL/WebGPU).

The code is ported from the old 2016 Clojure implementation in thi.ng/geom-clj, which itself is based on a 1992 paper (link in readme). Behind the scenes it uses thi.ng/matrices and thi.ng/vectors for various math ops.

There's also a small new example project to show how to use it (mouse & touch events are enabled, but zooming only works via scroll gestures on touchpad or mousewheel):

demo.thi.ng/umbrella/webgl-arc

demo.thi.ng

webgl-arcball · @thi.ng/umbrella

@toxi@mastodon.thi.ng

Wow, just noticed reached 3700 stars on GitHub — I'm celebrating... 🤩🫠

Heartfelt thanks to all of you who've been helping along the way (in any shape & form) and been supporting this work for all these years and across different programming languages/camps! Merci beaucoup!!! Esp. big Thank You's to fellow fediverse people/supporters from various stages of this project: @avi, @made, @lurvey, @alesroubicek, @brandtryan, @latrokles, @rc101, @jeffpalmer, @jack, @Yura, @danielrothaug, @computersandblues, @shiffman... (apologies if I forgot you/others here!) 🙏😍

Not counting the earlier years spent on my related toxiclibs library collection for Java/Processing (developed between ~2006-2012), the larger thi.ng project is now 14+ years old, starting with various 2D/3D geometry and dataviz-related libraries for Clojure/ClojureScript in 2011.

Since 2018 the main focus has been thi.ng/umbrella, a monorepo collection of (so far) 210+ projects/libraries. It will be 8 years old in January and covers an extremely wide spectrum of topics, use cases, data structures and techniques (take a look at the tag cloud on the thi.ng website or the tag browser[1] to explore the scope and related projects).

These 200+ main libraries are NOT forming a monolithic framework and can largely be used individually. However, many of these libraries are complementing each other, or are structured to be composable, expose related functionality at different levels of abstraction and/or are heavily re-use functionality to ensure high code density and small bundle sizes when building large(r) projects. 99% of the packages have NO 3rd party runtime dependencies... The umbrella meta-project also includes 185 commented standalone example projects, hundreds of code snippets in documentation and readme files, illustrating other possible usage & composition patterns.

The total code size of this project is now around 3850 source files, 140k lines of code and 71k lines of comments/docstrings. The example projects add in total another ~35k lines of code & comments. The average package readme size is 11.8KB. 99.9% of this all has been created & maintained by yours truly...

There're still so many unreleased (and useful/interesting!) parts of functionality I've been working on and still need to figure out how to best refactor and package them up (bit by bit) before releasing... we're not done just yet!

There seemingly are quite a few active users (~1.8 million of combined installs per month) and it's so pleasing to see how these tools have matured, are stable/reliable[2] and it confirms to me these efforts were all somehow worth it. Especially this year, I've also spent a lot more time myself using these packages in production, mostly for client projects, but also my own (some of which will be open sourced too). Of course, we all have our own particular likes and preferences for our own tools, but for my kind of work/workflows, provides some of the most varied, productive, _composable_ and malleable tools I've ever used...

Happy coding! 🙌

[1] demo.thi.ng/umbrella/thing-bro

[2] ...even many of those packages which still manage to have a v0.x.y version number, often for years already! My release tool only creates new major versions when there're breaking changes, so if the API is already stable, the version stays at 0.x — I just need to manually bump some of them to a v1.0... 😅

@toxi@mastodon.thi.ng

— Thanks to a user suggestion, I've added support for declarative canvas pixel density adjustments in the following packages:

- thi.ng/hiccup-canvas
- thi.ng/hdom-canvas
- thi.ng/rdom-canvas

By default canvas components defined via the latter two packages are defaulting to use the current `window.devicePixelRatio`, but this can now be overridden via the new `__dpr` control attribute to force a certain pixel density. For example, set it to 4 to create a 4x larger canvas in terms of pixel dimensions, but keep the apparent display size the same. Likewise, for performance reasons, it might be useful to keep the pixel density at 1 (or lower), even if the current screen would have a higher density.

More info in this readme section (the hiccup-canvas package is the shared "low-level" backend for the other two UI packages, which also have updated readmes):

docs.thi.ng/umbrella/hiccup-ca

Btw. There were also several other recent additions/releases, but since there're hardly ever any reactions to these announcements, I've reduced my messages about project updates posted here. Please let me know if I should change my mind... :)

docs.thi.ng

@thi.ng/hiccup-canvas

Documentation for @thi.ng/hiccup-canvas

@toxi@mastodon.thi.ng

For some more WIP snapshots of STRATA, a generative system I've been on/off working on since 2014 (in Clojure/TypeScript/Zig, originally for the cover design of HOLO magazine), loosely based on 1950s research/experiments by Barricelli, somewhat related to cellular automata and extended to use a different and much larger set of "reproduction/collision rules" for (often) more complex outcomes. It's a hard system to tweak and curate, but I'm still in love with the resulting structures/textures (reminiscent of thin section petrography), so I keep returning to it every now and then...

Previously:
mastodon.thi.ng/@toxi/tagged/S

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.
ALT text

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.
ALT text

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.
ALT text

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.
ALT text

Abstract, colorful & highly detailed pixel texture, resulting from a cellular-automata-like simulation generation process.

@toxi@mastodon.thi.ng

MonochromeEvolutionaryBioDigitalCellularAutomataSimulation

Unlike the recently shared[1] multi-cellular struggles, these here are some selected research stills (handpicked from tens of thousands) of only single CA configurations (aka mono-cultures) which I found interesting/promising and which were then used as raw ingredients/candidates for my infinitely evolving C-SCAPE project[2]...

Each of these cellular automata is 1.5D, meaning each pixel row is one generation, but I allowed the neighborhoods to be flexible, larger (potentially discontinuous), and in some cases extended to enable access to cell states in previous generations (i.e. a form of temporal short term memory). This leads to all sorts of much more interesting and complex outcomes than "traditional" (aka textbook) 1-dimensional CA setups...

More details in the readme of the related open source project:
thi.ng/cellular

[1] mastodon.thi.ng/@toxi/11552640
[2] art.thi.ng/c-scape

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.
ALT text

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.
ALT text

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of a regular pattern.
ALT text

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of a regular pattern.

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.
ALT text

Abstract monochrome still image of a 1.5D cellular automata simulation, showing the evolution of almost geometric/architectural features from an initial seed generation of just noise.

@jnkrtech@treehouse.systems

New blog post is up! This is a deep dive into continuation-passing style in TypeScript. (No, I'm not talking about asynchronous callbacks.)

jnkr.tech/blog/cps-in-ts

Let me know what you think and if you have any questions I can answer!

jnkr.tech

Continuation-Passing Style in TypeScript · Programming should be enjoyable

Tail recursion, resumable exceptions, and more

@hongminhee@hollo.social
@hongminhee@hollo.social
@hongminhee@hollo.social
@hongminhee@hollo.social
@toxi@mastodon.thi.ng

Maybe a good opportunity to illustrate the purpose of one of the more uncommon packages in : The thi.ng/hex package provides hexadecimal formatters for a variety of word sizes (4-64 bits) and also a customizable hex dump facility, which is super useful for analyzing, debugging & reverse engineering binary data or file formats from within a NodeJS REPL session (my main dev env & workflow), but of course can also be used in other situations... This has already saved me countless of times...

Cropped screensho of a NodeJS REPL session showing an hexdump of a chunk of binary PDF data (trying to analyze why an earlier parse error occurred...)
ALT text

Cropped screensho of a NodeJS REPL session showing an hexdump of a chunk of binary PDF data (trying to analyze why an earlier parse error occurred...)

@toxi@mastodon.thi.ng

Tags are sets. Many apps support tagging of content, but most of them (incl. Mastodon) treat tags only as singular/isolated topic filters, akin to a flat folder-based approach. But tagging can be so, so much more powerful when treating tags as sets and offering users the possibility to combine and query tagged content as sets (think Venn diagrams), i.e. allowing tags to be combined using AND/OR/NOT aka intersection/union/difference operations...

Below is a simple query engine to do just that in ~40 lines of code (sans comments), incl. using an extensible interpreter for a simple Lisp-like S-Expression language to define arbitrarily complex nested tag queries (the code is actually lifted & simplified from my personal knowledge graph tooling, also talked about here recently[1]...)

gist.github.com/postspectacula

For example, the query:

`(and (or 'Alps' 'PNW') (or 'LandscapePhotography' 'NaturePhotography') (not 'Monochrome'))`

...would select all items which have been tagged with `Alps` OR `PNW`, AND have at least one of the two photography tags given, but have NOT the `Monochrome` tag.

Whilst this syntax is probably alien-looking to the average user, it'd would be fairly straightforward to create visual/structural UIs for defining such queries (over the past 20 years I've done that myself several times already), heck even a SLM (small language model) could be used to translate natural language into such query expressions — what matters here is the widespread lack of treating tags this way in terms of conceptual/data modeling in most applications. Imagine being able to use hashtags this way on Mastodon to assemble personalized timelines (and extend the system to not just deal with hashtags, but other post metadata/provenance too)...

The code example illustrates how, with the right tools, such features are actually not hard to implement (or to integrate into existing apps). The example uses the following packages for its key functionality:

- thi.ng/associative: Set-theory operations, custom Map/Set data types (unused here)
- thi.ng/lispy: Customizable/extensible S-expression parser, interpreter & runtime
- thi.ng/oquery: Optimized object and array pattern query engine

[1] mastodon.thi.ng/@toxi/11549755

Syntax highlighted TypeScript sourcecode of the linked code example...
ALT text

Syntax highlighted TypeScript sourcecode of the linked code example...

@toxi@mastodon.thi.ng

Been updating my personal Mastodon tooling to download and convert my bookmarked toots. Here's how little code is needed to download a single message and convert its HTML content into Markdown, all using these packages:

- thi.ng/hiccup: Interop data format (i.e. just nested JS arrays) to encode hierarchical documents
- thi.ng/hiccup-html-parse: Parses HTML into hiccup format
- thi.ng/hiccup-markdown: Serialize hiccup to Markdown (also includes a Markdown parser to hiccup, but not used here)
- thi.ng/zipper: Functional tree editing, manipulation & navigation (here to clean/transform the parsed HTML document)

Edit: Gist version of this example code:
gist.github.com/postspectacula

Syntax colored TypeScript source code:

import { parseHtml } from "@thi.ng/hiccup-html-parse";
import { serialize } from "@thi.ng/hiccup-markdown";
import { arrayZipper, type Location } from "@thi.ng/zipper";

// load a Mastodon status via API
const res = await (
	await fetch("https://mastodon.thi.ng/api/v1/statuses/115464108396925195")
).json();

// parse HTML content into thing/hiccup format (nested JS arrays)
const parsed = parseHtml(res.content, {
	whitespace: true,
	ignoreAttribs: ["class"],
}).result!;

// structure of parsed example:
// [["p", {}, "text"], ["p", {}, ...], ...]

// recursively traverse result document/array using thi.ng/zipper
// and replace all <span> elements with their raw text body
let loc: Location<any> | undefined = arrayZipper(parsed);
while (loc) {
	loc = loc.next;
	if (Array.isArray(loc?.node) && loc?.node[0] == "span")
		loc = loc.replace(loc.node[2]);
	if (loc?.next == null) break;
}

// serialize hiccup to markdown
console. log(serialize(loc?.root, null));

/*
Result (in markdown format), omitted here due to alt text limits
*/
ALT text

Syntax colored TypeScript source code: import { parseHtml } from "@thi.ng/hiccup-html-parse"; import { serialize } from "@thi.ng/hiccup-markdown"; import { arrayZipper, type Location } from "@thi.ng/zipper"; // load a Mastodon status via API const res = await ( await fetch("https://mastodon.thi.ng/api/v1/statuses/115464108396925195") ).json(); // parse HTML content into thing/hiccup format (nested JS arrays) const parsed = parseHtml(res.content, { whitespace: true, ignoreAttribs: ["class"], }).result!; // structure of parsed example: // [["p", {}, "text"], ["p", {}, ...], ...] // recursively traverse result document/array using thi.ng/zipper // and replace all <span> elements with their raw text body let loc: Location<any> | undefined = arrayZipper(parsed); while (loc) { loc = loc.next; if (Array.isArray(loc?.node) && loc?.node[0] == "span") loc = loc.replace(loc.node[2]); if (loc?.next == null) break; } // serialize hiccup to markdown console. log(serialize(loc?.root, null)); /* Result (in markdown format), omitted here due to alt text limits */

@yabuki@pao.moe
@toxi@mastodon.thi.ng

Some details about the recently updated/fixed thi.ng/color package: The color scheme creation strategy functions (analog/complementary/triadic/tetradic/monochrome etc.) are all accepting base colors in any format now, but do their computation and provide results in LCH space only. I've updated/extended the readme with some basic code examples (incl. result swatches) how to use these functions — something I thought I did already 3 years ago, but obviously didn't... mea culpa! 😇

Note: The package also provides more powerful declarative, parametric approaches to color scheme generation (see 2nd image, link in alt text), plus there's also thi.ng/color-palettes (3rd image) which provides 255 manually created palettes (image based & curated by yours truly, used for many of own art projects...) and includes composable query operators to select palettes based on different criteria...

Screenshot of excerpt of the thi.ng/color package readme about declarative/parametric color scheme generation. Direct link to relevant section: https://github.com/thi-ng/umbrella/blob/develop/packages/color/README.md#color-theme-generation
ALT text

Screenshot of excerpt of the thi.ng/color package readme about declarative/parametric color scheme generation. Direct link to relevant section: https://github.com/thi-ng/umbrella/blob/develop/packages/color/README.md#color-theme-generation

Screenshot of excerpt of the thi.ng/color package readme discussing color scheme strategies. Direct link to relevant section: https://github.com/thi-ng/umbrella/blob/develop/packages/color/README.md#color-theme-strategies
ALT text

Screenshot of excerpt of the thi.ng/color package readme discussing color scheme strategies. Direct link to relevant section: https://github.com/thi-ng/umbrella/blob/develop/packages/color/README.md#color-theme-strategies

Screenshot of excerpt of the thi.ng/color-palettes package readme showing swatches of the most recently added themes...
ALT text

Screenshot of excerpt of the thi.ng/color-palettes package readme showing swatches of the most recently added themes...

@toxi@mastodon.thi.ng
False-color barren glacial landscape near Bernina Pass, Switzerland.
ALT text

False-color barren glacial landscape near Bernina Pass, Switzerland.

False-color high-alpine tundra landscape with large boulders.
ALT text

False-color high-alpine tundra landscape with large boulders.

False-color sunset over a craggy cliff and forest during summer solstice.
ALT text

False-color sunset over a craggy cliff and forest during summer solstice.

False-color forest reflecting in a mountain lake during early morning
ALT text

False-color forest reflecting in a mountain lake during early morning

@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@toxi@mastodon.thi.ng

An update: After several failed publish attempts, more searching, (re)reading and experimenting for the past 4 hours, I've now figured out a solution using granular access tokens... But to summarize & document the issues, in case someone else encounters the same pain points:

1) There seems to be a new incompatibility between the NPM auth changes and running `yarn npm publish --access public`. After working successfully for the past 8 years, that command now gives me 404, even after re-authenticating. It just doesn't seem to pick up the auth token configured in `$HOME/.npmrc`. As result I've now switched all my publish commands to just be `npm publish --access public`. That seems to work!

2) The wording about the 50 package limit on the NPM auth token docs is very confusing: "Each token can access up to 50 organizations, and up to either 50 packages, 50 scopes, or a combination of 50 packages and scopes." As written, this reads like these limits are omnipresent for each token, but in fact one can also create tokens which can access ALL packages under your control. The 50 limit only seems to apply when creating token which is only allowed a subset...

Summa summarum, it is after all (updates to thi.ng/geom, bug fixes for thi.ng/args) and I can now proceed to enjoy the start of the Glühwein season on this cold Friday night... 🎉

thi.ng

Declarative, functional & typechecked CLI argument/options parser, value coercions etc.

@julian@fietkau.social · Reply to Julian Fietkau

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!

Fedify 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:

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

https://fedify.dev/

@toxi@mastodon.thi.ng

Published another couple of new versions of thi.ng/genart-api, mainly involving updates to the Layer (layer.com) platform adapter, adding config options and minor quality of life improvements (e.g. handling of private [aka artist-only] params)

I also updated the readme, clarifying the current versioning scheme: For ease of use and to avoid guess work about compatibility, currently all packages in this repo are published using a shared version identifier. With the release of v1.0.0, this will switch to independent semantic versioning, with support package versions aligned to the major versions of the main API.

After over a year of development, dogfooding it and using it successfully without any friction for already a dozen art pieces/projects, I'd actually consider the main API to be pretty much v1.0.0 already (even though it's current v0.33.0). So the switch will happen soon!

If you've have any issues or feature requests, please file them via the issue tracker (or write back here to discuss)! Thanks! :)

thi.ng

Platform independent API for browser-based algorithmic/generative/procedural art

@toxi@mastodon.thi.ng

Just pushed a new version of thi.ng/genart-api (v0.31.0) with these updates:

- (Art) platform adapters can now have an optional `.configure({...})` method to customize platform-specific behaviors. To ensure future portability of your artwork (between different art platforms), calls to this method should be done from outside the artwork, i.e. via an additional `<script>` in the HTML wrapper.
- Of the provided platform adapters, so far only the Layer adapter supports any options, but I'm also working on a new one for my website which will require other options and there are more use cases for which this will come in handy without adding any complexity to the overall system...
- Updated param change handling in the Layer platform adapter, which now supports auto-reload for params whose update behavior has been set to `reload`. More info here: docs.thi.ng/genart-api/adapter

docs.thi.ng

@genart-api/adapter-layer

Documentation for @genart-api/adapter-layer

@vbfox@hachyderm.io

Tried again to switch from prettier to (@biomejs) on work projects.

Good news is that formatting formating works well and prettier compatibility is now near perfect.

Bad news are that it doesn't yet format sass or yaml, the VSCode extension is invasive and configuration file is still horrible.

🤷‍♂️ will try again in 6 months

@toxi@mastodon.thi.ng

(Yet another) 1-minute excerpt of an variation, one of my recent algorithmic/generative realtime animation art pieces, constantly evolving and exhibited exclusively on Layer.

Very much love this color theme, especially after ~15 seconds... 🤌

(See above hashtag for other clips)

Made with ❤️ and my opensource thi.ng/umbrella tools...


Short animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways.
ALT text

Short animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways.

@toxi@mastodon.thi.ng

Another 1-minute excerpt of an variation, one of my recent algorithmic/generative realtime animation art pieces, constantly evolving and exhibited exclusively on Layer.

(See above hashtag for other clips)

Made with ❤️ and my opensource thi.ng/umbrella tools...


Short animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways. Meditative character. At times reminiscent of bright skies
ALT text

Short animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways. Meditative character. At times reminiscent of bright skies

@toxi@mastodon.thi.ng

Just pushed an update for thi.ng/genart-api (v0.29.0) which now supports dynamic switching of time providers. This is useful for situations where you want to switch from realtime animation to offline-based timing, e.g. to export high-resolution image sequences and give the browser time to grab & encode each frame and reduce related memory pressure...

For example, your animation loop can now have something like this below to switch time providers based on a certain start frame for recording:

```
$genart.setUpdate((time, frame) => {
if (frame === 1000) {
// switch to non-realtime animation:
// wait 250ms between frames w/ 60 fps reference frame rate
// start frame for new time provider is current frame + 1
$genart.setTimeProvider(
$genart.time.offline(250, 60, frame + 1)
);
}
// actual animation logic
// ...
return true;
});
```

thi.ng

thi.ng/genart-api

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

@toxi@mastodon.thi.ng

Been working on some additions/adjustments for , one of my recent algorithmic/generative art pieces, currently shown exclusively on Layer.

Here's a 3 minute segment (of an infinite realtime animation). Give it time to develop/change! Fullscreen playback probably best...

Made with thi.ng/shader-ast (transpile TypeScript to GLSL) & thi.ng/webgl-shadertoy

Let's hope the video compression gods are kind to this one...

(Ps. Alas Firefox still doesn't support Rec.2020 color in video, so use Chrome/Safari for best viewing experience)

3m20s animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways. Meditative character. At times reminiscent of sunrise/sunset skies
ALT text

3m20s animation of abstract complex wispy, etheric, cloud-like & fractal-like forms and color washes, constantly evolving, morphing, obscuring and revealing themselves in unpredictable ways. Meditative character. At times reminiscent of sunrise/sunset skies

@toxi@mastodon.thi.ng

— New version 3.1.0 of the recently talked about thi.ng/args package, a declarative & functional CLI argument parser & app framework. I updated the arg specifications to be fully self-describing & serializable (with minor exceptions), and streamlined the API for factory functions to define the specs.

Why is this useful? For example, now I can (already have!) implemented a CLI as separate short-lived client/process which only acts as RPC frontend/proxy for the actual CLI commands defined & executed in a long running app server, which is heavily based on a plugin architecture. Each plugin can contribute any number of CLI commands, each with its own set of args/options... When the CLI client app is launched, it first retrieves a list of these registered commands and all their options from the server, then uses the thi.ng/args CLI framework to select the right command, validate its options or display formatted usage info. If all is ok, the command is then triggered via an HTTP request to the app server, executes there and the command's log messages are send back as response...

Block diagram giving a highlevel overview of a software architecture consisting of: app server, router, CLI and a number of plugins. These app component interact with each other via registrations and delegations. A separate box "CLI RPC" relates to a separate client app which only interacts with the app server and is used as remote frontend for invoking commands inside the (much longer running) main app.
ALT text

Block diagram giving a highlevel overview of a software architecture consisting of: app server, router, CLI and a number of plugins. These app component interact with each other via registrations and delegations. A separate box "CLI RPC" relates to a separate client app which only interacts with the app server and is used as remote frontend for invoking commands inside the (much longer running) main app.

@toxi@mastodon.thi.ng

Finally got around documenting a little more the small CLI app "framework" I've been using for almost a dozen projects now (incl. several work projects). The package in question is now already 3 years old (thi.ng/args), but I've only just managed now to add a basic, commented usage example for this `cliApp()` feature to the readme:

Defining a multi-command CLI app (incl. two sub-commands):
github.com/thi-ng/umbrella/blo

Also part of this: I've refactored a few other projects to simplify their CLI handling using this `cliApp()` wrapper (project links are in the above readme, in case you'd like to see more advanced/realworld uses...) One of the (non-public) work projects ended up consisting of up to a dozen sub-commands and I found this declarative and modular setup to be very, very helpful (and elegant)...

github.com

umbrella/packages/args/README.md at develop · thi-ng/umbrella

⛱ Broadly scoped ecosystem & mono-repository of 210 TypeScript projects (and ~185 examples) for general purpose, functional, data driven development - thi-ng/umbrella

@cryptadamist@universeodon.com

Ω🪬Ω
(the customizable timeline algorithm / filtering system for your Mastodon feed) v1.2.2 is deployed now. Has a switch that makes sure any / users / etc. that you follow are displayed as filter options even if they don't meet the minimum number of recent toots threshold.

Also a bunch of bug fixes and small improvements.

* Try it here: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action (slightly outdated): universeodon.com/@cryptadamist

screenshot of fedialgo demo
ALT text

screenshot of fedialgo demo

@cryptadamist@universeodon.com

Ω🪬Ω
(the customizable timeline algorithm / filtering system for your Mastodon feed) v1.2.2 is deployed now. Has a switch that makes sure any / users / etc. that you follow are displayed as filter options even if they don't meet the minimum number of recent toots threshold.

Also a bunch of bug fixes and small improvements.

* Try it here: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action (slightly outdated): universeodon.com/@cryptadamist

screenshot of fedialgo demo
ALT text

screenshot of fedialgo demo

@cryptadamist@universeodon.com

Ω🪬Ω
(the customizable timeline algorithm / filtering system for your Mastodon feed) v1.2.2 is deployed now. Has a switch that makes sure any / users / etc. that you follow are displayed as filter options even if they don't meet the minimum number of recent toots threshold.

Also a bunch of bug fixes and small improvements.

* Try it here: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action (slightly outdated): universeodon.com/@cryptadamist

screenshot of fedialgo demo
ALT text

screenshot of fedialgo demo

@cryptadamist@universeodon.com

Ω🪬Ω
(the customizable timeline algorithm / filtering system for your Mastodon feed) v1.2.2 is deployed now. Has a switch that makes sure any / users / etc. that you follow are displayed as filter options even if they don't meet the minimum number of recent toots threshold.

Also a bunch of bug fixes and small improvements.

* Try it here: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action (slightly outdated): universeodon.com/@cryptadamist

screenshot of fedialgo demo
ALT text

screenshot of fedialgo demo

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@toxi@mastodon.thi.ng

Speaking of new tools: Here's some other open-ended and work-in-progress tooling I published recently:

Assorted CLI utilities for data wrangling & media conversion
codeberg.org/thi.ng/thing-tools

This is (will be) a Swiss-army knife type multi-tool for frequent little tasks I've been encountering and not found satisfactory equivalent other solutions for. So far, there're only two commands published, but a dozen or so more are to come (for which I still have more cleaning up to do, also in upstream projects):

- CSV-to-JSON parsing/conversion, with configurable filtering, renaming and column value coercions
- De-dupe lines with support for regexp-based inclusions, exclusions and pattern-based uniqueness. Patterns can be read from files.

The readme contains installation instructions and documentation for all commands, their options and some example use cases. E.g. I regularly use the `dedupe-lines` command to cleanup my `.bash_history` file.

Using bun.sh, the tool can be compiled into a standalone executable.

All commands share common infrastructure of the main CLI tooling (based on thi.ng/args and many other thi.ng/umbrella packages). This reduces the code size of each command and makes it trivial to add additional commands (or share functionality, invoke some of those other commands for sub-tasks). There're also re-usable CLI arg specs to provide a uniform "API" for certain types of parameters.

Some of the still unreleased commands are for `ffmpeg` workflows/tasks, will update when ready...

thi.ng

thi.ng/umbrella

@toxi@mastodon.thi.ng

Since I've just been asked again if I could use more topic-specific accounts and not mix my photography with other topics — Unfortunately, nope! I'm on a single user managed instance and cannot create new accounts on this server nor do I want to create an account for every single topic I'm interested in or posting about. However, you can filter my posts by hashtags, which I'm trying to use consistently (also for my own purposes)...

Hashtags can be browsed individually, subscribed to (via Mastodon) or even syndicated via RSS, e.g.

Browse:
mastodon.thi.ng/@toxi/tagged/L

RSS:
mastodon.thi.ng/@toxi/tagged/L

My most commonly used tags are:

Photography:
(my B&W photos)

Open source projects:

Art:

Music:

AI relatated:

Education/research:

Hope that helps!

@fireisgood@app.wafrn.net

The new settings.service.ts file btw


#wafrn #javascript #typescript
Screenshot of a neovim session. The screen is zoomed very far out and split vertically into six sections. Each section shows around 150 lines of code from the file.
ALT text

Screenshot of a neovim session. The screen is zoomed very far out and split vertically into six sections. Each section shows around 150 lines of code from the file.

@fireisgood@app.wafrn.net

The new settings.service.ts file btw


#wafrn #javascript #typescript
Screenshot of a neovim session. The screen is zoomed very far out and split vertically into six sections. Each section shows around 150 lines of code from the file.
ALT text

Screenshot of a neovim session. The screen is zoomed very far out and split vertically into six sections. Each section shows around 150 lines of code from the file.

@zkat@toot.cat

cross-posting my little rant about stuff here:

Random NPM thoughts of the day:

  1. The primary NPM registry should be obsoleted entirely ASAP
  2. JSR does not do anywhere near as much as it should, and it's probably too late to fix.
  3. A proper successor must only support "standard" JS, though temporarily accepting "strippable types" is ok rn
  4. All packages MUST be ESM (JSR ok here)
  5. MUST include docstrings on all publicly-reachable interfaces.
  6. MUST NOT include any type of dependency other than a named registry dependency with a semver version (no git deps etc)
  7. MUST have a non-trivial README.
  8. MUST be tied to a PUBLIC repo.
  9. MUST NOT have install scripts (yeah sorry, the fight's over)
  10. MUST clearly include a license, even if the license is "source available, not open source". This restriction MUST NOT limit to OSI's ridiculous list.
  11. MUST have a name that is scoped to its publishing user/org (@foo/bar)All of the above constraints MUST be checked at publish time.

Furthermore, the registry MUST provide the following, based on this:

  1. Full browsable (published) package sources, right on the site. With linkable paths. None of this absolute trash NPM decided to do.
  2. Autogenerated API docs.
  3. Lower-traffic packages that have not had a new version in 6 months should be completely delisted. They can be installed, with a warning printed.
  4. Usernames/org names and package names must employ a suitably-aggressive levenshtein distance for potential conflicts. This should be aggressive.
  5. Packages cannot be transferred between accounts, and it's against policy to allow others access to your personal account. Orgs can work around this.
  6. Top 1000 packages (maybe more) have all new publishes put on hold for 7 days, and placed into a public review queue, overridden by [tbd?staff?]
  7. Y'all aren't gonna like this but: package installation should be reasonably throttled. Both to keep costs down, and to encourage people to do something less lazy than "I'm just going to install all 2k dependencies on CI every time I push a docs change". It's wasteful and harmful for many reasons.

I think that's all I got off the top of my head for now.

There's honestly a lot of stuff that could be done on the client side to make life better, too, and y'all know I have a ton of thoughts on that, but I wanted to rant about registries for a bit, esp now that the NPM registry is crumbling.

@hongminhee@hollo.social

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

hackers.pub

Optique 0.4.0: Better help, rich docs, and Temporal support

Optique 0.4.0 introduces enhancements to streamline CLI development in TypeScript. This release focuses on improving help text organization through labeled merge groups and a new `group()` combinator, making complex CLIs more user-friendly by organizing options under clear sections. Comprehensive documentation support is added via the `run()` function, allowing brief descriptions, detailed explanations, and footers without altering parser definitions. The update also includes Temporal API support with the `@optique/temporal` package, enabling type-safe parsing for dates, times, and time zones. Improved type inference for `merge()` and `tuple()` combinators enhances type safety, alongside minor breaking changes. These updates aim to make CLI construction more intuitive and maintainable, offering developers greater control over user experience and code structure.

@hongminhee@hackers.pub

We're excited to announce Optique 0.4.0, which brings significant improvements to help text organization, enhanced documentation capabilities, and introduces comprehensive Temporal API support.

Optique is a type-safe combinatorial CLI parser for TypeScript that makes building command-line interfaces intuitive and maintainable. This release focuses on making your CLI applications more user-friendly and maintainable.

Better help text organization

One of the most visible improvements in Optique 0.4.0 is the enhanced help text organization. You can now label and group your options more effectively, making complex CLIs much more approachable for users.

Labeled merge groups

The merge() combinator now accepts an optional label parameter, solving a common pain point where developers had to choose between clean code structure and organized help output:

// Before: unlabeled merged options appeared scattered
const config = merge(connectionOptions, performanceOptions);

// Now: group related options under a clear section
const config = merge(
  "Server Configuration",  // New label parameter
  connectionOptions,
  performanceOptions
);

This simple addition makes a huge difference in help text readability, especially for CLIs with many options spread across multiple reusable modules.

The resulting help output clearly organizes options under the Server Configuration section:

Demo app showcasing labeled merge groups
Usage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries
       INTEGER

Server Configuration:
  --host STRING               Server hostname or IP address
  --port INTEGER              Port number for the connection
  --timeout INTEGER           Connection timeout in seconds
  --retries INTEGER           Number of retry attempts

The new group() combinator

For cases where merge() doesn't apply, the new group() combinator lets you wrap any parser with a documentation label:

// Group mutually exclusive options under a clear section
const outputFormat = group(
  "Output Format",
  or(
    map(flag("--json"), () => "json"),
    map(flag("--yaml"), () => "yaml"),
    map(flag("--xml"), () => "xml"),
  )
);

This is particularly useful for organizing mutually exclusive flags, multiple inputs, or any parser that doesn't natively support labeling. The resulting help text becomes much more scannable and user-friendly.

Here's how the grouped output format options appear in the help text:

Demo app showcasing group combinator
Usage: demo-group.ts --json
       demo-group.ts --yaml
       demo-group.ts --xml

Output Format:
  --json                      Output in JSON format
  --yaml                      Output in YAML format
  --xml                       Output in XML format

Rich documentation support

Optique 0.4.0 introduces comprehensive documentation fields that can be added directly through the run() function, eliminating the need to modify parser definitions for documentation purposes.

Brief descriptions, detailed explanations, and footers

Both @optique/core/facade and @optique/run now support brief, description, and footer options through the run() function:

import { run } from "@optique/run";
import { message } from "@optique/core/message";

const result = run(parser, {
  brief: message`A powerful data processing tool`,
  description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
  footer: message`Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs`,
  help: "option"
});

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

The complete help output demonstrates the rich documentation features with brief description, detailed explanation, option descriptions, default values, and footer information:

A powerful data processing tool
Usage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRING

This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]
  --verbose STRING            Verbosity level

Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

Display default values

A frequently requested feature is now available: showing default values directly in help text. Enable this with the new showDefault option when using withDefault():

const parser = object({
  port: withDefault(
    option("--port", integer(), { description: message`Server port number` }),
    3000,
  ),
  format: withDefault(
    option("--format", string(), { description: message`Output format` }),
    "json",
  ),
});

run(parser, { showDefault: true });

// Or with custom formatting:
run(parser, {
  showDefault: {
    prefix: " (default: ",
    suffix: ")"
  }  // Shows: --port (default: 3000)
});

Default values are automatically dimmed when colors are enabled, making them visually distinct while remaining readable.

The help output shows default values clearly marked next to each option:

Usage: demo-defaults.ts [--port INTEGER] [--format STRING]

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]

Temporal API support

Optique 0.4.0 introduces a new package, @optique/temporal, providing comprehensive support for the modern Temporal API. This brings type-safe parsing for dates, times, durations, and time zones:

import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";

const parser = object({
  // Parse ISO 8601 timestamps
  timestamp: option("--at", instant()),

  // Parse durations like "PT30M" or "P1DT2H"
  timeout: option("--timeout", duration()),

  // Parse zoned datetime with timezone info
  meeting: option("--meeting", zonedDateTime()),
});

The temporal parsers return native Temporal objects with full functionality:

const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
  const instant = result.value;
  console.log(`UTC: ${instant.toString()}`);
  console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}

Install the new package with:

npm add @optique/temporal

Improved type inference

The merge() combinator now supports up to 10 parsers (previously 5), and the tuple() parser has improved type inference using TypeScript's const type parameter. These enhancements enable more complex CLI structures while maintaining perfect type safety.

Breaking changes

While we've maintained backward compatibility for most APIs, there are a few changes to be aware of:

  • The Parser.getDocFragments() method now uses DocState<TState> instead of direct state values (only affects custom parser implementations)
  • The merge() combinator now enforces stricter type constraints at compile time, rejecting non-object-producing parsers

Learn more

For a complete list of changes, bug fixes, and improvements, see the full changelog.

Check out the updated documentation:

Installation

Upgrade to Optique 0.4.0:

npm update @optique/core @optique/run
# or
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0

Add temporal support (optional):

npm add @optique/temporal
# or
deno add jsr:@optique/temporal

We hope these improvements make building CLI applications with Optique even more enjoyable. As always, we welcome your feedback and contributions on GitHub.

github.com

GitHub - dahlia/optique: Type-safe combinatorial CLI parser for TypeScript

Type-safe combinatorial CLI parser for TypeScript. Contribute to dahlia/optique development by creating an account on GitHub.

@hongminhee@hollo.social

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

hackers.pub

Optique 0.4.0: Better help, rich docs, and Temporal support

Optique 0.4.0 introduces enhancements to streamline CLI development in TypeScript. This release focuses on improving help text organization through labeled merge groups and a new `group()` combinator, making complex CLIs more user-friendly by organizing options under clear sections. Comprehensive documentation support is added via the `run()` function, allowing brief descriptions, detailed explanations, and footers without altering parser definitions. The update also includes Temporal API support with the `@optique/temporal` package, enabling type-safe parsing for dates, times, and time zones. Improved type inference for `merge()` and `tuple()` combinators enhances type safety, alongside minor breaking changes. These updates aim to make CLI construction more intuitive and maintainable, offering developers greater control over user experience and code structure.

@hongminhee@hackers.pub

We're excited to announce Optique 0.4.0, which brings significant improvements to help text organization, enhanced documentation capabilities, and introduces comprehensive Temporal API support.

Optique is a type-safe combinatorial CLI parser for TypeScript that makes building command-line interfaces intuitive and maintainable. This release focuses on making your CLI applications more user-friendly and maintainable.

Better help text organization

One of the most visible improvements in Optique 0.4.0 is the enhanced help text organization. You can now label and group your options more effectively, making complex CLIs much more approachable for users.

Labeled merge groups

The merge() combinator now accepts an optional label parameter, solving a common pain point where developers had to choose between clean code structure and organized help output:

// Before: unlabeled merged options appeared scattered
const config = merge(connectionOptions, performanceOptions);

// Now: group related options under a clear section
const config = merge(
  "Server Configuration",  // New label parameter
  connectionOptions,
  performanceOptions
);

This simple addition makes a huge difference in help text readability, especially for CLIs with many options spread across multiple reusable modules.

The resulting help output clearly organizes options under the Server Configuration section:

Demo app showcasing labeled merge groups
Usage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries
       INTEGER

Server Configuration:
  --host STRING               Server hostname or IP address
  --port INTEGER              Port number for the connection
  --timeout INTEGER           Connection timeout in seconds
  --retries INTEGER           Number of retry attempts

The new group() combinator

For cases where merge() doesn't apply, the new group() combinator lets you wrap any parser with a documentation label:

// Group mutually exclusive options under a clear section
const outputFormat = group(
  "Output Format",
  or(
    map(flag("--json"), () => "json"),
    map(flag("--yaml"), () => "yaml"),
    map(flag("--xml"), () => "xml"),
  )
);

This is particularly useful for organizing mutually exclusive flags, multiple inputs, or any parser that doesn't natively support labeling. The resulting help text becomes much more scannable and user-friendly.

Here's how the grouped output format options appear in the help text:

Demo app showcasing group combinator
Usage: demo-group.ts --json
       demo-group.ts --yaml
       demo-group.ts --xml

Output Format:
  --json                      Output in JSON format
  --yaml                      Output in YAML format
  --xml                       Output in XML format

Rich documentation support

Optique 0.4.0 introduces comprehensive documentation fields that can be added directly through the run() function, eliminating the need to modify parser definitions for documentation purposes.

Brief descriptions, detailed explanations, and footers

Both @optique/core/facade and @optique/run now support brief, description, and footer options through the run() function:

import { run } from "@optique/run";
import { message } from "@optique/core/message";

const result = run(parser, {
  brief: message`A powerful data processing tool`,
  description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
  footer: message`Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs`,
  help: "option"
});

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

The complete help output demonstrates the rich documentation features with brief description, detailed explanation, option descriptions, default values, and footer information:

A powerful data processing tool
Usage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRING

This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]
  --verbose STRING            Verbosity level

Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

Display default values

A frequently requested feature is now available: showing default values directly in help text. Enable this with the new showDefault option when using withDefault():

const parser = object({
  port: withDefault(
    option("--port", integer(), { description: message`Server port number` }),
    3000,
  ),
  format: withDefault(
    option("--format", string(), { description: message`Output format` }),
    "json",
  ),
});

run(parser, { showDefault: true });

// Or with custom formatting:
run(parser, {
  showDefault: {
    prefix: " (default: ",
    suffix: ")"
  }  // Shows: --port (default: 3000)
});

Default values are automatically dimmed when colors are enabled, making them visually distinct while remaining readable.

The help output shows default values clearly marked next to each option:

Usage: demo-defaults.ts [--port INTEGER] [--format STRING]

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]

Temporal API support

Optique 0.4.0 introduces a new package, @optique/temporal, providing comprehensive support for the modern Temporal API. This brings type-safe parsing for dates, times, durations, and time zones:

import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";

const parser = object({
  // Parse ISO 8601 timestamps
  timestamp: option("--at", instant()),

  // Parse durations like "PT30M" or "P1DT2H"
  timeout: option("--timeout", duration()),

  // Parse zoned datetime with timezone info
  meeting: option("--meeting", zonedDateTime()),
});

The temporal parsers return native Temporal objects with full functionality:

const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
  const instant = result.value;
  console.log(`UTC: ${instant.toString()}`);
  console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}

Install the new package with:

npm add @optique/temporal

Improved type inference

The merge() combinator now supports up to 10 parsers (previously 5), and the tuple() parser has improved type inference using TypeScript's const type parameter. These enhancements enable more complex CLI structures while maintaining perfect type safety.

Breaking changes

While we've maintained backward compatibility for most APIs, there are a few changes to be aware of:

  • The Parser.getDocFragments() method now uses DocState<TState> instead of direct state values (only affects custom parser implementations)
  • The merge() combinator now enforces stricter type constraints at compile time, rejecting non-object-producing parsers

Learn more

For a complete list of changes, bug fixes, and improvements, see the full changelog.

Check out the updated documentation:

Installation

Upgrade to Optique 0.4.0:

npm update @optique/core @optique/run
# or
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0

Add temporal support (optional):

npm add @optique/temporal
# or
deno add jsr:@optique/temporal

We hope these improvements make building CLI applications with Optique even more enjoyable. As always, we welcome your feedback and contributions on GitHub.

github.com

GitHub - dahlia/optique: Type-safe combinatorial CLI parser for TypeScript

Type-safe combinatorial CLI parser for TypeScript. Contribute to dahlia/optique development by creating an account on GitHub.

@hongminhee@hollo.social

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

hackers.pub

Optique 0.4.0: Better help, rich docs, and Temporal support

Optique 0.4.0 introduces enhancements to streamline CLI development in TypeScript. This release focuses on improving help text organization through labeled merge groups and a new `group()` combinator, making complex CLIs more user-friendly by organizing options under clear sections. Comprehensive documentation support is added via the `run()` function, allowing brief descriptions, detailed explanations, and footers without altering parser definitions. The update also includes Temporal API support with the `@optique/temporal` package, enabling type-safe parsing for dates, times, and time zones. Improved type inference for `merge()` and `tuple()` combinators enhances type safety, alongside minor breaking changes. These updates aim to make CLI construction more intuitive and maintainable, offering developers greater control over user experience and code structure.

@hongminhee@hackers.pub

We're excited to announce Optique 0.4.0, which brings significant improvements to help text organization, enhanced documentation capabilities, and introduces comprehensive Temporal API support.

Optique is a type-safe combinatorial CLI parser for TypeScript that makes building command-line interfaces intuitive and maintainable. This release focuses on making your CLI applications more user-friendly and maintainable.

Better help text organization

One of the most visible improvements in Optique 0.4.0 is the enhanced help text organization. You can now label and group your options more effectively, making complex CLIs much more approachable for users.

Labeled merge groups

The merge() combinator now accepts an optional label parameter, solving a common pain point where developers had to choose between clean code structure and organized help output:

// Before: unlabeled merged options appeared scattered
const config = merge(connectionOptions, performanceOptions);

// Now: group related options under a clear section
const config = merge(
  "Server Configuration",  // New label parameter
  connectionOptions,
  performanceOptions
);

This simple addition makes a huge difference in help text readability, especially for CLIs with many options spread across multiple reusable modules.

The resulting help output clearly organizes options under the Server Configuration section:

Demo app showcasing labeled merge groups
Usage: demo-merge.ts --host STRING --port INTEGER --timeout INTEGER --retries
       INTEGER

Server Configuration:
  --host STRING               Server hostname or IP address
  --port INTEGER              Port number for the connection
  --timeout INTEGER           Connection timeout in seconds
  --retries INTEGER           Number of retry attempts

The new group() combinator

For cases where merge() doesn't apply, the new group() combinator lets you wrap any parser with a documentation label:

// Group mutually exclusive options under a clear section
const outputFormat = group(
  "Output Format",
  or(
    map(flag("--json"), () => "json"),
    map(flag("--yaml"), () => "yaml"),
    map(flag("--xml"), () => "xml"),
  )
);

This is particularly useful for organizing mutually exclusive flags, multiple inputs, or any parser that doesn't natively support labeling. The resulting help text becomes much more scannable and user-friendly.

Here's how the grouped output format options appear in the help text:

Demo app showcasing group combinator
Usage: demo-group.ts --json
       demo-group.ts --yaml
       demo-group.ts --xml

Output Format:
  --json                      Output in JSON format
  --yaml                      Output in YAML format
  --xml                       Output in XML format

Rich documentation support

Optique 0.4.0 introduces comprehensive documentation fields that can be added directly through the run() function, eliminating the need to modify parser definitions for documentation purposes.

Brief descriptions, detailed explanations, and footers

Both @optique/core/facade and @optique/run now support brief, description, and footer options through the run() function:

import { run } from "@optique/run";
import { message } from "@optique/core/message";

const result = run(parser, {
  brief: message`A powerful data processing tool`,
  description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
  footer: message`Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs`,
  help: "option"
});

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

The complete help output demonstrates the rich documentation features with brief description, detailed explanation, option descriptions, default values, and footer information:

A powerful data processing tool
Usage: demo-rich-docs.ts [--port INTEGER] [--format STRING] --verbose STRING

This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]
  --verbose STRING            Verbosity level

Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs

These documentation fields appear in both help output and error messages (when configured), providing consistent context throughout your CLI's user experience.

Display default values

A frequently requested feature is now available: showing default values directly in help text. Enable this with the new showDefault option when using withDefault():

const parser = object({
  port: withDefault(
    option("--port", integer(), { description: message`Server port number` }),
    3000,
  ),
  format: withDefault(
    option("--format", string(), { description: message`Output format` }),
    "json",
  ),
});

run(parser, { showDefault: true });

// Or with custom formatting:
run(parser, {
  showDefault: {
    prefix: " (default: ",
    suffix: ")"
  }  // Shows: --port (default: 3000)
});

Default values are automatically dimmed when colors are enabled, making them visually distinct while remaining readable.

The help output shows default values clearly marked next to each option:

Usage: demo-defaults.ts [--port INTEGER] [--format STRING]

  --port INTEGER              Server port number [3000]
  --format STRING             Output format [json]

Temporal API support

Optique 0.4.0 introduces a new package, @optique/temporal, providing comprehensive support for the modern Temporal API. This brings type-safe parsing for dates, times, durations, and time zones:

import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";

const parser = object({
  // Parse ISO 8601 timestamps
  timestamp: option("--at", instant()),

  // Parse durations like "PT30M" or "P1DT2H"
  timeout: option("--timeout", duration()),

  // Parse zoned datetime with timezone info
  meeting: option("--meeting", zonedDateTime()),
});

The temporal parsers return native Temporal objects with full functionality:

const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
  const instant = result.value;
  console.log(`UTC: ${instant.toString()}`);
  console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}

Install the new package with:

npm add @optique/temporal

Improved type inference

The merge() combinator now supports up to 10 parsers (previously 5), and the tuple() parser has improved type inference using TypeScript's const type parameter. These enhancements enable more complex CLI structures while maintaining perfect type safety.

Breaking changes

While we've maintained backward compatibility for most APIs, there are a few changes to be aware of:

  • The Parser.getDocFragments() method now uses DocState<TState> instead of direct state values (only affects custom parser implementations)
  • The merge() combinator now enforces stricter type constraints at compile time, rejecting non-object-producing parsers

Learn more

For a complete list of changes, bug fixes, and improvements, see the full changelog.

Check out the updated documentation:

Installation

Upgrade to Optique 0.4.0:

npm update @optique/core @optique/run
# or
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0

Add temporal support (optional):

npm add @optique/temporal
# or
deno add jsr:@optique/temporal

We hope these improvements make building CLI applications with Optique even more enjoyable. As always, we welcome your feedback and contributions on GitHub.

github.com

GitHub - dahlia/optique: Type-safe combinatorial CLI parser for TypeScript

Type-safe combinatorial CLI parser for TypeScript. Contribute to dahlia/optique development by creating an account on GitHub.

@develwithoutacause@techhub.social

Over the last few days while working on an upcoming blog post I've performed quite the yak shaving:

1. I wanted to use `@layer` in a demo (ironically one showing that it doesn't solve this particular use case).
2. My auto setup using and failed to parse `@layer`.
3. I upgraded .
4. I removed and replaced it with , which works with `@layer`.
5. I wanted to use `Object.groupBy` here which requires `target: "ES2024"` in .
6. Therefore I needed to upgrade TS.
7. Upgrading TS broke for reasons I couldn't understand.
8. Therefore I migrated from Karma to (which I've wanted to do anyways).
9. Now is confused that I have both an 11ty and Vite project and fails, asking me to pick one.
10. I pick one in `netlify.toml`, but a bug in Netlify refuses to accept it.

answers.netlify.com/t/netlify-

answers.netlify.com

Netlify ignores framework configuration and throws "Error: Detected commands for: Eleventy, Vite."

Hi, I have an Eleventy project and recently added Vitest to it for local testing. This seems to confuse Netlify’s deployment which complains that it doesn’t know which one to use: Error: Detected commands for: Eleventy, Vite. Update your settings to specify which to use. Refer to https://ntl.fyi/dev-monorepo for more information. Ok, well that link says I can explicitly specify the framework. So I tried: [dev] framework = "11ty" And: [dev] framework = "Eleventy" But neither of these work a...

@cryptadamist@universeodon.com
@cryptadamist@universeodon.com
@cryptadamist@universeodon.com
@toxi@mastodon.thi.ng

Yesterday I released new versions of thi.ng/wasm-api (and its add-on packages), a modular and extensible bridge API & toolchain for hybrid JS/TS/Zig/WebAssembly apps, now updated to be compatible with the latest Zig version 0.15.1...

The update addresses some of Zig's breaking syntax & build system changes only, nothing on the JS/TS side has changed. As a result thi.ng/wasm-api-dom has a slightly revised internal structure (also a breaking change, but nothing major & unavoidable). All bundled Zig examples[1] in the repo have been updated too, take a look for reference (if needed).

FYI More details about the Zig language changes here:
ziglang.org/download/0.15.1/re

Specifically, the removal of `usingnamespace` has had a major impact on the existing handling of generated types in these wasm-api support packages (or your own) and now forces an additional level of hierarchy in terms of namespacing. This is because `usingnamespace` enabled a form of namespace merging, which allowed the generated WASM⭤TS interop types (written to their own sourcefile) to be merged/hoisted into the main library module.

For example, previously after importing `const dom = @import("wasm-api-dom");` we could refer to a type via `dom.WindowInfo`. Now with namespace merging removed, we have to use `dom.types.WindowInfo`. As I said, it's not a major departure, but a breaking change nonetheless[2]...

The `build.zig` file bundled with thi.ng/wasm-api is now also only compatible with Zig 0.15.1 (for now). Build files for older Zig versions are still included too (in the same directory)[3].

Lastly, once more for the record: The wasm-api bridge itself is NOT tied to Zig (or a particular version), however it's the main use case/language for my own WebAssembly use cases...

[1] github.com/thi-ng/umbrella/tre (all examples starting with `zig-*`)

[2] The existing design of these modules helped to keep these breaking changes to a minimum in userland code and these updates are all following the same uniform pattern (i.e. exposing interop types via `modulename.types.TypeName`...)

[3] github.com/thi-ng/umbrella/tre

github.com

umbrella/packages/wasm-api at develop · thi-ng/umbrella

⛱ Broadly scoped ecosystem & mono-repository of 210 TypeScript projects (and ~185 examples) for general purpose, functional, data driven development - thi-ng/umbrella

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

@jnkrtech@treehouse.systems

I just published a blog post on the use of type-level programming in TypeScript. It was originally a section of the larger post I’ve been alluding to but I broke it out and expanded it. It’s much more of an opinion piece than most things I write but I’d like to think I have a few decent insights in there. Please check it out and let me know what you think.

jnkr.tech/blog/expressive-type

jnkr.tech

Tradeoffs of highly-expressive types · Programming should be enjoyable

Or, hypertyping considered sometimes harmful, sometimes beneficial, it's complicated really

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

The monorepo has grown to 16 packages!

We've been working hard to make Fedify more modular and easier to integrate with your favorite tools and platforms. From the core framework to database drivers, from CLI tools to web framework integrations—we've got you covered.

Our packages now include:

  • Core framework and CLI tools
  • Web framework integrations: Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit
  • Database drivers: PostgreSQL, Redis, SQLite, AMQP/RabbitMQ
  • Platform integrations: Cloudflare Workers, Deno KV
  • Testing utilities

Each package is available on JSR and/or npm, making it easy to pick exactly what you need for your ActivityPub implementation.

What integration would you like to see next? Let us know!

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).
ALT text

A table showing 16 Fedify packages with three columns: Package name, registry availability (JSR and npm links), and Description. The packages include the core @fedify/fedify framework, CLI toolchain, database drivers (PostgreSQL, Redis, SQLite, AMQP/RabbitMQ), web framework integrations (Express, Hono, H3, Elysia, NestJS, Next.js, SvelteKit, Cloudflare Workers), Deno KV integration, and testing utilities. Most packages are available on both JSR and npm registries, with some exceptions like @fedify/denokv (JSR only) and @fedify/elysia, @fedify/nestjs, @fedify/next (npm only).

@jnkrtech@treehouse.systems

I just published a blog post on the use of type-level programming in TypeScript. It was originally a section of the larger post I’ve been alluding to but I broke it out and expanded it. It’s much more of an opinion piece than most things I write but I’d like to think I have a few decent insights in there. Please check it out and let me know what you think.

jnkr.tech/blog/expressive-type

jnkr.tech

Tradeoffs of highly-expressive types · Programming should be enjoyable

Or, hypertyping considered sometimes harmful, sometimes beneficial, it's complicated really

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@hongminhee@hollo.social

New blog post: Bringing parser combinators to CLI parsing with Optique

  • Compose parsers like or(option("-a"), option("-b"))
  • TypeScript infers discriminated unions automatically
  • Inspired by Haskell's optparse-applicative

https://dev.to/hongminhee/optique-type-safe-cli-parser-combinators-39md

dev.to

Optique: Type-Safe CLI Parser Combinators

Recently, I developed a somewhat experimental CLI parser library called Optique. While it has now...

@bp@social.bennypowers.com

🚀 The CEM Language Server is here!

Remember the frustration of working with custom elements in your editor? No auto-complete for
, no hover docs for attributes, go-to-definition that just... doesn't?

Those dark ages are over.


I built a complete toolchain from scratch in Go that changes everything:

🔬 Analyzes your TypeScript/JavaScript to understand your custom elements
📋 Generates Custom Element Manifest files from your source code
🧠 Provides Language Server Protocol support for amazing editor integration

You get:
🎯 Smart completions for element names, attributes, slots
📚 Hover documentation pulled directly from your code
🔍 Go-to-definition that actually works
Real-time validation and error checking
🛠️ Works with VS Code, Zed, Neovim, Emacs

The beautiful part? It's a complete end-to-end solution. One tool that both understands your code AND provides the editor experience. Zero serialization overhead, perfect consistency.

Built on the shoulders of
@matsuuu 's pioneering work with custom-elements-language-server. This explores a different architectural approach while building on his insights about what features matter most.

Finally - TypeScript-level tooling for our
! 🎉

📖 bennypowers.dev/cem/docs/lsp/
💬 github.com/bennypowers/cem/discussions
🪟 marketplace.visualstudio.com/items?itemName=pwrs.cem-language-server-vscode

marketplace.visualstudio.com

Custom Elements Manifest Language Server - Visual Studio Marketplace

Extension for Visual Studio Code - IDE features for custom elements with intelligent autocomplete and hover documentation

@cryptadamist@universeodon.com

Ω🪬Ω
New version (v1.1.0) of , the customizable timeline algorithm / filtering system for your Mastodon feed, has a toggle switch to allow or disallow the selection of more than one filter option for when you're checking out your favourite hashtags.

* Link: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action (slightly out of date): universeodon.com/@cryptadamist

screenshot of fedialgo multiselect for hashtag filters
ALT text

screenshot of fedialgo multiselect for hashtag filters

@cryptadamist@universeodon.com

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

🎉 Huge shoutout to @2chanhaeng for implementing custom collection dispatchers in through the Korean program!

This incredible contribution adds support for creating arbitrary collections beyond the built-in ones (e.g., outbox, inbox, following, followers). Now developers can expose custom collections like user bookmarks, post categories, or any grouped content through the protocol:

federation
  .setCollectionDispatcher(
    "bookmarks",
    Article,
    "/users/{identifier}/bookmarks",
    async (ctx, values, cursor) => {
      const { posts, nextCursor } = await getBookmarkedPosts(values.identifier, cursor);
      return { items: posts, nextCursor };
    }
  )
  .setCounter(async (ctx, values) =>
    getBookmarkCount(values.identifier)
  );

The implementation is technically excellent with full support, both Collection and OrderedCollection types, cursor-based pagination, authorization predicates, and zero breaking changes. @2chanhaeng delivered not just code but a complete feature with 313 lines of comprehensive documentation, practical examples, and thorough test coverage.

This opens up countless possibilities for ActivityPub applications built with Fedify. From user-specific collections to complex categorization systems, developers now have the flexibility to create any type of custom collection while maintaining full ActivityPub compliance.

Thank you @2chanhaeng for this outstanding contribution and to the OSSCA program for fostering such excellent open source collaboration! 🚀

github.com

Support custom collection dispatchers by 2chanhaeng · Pull Request #332 · fedify-dev/fedify

Summary This PR implements custom collection dispatchers for Fedify, allowing developers to create and expose arbitrary collections of ActivityPub objects beyond the built-in collections (outbox, i...

Fedify 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:

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

https://fedify.dev/

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@manlycoffee@techhub.social

I'm looking for a junior to intermediate developer to work with us to empower everyone to become professional video network operators.

It's on-site, 4 days a week.

I'm specifically looking to onboard someone to our React frontend.

React experience (or even frontend experience) is not a hard requirement.

If you want to learn more about the company itself, check it out here gooseott.com/en/home-en/

And please DM me if you're interested.

gooseott.com

What is Goose? - Goose

Goose is an easy, secure and cost-free OTT solution. Create your own streaming app and monetize your video content without third parties or limitations. Suppliers and Operators Easily create your own OTT streaming platform and offer your subscribers live or video on demand (VOD) content.

@toxi@mastodon.thi.ng

There's a whole bunch of recent updates which I still have to write about, but one of the things is the reworked, improved and more customizable optical flow (aka thi.ng/pixel-flow package). The visualization in this test video is showing it in action via color-coded overlaid flow field vectors (once again worst-case scenario for video compression, let's see how it comes out [or not...])

Test video (a recent POV hiking clip posted a few days ago) showing optical flow information via color-coded overlaid field vectors. The white arrow/triangle in the center shows the current mean flow direction/magnitude
ALT text

Test video (a recent POV hiking clip posted a few days ago) showing optical flow information via color-coded overlaid field vectors. The white arrow/triangle in the center shows the current mean flow direction/magnitude

@cryptadamist@universeodon.com
@cryptadamist@universeodon.com
@joschi@hachyderm.io
@cryptadamist@universeodon.com

Ω🪬Ω
Latest release of , the customizable timeline algorithm / filtering system for your Mastodon feed, lets you blur / hide images marked as sensitive / , which solves the "unwanted dick pics in your feed" issue that can come up when users of one of the more "risque" fediverse servers manage to make one of their favourite hashtags trend.

* Link: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action: universeodon.com/@cryptadamist
* Release notes: github.com/michelcrypt4d4mus/f

screenshot of fedialgo showing an image post from the mastobate.social server has been blurred out
ALT text

screenshot of fedialgo showing an image post from the mastobate.social server has been blurred out

@aartaka@merveilles.town · Reply to Artyom Bologov

> In addition to generic interfaces, we can also create generic classes. Note that it is not possible to create generic enums and namespaces.

So... arbitrary opinionated restrictions in ? Why not generic enums, actually?

@aartaka@merveilles.town · Reply to Artyom Bologov

Oh, so "const" type assertion on tuples means they are "readonly" and "this" in interface definition means the object that interface methods are used on. So TS uses protected keywords for its own purposes without considering how confusing this is. As someone who's into API poetry, I'm infuriated.

@aartaka@merveilles.town · Reply to Artyom Bologov

Okay, so hear me out: literal types (typing the value as literal "foo") are cool, but... providing literally the same value to a literally typed variable might error out because the type of the provided value will be "string" and not ""foo""?! So they just introduced literal types and gave everyone the reason to never use them. I looooooooooove 👺

@aartaka@merveilles.town

Okay, one more hater post: override functions are useless. Their selling point is that you can provide multiple (supposedly compatible) signatures for a function and then process whatever comes in being certain of its type. Except... it only allows one implementation body. So you may have five override signatures, but only one implementation function. And this implementation is doomed to re-invent type/value dispatching, even though TS was supposed to help. To illustrate, here's a simple "take string or int, convert it to int, and print it out" function in , , and

(defmethod foo ((x string))
(foo (parse-integer x)))

(defmethod foo ((x integer))
(format t "~&X is ~d~%" x))

-----------------------------------

function foo (x) {
if (typeof x === "string"){
foo(parseInt(x));
} else {
console.log("X is " + x)
}
}

------------------------------------

function foo(x: number): void;
function foo(x: string): void;
function foo(x: string | number): void {
if (typeof x === "string") {
console.log("X is " + parseInt(x));
} else {
console.log("X is " + x);
}
}

- CL generic function is short and strictly typed.
- JS function is short-ish and does its own type dispatching.
- TS function is LONG and DOES ITS OWN TYPE DISPATCHING. Useless, in other words.

@rauschma@fosstodon.org
@rauschma@fosstodon.org
@cryptadamist@universeodon.com

Ω🪬Ω
new release of , the customizable timeline algorithm / filtering system for your Mastodon feed, counts the number of times each hashtag appears in your timeline even if people don't use a "#" character to give you a better sense of what people are talking about in the Fediverse.

there's a little bit of art vs. science here because some strings are disqualified from this kind of counting (e.g. a word like "the" should not be counted even if some maniac decided to make it a hashtag) so let me know if you see any weirdly high counts.

* Link: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action: universeodon.com/@cryptadamist

screenshot of fedialgo hashtag filters
ALT text

screenshot of fedialgo hashtag filters

@rauschma@fosstodon.org
@cryptadamist@universeodon.com

Ω🪬Ω
new release of , the customizable timeline algorithm / filtering system for your Mastodon feed, counts the number of times each hashtag appears in your timeline even if people don't use a "#" character to give you a better sense of what people are talking about in the Fediverse.

there's a little bit of art vs. science here because some strings are disqualified from this kind of counting (e.g. a word like "the" should not be counted even if some maniac decided to make it a hashtag) so let me know if you see any weirdly high counts.

* Link: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action: universeodon.com/@cryptadamist

screenshot of fedialgo hashtag filters
ALT text

screenshot of fedialgo hashtag filters

@cryptadamist@universeodon.com

Ω🪬Ω
new release of , the customizable timeline algorithm / filtering system for your Mastodon feed, counts the number of times each hashtag appears in your timeline even if people don't use a "#" character to give you a better sense of what people are talking about in the Fediverse.

there's a little bit of art vs. science here because some strings are disqualified from this kind of counting (e.g. a word like "the" should not be counted even if some maniac decided to make it a hashtag) so let me know if you see any weirdly high counts.

* Link: michelcrypt4d4mus.github.io/fe
* Code: github.com/michelcrypt4d4mus/f
* Video of FediAlgo in action: universeodon.com/@cryptadamist

screenshot of fedialgo hashtag filters
ALT text

screenshot of fedialgo hashtag filters

@arendjr@mstdn.social

With this latest PR, inference for `noFloatingPromises` is pushed to over 80% success rate in Vercel's repositories: github.com/biomejs/biome/pull/

While I targeted specific patterns used by their own `swr` library, all the fixes are generically applicable, meaning other code benefits too.

Do you want to use Biome's `noFloatingPromises`, but need support for some library that is important to you? Reach out to us and we can make it happen: biomejs.dev/enterprise/

biomejs.dev

Enterprise Support

Commercial support for Biome

@arendjr@mstdn.social

With this latest PR, inference for `noFloatingPromises` is pushed to over 80% success rate in Vercel's repositories: github.com/biomejs/biome/pull/

While I targeted specific patterns used by their own `swr` library, all the fixes are generically applicable, meaning other code benefits too.

Do you want to use Biome's `noFloatingPromises`, but need support for some library that is important to you? Reach out to us and we can make it happen: biomejs.dev/enterprise/

biomejs.dev

Enterprise Support

Commercial support for Biome

@arendjr@mstdn.social

With this latest PR, inference for `noFloatingPromises` is pushed to over 80% success rate in Vercel's repositories: github.com/biomejs/biome/pull/

While I targeted specific patterns used by their own `swr` library, all the fixes are generically applicable, meaning other code benefits too.

Do you want to use Biome's `noFloatingPromises`, but need support for some library that is important to you? Reach out to us and we can make it happen: biomejs.dev/enterprise/

biomejs.dev

Enterprise Support

Commercial support for Biome

@arendjr@mstdn.social

With Biome v2 reaching ~75% accuracy for the `noFloatingPromises` rule, one might wonder, how?
* First of all keep in mind this is measured on a single (very large) repository. Yours might fare differently depending on libraries/patterns/etc..
* What you're seeing is a successful application of the 80/20 rule, which says that by doing 20% of the work, you can reach 80% of the results. So far we're only scratching the surface of , but for most applications, that's all we need.

@arendjr@mstdn.social

With Biome v2 reaching ~75% accuracy for the `noFloatingPromises` rule, one might wonder, how?
* First of all keep in mind this is measured on a single (very large) repository. Yours might fare differently depending on libraries/patterns/etc..
* What you're seeing is a successful application of the 80/20 rule, which says that by doing 20% of the work, you can reach 80% of the results. So far we're only scratching the surface of , but for most applications, that's all we need.

@arendjr@mstdn.social

With Biome v2 reaching ~75% accuracy for the `noFloatingPromises` rule, one might wonder, how?
* First of all keep in mind this is measured on a single (very large) repository. Yours might fare differently depending on libraries/patterns/etc..
* What you're seeing is a successful application of the 80/20 rule, which says that by doing 20% of the work, you can reach 80% of the results. So far we're only scratching the surface of , but for most applications, that's all we need.

@Alex0007@mastodon.social
Screenshot of a code editor showing a TypeScript definition. The code defines `baseSubmissionOptions` with an explicit `any` type. Below the code, there's a text "Perfect! Now the function is much more optimized. Here's what the final optimized version does:", ironically contradicting the use of `any`, which is considered an improper solution in TypeScript for proper typing.
ALT text

Screenshot of a code editor showing a TypeScript definition. The code defines `baseSubmissionOptions` with an explicit `any` type. Below the code, there's a text "Perfect! Now the function is much more optimized. Here's what the final optimized version does:", ironically contradicting the use of `any`, which is considered an improper solution in TypeScript for proper typing.

@toxi@mastodon.thi.ng

Recently I've combined various functions which I've been using in other projects (e.g. my personal PKM toolchain) and published them as new library thi.ng/text-analysis for better re-use:

- customizable, composable & extensible tokenization (transducer based)
- ngram generation
- Porter-stemming & stopword removal
- vocabulary (bi-directional index) creation
- dense & sparse multi-hot vector encoding/decoding
- histograms (incl. sorted versions)
- tf-idf (term frequency & inverse document frequency), multiple strategies
- k-means clustering (with k-means++ initialization & customizable distance metrics)
- similarity/distance functions (dense & sparse versions)
- central terms extraction

The attached code example (also in the project readme) uses this package to creeate a clustering of all ~210 packages, based on their assigned tags/keywords...

The library is not intended to be a full-blown NLP solution, but I keep on finding myself running into these functions/concepts quite often, and maybe you'll find them useful too...

Commented and syntax-highlighted TypeScript source code/example from the project readme, showing different steps, transformations and analysis results and how to create a k-means clustering of 200+ projects
ALT text

Commented and syntax-highlighted TypeScript source code/example from the project readme, showing different steps, transformations and analysis results and how to create a k-means clustering of 200+ projects

@rauschma@fosstodon.org

: What name do you use for the directory where the transpiled JavaScript resides?

  • dist68 (88%)
  • out1 (1%)
  • js3 (4%)
  • (other—reply with details)5 (6%)
@raphael@mastodon.communick.com

I borrowed a lot of the concepts I used to implement toolkit to implement the local-first client: usage of rdf libraries to process linked data regardless of implementation quirks, first-citizen classes for Actors/Objects/Activities, a handy "Reference" class to work as a container of data that has only URLs instead of documents, etc...

In the process of removing the "server stuff" (database, mostly) I ended up with a small "core" module for typescript.

@toxi@mastodon.thi.ng

— New version of thi.ng/tsne with ~15-20% better performance[1] due to avoiding repeated internal allocations and skipping gradient updates where unnecessary...

[1] Benchmarked with multiple datasets of ~750 items, each with 192 dimensions (now ~165ms @ MBA M1, 2020)...

thi.ng

Highly configurable t-SNE implementation for arbitrary dimensions

@toxi@mastodon.thi.ng

— New version (v0.27.0) of thi.ng/genart-api, a platform-independent extensible API for browser-based computational/algorithmic/generative art projects:

This version features an overhaul of the platform provided PRNG (pseudo-random number generator) handling and makes it easier to create multiple PRNGs for artworks which require/desire them...

Related section in the README:
github.com/thi-ng/genart-api/b

Also, just as a reminder, the project has:

- no external dependencies
- adapters for 3 art platforms (EditArt, fxhash, Layer)
- 6 example projects
- testing/dev sandbox with two parameter editors
- WebAssembly bindings & demo (currently for only)

Happy coding! :)

github.com

genart-api/README.md at main · thi-ng/genart-api

Generalized API for browser-based generative art projects, plug & play support for platform specifics, parameter declarations, GUI creation, IPC - thi-ng/genart-api

@forest_watch_impress@rss-mstdn.studiofreesia.com
@forest_watch_impress@rss-mstdn.studiofreesia.com
@mackuba@martianbase.net

I gotta say, I'm kinda enjoying writing JS in this "JSDocScript" mode 🤔 The code is almost* unchanged except the comments - I really wanted to avoid complicating it or adding more instructions just for the types - but I get most of the advantage of TS in much more confident and faster refactoring.

@toxi@mastodon.thi.ng

(Revisiting an unoptimized old code sketch, semi-fluid screen recording only... Love the contrast between soft gradients and hard edges and the unexpected emergence of shapes [and their disappearance]...)

(Made with thi.ng/shader-ast)

2 min animation of abstract, slowly morphing shapes & complex color gradients/washes... the color theme is somewhere between salmon, pinks, oranges, blues, purples
ALT text

2 min animation of abstract, slowly morphing shapes & complex color gradients/washes... the color theme is somewhere between salmon, pinks, oranges, blues, purples

@arendjr@mstdn.social

Over the weekend, I wrote an overview of Biome's type architecture, including our motivation and a discussion of the constraints that led to this architecture: arendjr.nl/blog/2025/05/biome-

Reply to this post to comment!

arendjr.nl

Biome Type Inference: A Look Behind The Scenes

An in-depth exploration of the architecture powering Biome's type inference.

@arendjr@mstdn.social

Over the weekend, I wrote an overview of Biome's type architecture, including our motivation and a discussion of the constraints that led to this architecture: arendjr.nl/blog/2025/05/biome-

Reply to this post to comment!

arendjr.nl

Biome Type Inference: A Look Behind The Scenes

An in-depth exploration of the architecture powering Biome's type inference.

@arendjr@mstdn.social

Over the weekend, I wrote an overview of Biome's type architecture, including our motivation and a discussion of the constraints that led to this architecture: arendjr.nl/blog/2025/05/biome-

Reply to this post to comment!

arendjr.nl

Biome Type Inference: A Look Behind The Scenes

An in-depth exploration of the architecture powering Biome's type inference.

@toxi@mastodon.thi.ng

More progress: Added a soft global constraint to create more of a (macro)organism feel w/ a sense of belonging and fuzzy boundary. Also slowly updating the behavior/relationship matrix between the six different types now, to create varying temporary alliances...

(Note: Sadly Firefox doesn't respect the Rec2020 color profile in the video, please download or use Chrome or Safari for viewing...)

1 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemone...
ALT text

1 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemone...

@toxi@mastodon.thi.ng

— Just added 35 new color palettes (255 in total now) to thi.ng/color-palettes. All of these are based on images and dominant colors have been extracted via this tool below and then partially hand edited. The SVG swatches were generated via a custom tool (included in the project repo).

The package provides accessors for obtaining themes as CSS hex colors, RGB or LCH tuples. Themes can also be programmatically selected/filtered by a number of composable criteria (examples in the readme)...

demo.thi.ng/umbrella/dominant-

Excerpt from the package readme, showing a table of 18 newly added color themes, each consisting of 6 colors and visualized as 6 swatches.
ALT text

Excerpt from the package readme, showing a table of 18 newly added color themes, each consisting of 6 colors and visualized as 6 swatches.

Excerpt from the package readme, showing a table of 17 newly added color themes, each consisting of 6 colors and visualized as 6 swatches.
ALT text

Excerpt from the package readme, showing a table of 17 newly added color themes, each consisting of 6 colors and visualized as 6 swatches.

@LunaFreyja@hachyderm.io

Is Node.js the future of backend development, or just a beautifully wrapped grenade?

Lately, I see more and more backend systems, yes, even monoliths, built entirely in Node.js, sometimes with server-side rendering layered on top. These are not toy projects. These are services touching sensitive PII data, sometimes in regulated industries.

When I first used Node.js years ago, I remember:
• Security concepts were… let’s say aspirational.
• Licensing hell due to questionable npm dependencies.
• Tests were flaky, with mocking turning into dark rituals.
• Behavior of libraries changed weekly like socks, but more dangerous.
• Internet required to run a “local” build. How comforting.

Even with TypeScript, it all melts back into JavaScript at runtime, a language so flexible it can hang itself.

Sure, SSR and monoliths can simplify architecture. But they also widen the attack surface, especially when:
• The backend is non-compiled.
• Every endpoint is a potential open door.
• The system needs Node + a fleet of dependencies + a container + prayer just to run.

Compare that to a compiled, stateless binary that:
• Runs in a scratch container.
• Requires zero runtime dependencies.
• Has encryption at rest, in transit, and ideally per-user.
• Can be observed, scaled, audited, stateless and destroyed with precision.

I’ve shipped frontends that are static, CDN-delivered, secure by design, and light enough to fit on a floppy disk. By running them with Node, I’m loading gigabytes of unknown tooling to render “Hello, user”.

So I wonder:
Is this the future? Or am I just… old?

Are we replacing mature, scalable architectures with serverless spaghetti and 12-factor mayhem because “it works on Vercel”?

Tell me how you build secure, observable, compliant systems in Node.js.
Genuinely curious.
Mildly terrified and maybe old.

Compiled Languages vs NodeJs picture
ALT text

Compiled Languages vs NodeJs picture

@toxi@mastodon.thi.ng

Found some time last night to implement multi-behaviors and I'm very excited about where this is going... 😍 The video shows 6 different types interacting with (and avoiding) each other. Next step is to vary the behavior matrix over time, causing changing alliances and breakup behaviors...

See for more context...

(Note: Sadly Firefox doesn't respect the Rec2020 color profile in the video, please download or use Chrome or Safari for viewing...)

2 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..
ALT text

2 minute generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. The boids are grouped in 6 different types. The colors are chosen from gradients. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..

@zeab@fosstodon.org

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. 🫠

@zeab@fosstodon.org

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. 🫠

@zeab@fosstodon.org

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. 🫠

@JohnsDaily@mastodon.social
@JohnsDaily@mastodon.social
@deno_land@fosstodon.org
@toxi@mastodon.thi.ng

🚀 — I wonder how many other FLOSS devs are sitting on code for ~8 years prior to first release... In one of these cases (many others readily available in my stash 🙃), triggered by recent major updates to the thi.ng/vectors library, I've refactored (almost 100% rewritten) and applied the same approach to the new/old package:

thi.ng/tensors

This package provides 1D/2D/3D/4D tensors, supporting different storage implementations (currently still all CPU side only) and an extensible set of polymorphic tensor operations (currently ~45 math ops, incl. matrix-matrix/matrix-vector products, reductions, argmin/max, activation functions etc.). The tensor classes themselves also provide several zero-copy slicing, re-ordering, clipping, extraction functions, most of them type-safe.

The original (private) version was heavily reliant on dynamic code generation, which has now been replaced with higher-order functions to provide various dimension-optimized versions of all operations.

This package is NOT specifically aimed at machine learning, even though it could probably used for some tasks in that realm (likely with extra hand holding). There are many other use cases for this kind of data structure...

Also new in other packages in this release cycle (incl. some code examples):

- docs.thi.ng/umbrella/arrays/fu
- docs.thi.ng/umbrella/bidir-ind
- docs.thi.ng/umbrella/transduce

docs.thi.ng

binned | @thi.ng/transducers

Documentation for @thi.ng/transducers

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@toxi@mastodon.thi.ng

Added a new convenience transducer for clipping and binning values, e.g. as preparation step for histogram generation whilst working in the REPL. New release forthcoming. A small code example attached (actually taken from the doc string of the new `binned()` transducer).

Screenshot of syntax-highlighted TypeScript source code to compute histogram of 1 million gaussian random samples (aka normal distribution), using binned values and discard those outside configured interval. The histogram is then sorted by (bin) position and the values plotted as ANSI-art diagram
ALT text

Screenshot of syntax-highlighted TypeScript source code to compute histogram of 1 million gaussian random samples (aka normal distribution), using binned values and discard those outside configured interval. The histogram is then sorted by (bin) position and the values plotted as ANSI-art diagram

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@toxi@mastodon.thi.ng

Similar to my piece from last year (check the hashtag for references), these current explorations make me fully appreciate all the research, efforts and supporting hardware behind the DCI-P3 & Rec.2020 color spaces. The intensity (and subtlety) of some colors & combinations are just stunning (to me), and I don't mean this in any ableist way (just enjoying whilst I still can!)...

Also still amazed that something like this runs at a smooth 60fps @ 2160x2160 UHD resolution on a mobile device with a just Snapdragon 2 chipset... As part of my advisory role @ day job, over the past few months I've been tasked with optimizing artworks for almost a dozen generative/algorithmic artists, often achieving 2-4x framerate improvements... Very much feeling a longer blog post re: code craft vs code art coming up, hoping to connect them more...

"To understand a program you must become both the machine and the program." — Alan Perlis

(Note: Sadly Firefox does not seem to respect the Rec2020 color profile in the video, please download or use Chrome or Safari for viewing...)

Short generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of intense reds and light blues on dark blue background. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones...
ALT text

Short generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of intense reds and light blues on dark blue background. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones...

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@botkit@hollo.social

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other platforms without the constraints of these existing platforms.

This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.

The Journey to Better Bot Interactions

In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.

Expressing Your Bot's Personality with Custom Emojis

One of the most requested features has been support. Now your bots can truly express their personality with unique visuals that make their messages stand out.

// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
  botkit: { 
    file: `${import.meta.dirname}/images/botkit.png`, 
    type: "image/png" 
  },
  fedify: { 
    url: "https://fedify.dev/logo.png", 
    type: "image/png" 
  }
});

// Use these custom emojis in your messages
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);

With this new API, you can:

Engaging Through Reactions

Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:

// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);

// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);

// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
    { visibility: "direct" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new support enables more cohesive conversation threads:

// Quote another message in your bot's post
await session.publish(
  text`Responding to this interesting point...`,
  { quoteTarget: originalMessage }
);

// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
    { visibility: "direct" }
  );
};

With quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.

Looking Forward

BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.

For complete docs and more examples, visit our docs site.

Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!


BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.

fedify.dev

Fedify

Fedify is a TypeScript library for building federated server apps powered by ActivityPub and other standards, so-called fediverse.

@toxi@mastodon.thi.ng

Been working on various shader & behavior update and options for ... it's all starting to come together! 🤩

(Note: Sadly Firefox does not seem to respect the Rec2020 color profile in the video, please use Chrome or Safari for viewing...)

Short generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of orange and light blues on dark blue background. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..
ALT text

Short generative animation of 1000 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of orange and light blues on dark blue background. Each agent has pseudo-3D appearance and is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..

@deno_land@fosstodon.org
@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

Btw. Here're some more collected links to earlier experiments/stages of development (from the last 1.5 years) — If anything, this all is yet another example of my personal slow-cook art-making/revisiting approach... 😅

SDF obstacles (static & animated):
mastodon.thi.ng/@toxi/11169836
mastodon.thi.ng/@toxi/11169891

Path attraction/following:
mastodon.thi.ng/@toxi/11170412
mastodon.thi.ng/@toxi/11170416

Boids vs. Voronoi:
mastodon.thi.ng/@toxi/11172036

Visualizing motion/direction vectors:
mastodon.thi.ng/@toxi/11168883

mini tutorial:
mastodon.thi.ng/@toxi/11130843

mastodon.thi.ng

Karsten Schmidt (@toxi@mastodon.thi.ng)

Attached: 2 images #HowToThing #027 — Boid/flocking simulation with spatial indexing, configurable behaviors and neighborhood queries to visualize proximity. Key packages: - https://thi.ng/boids: n-dimensional boid simulation with highly configurable behaviors - https://thi.ng/timestep: deterministic fixed timestep simulation updates with state interpolation - https://thi.ng/geom-accel: 2D hash grid spatial indexing and neighborhood region queries The new https://thi.ng/boids package is still in alpha (still working on the API and how the package interfaces with others), but I've been using the underlying implementation for _maaany_ projects since ~2005... The agent/boid behaviors can be highly customized via the given parameters (which can also be dynamically adjusted). As usual with thi.ng packages, the visual representation of the boids is kept completely separate from the sim. The package really only deals with the latter and essentially only processes points in space (and directions, velocities)... However, it's also this separation, which makes it more useful for many different scenarios. Demo: https://demo.thi.ng/umbrella/boid-basics/ Source: https://github.com/thi-ng/umbrella/blob/develop/examples/boid-basics/src/index.ts If you have any questions about this topic or the packages used here, please reply in thread or use the discussion forum (or issue tracker): https://github.com/thi-ng/umbrella/discussions Ps. It's also #ReleaseFriday — check main https://thi.ng/umbrella readme for latest updates/changelogs... 🚀 #ThingUmbrella #Boids #Agents #Simulation #Graphics #TypeScript #JavaScript #GenerativeArt #OpenSource #Tutorial

@toxi@mastodon.thi.ng

Work in progress...

Finally finding some time to continue working on my earlier thi.ng/boids experiments, now also using WebGL instancing and floating point render textures for super-smooth blending/trails to create aesthetics reminiscent of sea anemones...

(Update: I've decided on the beautiful-sounding and fitting as project title...)

(Note: Sadly Firefox does not seem to respect the Rec2020 color profile in the video, please use Chrome or Safari for viewing...)

Short generative animation of 1200 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of cyan, orange, purple. Each boid is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..
ALT text

Short generative animation of 1200 agents/boids exhibiting self-organizing flocking behaviors. Each boid's radius and color is controlled by the distance to its neighbors. The colors are chosen from a gradient of cyan, orange, purple. Each boid is leaving a very slowly fading trail, creating aesthetics reminiscent of sea anemones..

@aral@mastodon.ar.al

Coming tomorrow to Kitten… Kitten icons!

Kitten will have built-in support for the Phosphor icons set with full authoring-time language intelligence where you can search for icons via category and tag (in addition to the canonical alphabetical categorisation).

Thought this was going to take me a few hours but it took a few days thanks to running into issues with size limits, type inference from JavaScript types in modules, etc., with the TypeScript language server but I believe I’ve finally cracked it :)

:kitten: 💕

Screenshot of detail of a Kitten template open in a code editor. Author is editing Kitten component reference in a markdown block, within a H2 header. The caret is at <${kitten.icons.tags. and the autocompletion box is open showing a list of possible fields: a11y, accessibility, accessible, accomodations, account, accounts, accuracy, acrobat, activity, add. The reasty of the line of code reads } weight=duotone size=1.5em/>
ALT text

Screenshot of detail of a Kitten template open in a code editor. Author is editing Kitten component reference in a markdown block, within a H2 header. The caret is at <${kitten.icons.tags. and the autocompletion box is open showing a list of possible fields: a11y, accessibility, accessible, accomodations, account, accounts, accuracy, acrobat, activity, add. The reasty of the line of code reads } weight=duotone size=1.5em/>

@deno_land@fosstodon.org
@deno_land@fosstodon.org
@deno_land@fosstodon.org
@toxi@mastodon.thi.ng

— I just released a new version (v8.0.0) of thi.ng/vectors, an almost complete rewrite of the package with all of its ~900 vector operations. I've updated the Readme with a section of _potentially_ minor breaking changes, however I expect this to be a seamless upgrade for the vast majority of users...

I've recently written more about the reasons and implications of this update and I'll refer you to those posts instead of repeating them once more (see links below).

Just the top-level changes:

- Replaced dynamic code generation with higher-order templating to be usable with strict content security policies (when deployed online)
- New structure allows for vast majority of functions to have doc strings (and they do now)
- More consistent/less confusing naming for some operations
- Potentially improved tree-shaking and smaller project bundle sizes

Related to this update I've also refactored and fixed some bugs in other packages (e.g. color, geom, matrices). As a result both the color & matrix packages are now also free from dynamic codegen and therefore won't cause any problems with strict CSPs

Should you run into any issues regarding this update, please get in touch (also grateful for any other experience/impact reports... 🙏)

More info in these recent posts/threads:

- mastodon.thi.ng/@toxi/11429644
- mastodon.thi.ng/@toxi/11431965
- mastodon.thi.ng/@toxi/11433601

Happy coding!

mastodon.thi.ng

Karsten Schmidt (@toxi@mastodon.thi.ng)

Just a quick #ThingUmbrella update to say that I've already replaced the https://thi.ng/vectors package on the develop branch and after LOTS of deep experimentation have decided NOT to split up the package. There will be a few (minor) breaking changes, mainly because of enforcing more consistent naming and more granularity in some source files (therefore possibly changed imports, though only if you use direct ones for individual functions...). All in all, I've managed to keep the impact on users to a bare minimum (likely unnoticeable for most), even though it's pretty much a complete rewrite of the entire package (with all its ~900 functions)... This package is now almost 10 years old and I'm very happy how this refactor turned out! In terms of file size impact: The FULL minified pkg bundle is now 56.4KB vs previously 48.5KB, however the code density has improved and the brotli-compressed pkg size is only 15.1KB (only 1KB larger than before), which I found absolutely incredible! 🎉 I also have to state once more that this package (and most others in #ThingUmbrella) are _designed for tree shaking_ and bundling. Hardly any project would ever use the full set of functions provided here all at once, most will only use a small/tiny subset... Also — more importantly — many of the 185 example projects in the repo are now showing between 2-25% smaller final bundle sizes. Some also have become slightly larger, but so far I found the most by only ~2%... Related to this change: I've also updated the https://thi.ng/color & https://thi.ng/matrices packages to be free from dynamic code generation now! The only packages still using `new Function(...)` are the following, but for those it's unavoidable and dynamic code generation is a core feature: - https://thi.ng/pixel (custom pixel format definition/compilation) - https://thi.ng/pixel-convolve (custom image convolution kernel compilation) - https://thi.ng/shader-ast-js (Shader AST to JavaScript compilation) I will do more testing over the coming days, then release new version(s) ASAP... #TypeScript #JavaScript #CodeGeneration #Vectors #OpenSource

@toxi@mastodon.thi.ng

Just added some new diagrams to describe the internals of the thi.ng/block-fs block storage & filesystem (incl. some examples) and also added/updated CLI tooling docs...

Screenshot excerpt of the https://thi.ng/block-fs readme, showing the section & diagrams about file system data layouts and internals.
ALT text

Screenshot excerpt of the https://thi.ng/block-fs readme, showing the section & diagrams about file system data layouts and internals.

Screenshot excerpt of the https://thi.ng/block-fs readme, showing the section about the command line tool (incl. terminal output). The first example shows how to convert a file tree from the host system into a single binary blob, the second command example shows how to list files/directories from such a blob
ALT text

Screenshot excerpt of the https://thi.ng/block-fs readme, showing the section about the command line tool (incl. terminal output). The first example shows how to convert a file tree from the host system into a single binary blob, the second command example shows how to list files/directories from such a blob

@toxi@mastodon.thi.ng · Reply to Karsten Schmidt

To put the "large" package size a little more into perspective: I don't know of any other feature-comparable JS vector library which provides all of the following:

- Generic n-dimensional float, int, uint, boolean vectors
- Size optimized versions for 2D/3D/4D (all types)
- Multiple-dispatch wrappers (auto-delegating to available optimized versions)
- Memory-mapped vectors and optimized versions for various memory layouts (e.g. SOA/AOS)
- Optimized versions of many vector-scalar ops
- Optimized compound operations (like multiply-add etc.)
- Vector randomizations (several approaches)
- 99% of GLSL vector operations & conversions
- Vector versions of most of JS `Math` ops
- Vector interpolations (linear, bilinear, cubic, quadratic...)
- 10 different distance functions & metrics
- Swizzling & vector coercion/extension
- Dozens of additional graphics, statistics & ML-related operations

@toxi@mastodon.thi.ng

Just a quick update to say that I've already replaced the thi.ng/vectors package on the develop branch and after LOTS of deep experimentation have decided NOT to split up the package. There will be a few (minor) breaking changes, mainly because of enforcing more consistent naming and more granularity in some source files (therefore possibly changed imports, though only if you use direct ones for individual functions...). All in all, I've managed to keep the impact on users to a bare minimum (likely unnoticeable for most), even though it's pretty much a complete rewrite of the entire package (with all its ~900 functions)... This package is now almost 10 years old and I'm very happy how this refactor turned out!

In terms of file size impact: The FULL minified pkg bundle is now 56.4KB vs previously 48.5KB, however the code density has improved and the brotli-compressed pkg size is only 15.1KB (only 1KB larger than before), which I found absolutely incredible! 🎉 I also have to state once more that this package (and most others in ) are _designed for tree shaking_ and bundling. Hardly any project would ever use the full set of functions provided here all at once, most will only use a small/tiny subset...

Also — more importantly — many of the 185 example projects in the repo are now showing between 2-25% smaller final bundle sizes. Some also have become slightly larger, but so far I found the most by only ~2%...

Related to this change: I've also updated the thi.ng/color & thi.ng/matrices packages to be free from dynamic code generation now! The only packages still using `new Function(...)` are the following, but for those it's unavoidable and dynamic code generation is a core feature:

- thi.ng/pixel (custom pixel format definition/compilation)
- thi.ng/pixel-convolve (custom image convolution kernel compilation)
- thi.ng/shader-ast-js (Shader AST to JavaScript compilation)

I will do more testing over the coming days, then release new version(s) ASAP...

thi.ng

Customizable JS codegen, compiler & runtime for @thi.ng/shader-ast

@company@prorocketeers.com

✌️Neustále hledáme způsoby, jak co nejlépe propojit technologie s reálnými potřebami zákazníků. 🤝

Náš software developer Ondra Sýkora se podělil o svou zkušenost s vývojem e-commerce služby @smontazi , která umožňuje spojit nákup produktu s montážní službou do jedné objednávky.

🔗 Více se dozvíte v rozhovoru:
prorocketeers.com/blog/rezerva 🚀


, ,

Rozhovor o e-commerce startupu ProRocketeers
ALT text

Rozhovor o e-commerce startupu ProRocketeers

@toxi@mastodon.thi.ng

In recent years every spring seems to turn into a period of _massive_ refactoring & restructuring in — maybe it's a form of spring cleaning, even though the reasons[1] are not seasonal... Currently spending my nights reworking the thi.ng/vectors package (likely one of the most comprehensive vector packages available for TS/JS) and trying out different splits/structures, testing their impact on package sizes and usability in existing downstream packages. Currently over 3000 source files with uncommitted changes... aaaarrrgghh! 🤯

Most functions (vector operations) in this package exist in multiple versions (many code generated, but now in need to be updated): Generic n-dimensional, loop-free, optimized 2D/3D/4D versions and strided versions for manipulating vectors views of larger nD data buffers (supporting all kinds of data layouts, incl. AOS, SOA, hybrid...)

[1] mastodon.thi.ng/@toxi/11429644

mastodon.thi.ng

Karsten Schmidt (@toxi@mastodon.thi.ng)

Thanks to @made@mastodon.gamedev.place I recently learned that dynamic code generation doesn't play nice with certain Content Security Policies (CSP). This has a major impact on a few core packages in #ThingUmbrella, like the https://thi.ng/vectors package which contains ~900 vector functions, most of them code generated and optimized for different vector sizes/dimensions (incl. n-dimensional versions). This package (and some others using a similar approach) are key dependencies for dozens of other geometry/visualization related packages... However, I found code generation the only way to practically manage & maintain the sheer amount of functionality provided. Because of this (CSP impact), I've been working on a new code generator, which converts the dynamically generated code into statically generated source code files. This will make the overall initial package size bigger, but this shouldn't be a major problem in practice, since there're also very positive effects, including: - The new format allows for doc strings for _all_ generated vector ops (with the dynamic approach there was no way to properly attach those in TypeScript) - The new file structure (single function per source file) massively helps with dead code elimination when using a bundler, resulting in smaller final file/bundle sizes. When NOT using a bundler, similar filesize savings can be had by using direct imports (to individual functions) rather than full package imports - None of the unused versions need to be code generated at runtime anymore, so also improving startup time The new codegen is already covering around more than a third of the 900 ops. If you want to keep an eye on progress & discussion, follow this issue: https://github.com/thi-ng/umbrella/issues/497 #ThingUmbrella #CodeGenerator #TypeScript #Vector #PSA

@aral@mastodon.ar.al

Coming tomorrow to Kitten… Kitten icons!

Kitten will have built-in support for the Phosphor icons set with full authoring-time language intelligence where you can search for icons via category and tag (in addition to the canonical alphabetical categorisation).

Thought this was going to take me a few hours but it took a few days thanks to running into issues with size limits, type inference from JavaScript types in modules, etc., with the TypeScript language server but I believe I’ve finally cracked it :)

:kitten: 💕

Screenshot of detail of a Kitten template open in a code editor. Author is editing Kitten component reference in a markdown block, within a H2 header. The caret is at <${kitten.icons.tags. and the autocompletion box is open showing a list of possible fields: a11y, accessibility, accessible, accomodations, account, accounts, accuracy, acrobat, activity, add. The reasty of the line of code reads } weight=duotone size=1.5em/>
ALT text

Screenshot of detail of a Kitten template open in a code editor. Author is editing Kitten component reference in a markdown block, within a H2 header. The caret is at <${kitten.icons.tags. and the autocompletion box is open showing a list of possible fields: a11y, accessibility, accessible, accomodations, account, accounts, accuracy, acrobat, activity, add. The reasty of the line of code reads } weight=duotone size=1.5em/>

Fedify 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:

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

https://fedify.dev/

@toxi@mastodon.thi.ng

Thanks to @made I recently learned that dynamic code generation doesn't play nice with certain Content Security Policies (CSP). This has a major impact on a few core packages in , like the thi.ng/vectors package which contains ~900 vector functions, most of them code generated and optimized for different vector sizes/dimensions (incl. n-dimensional versions). This package (and some others using a similar approach) are key dependencies for dozens of other geometry/visualization related packages... However, I found code generation the only way to practically manage & maintain the sheer amount of functionality provided.

Because of this (CSP impact), I've been working on a new code generator, which converts the dynamically generated code into statically generated source code files. This will make the overall initial package size bigger, but this shouldn't be a major problem in practice, since there're also very positive effects, including:

- The new format allows for doc strings for _all_ generated vector ops (with the dynamic approach there was no way to properly attach those in TypeScript)
- The new file structure (single function per source file) massively helps with dead code elimination when using a bundler, resulting in smaller final file/bundle sizes. When NOT using a bundler, similar filesize savings can be had by using direct imports (to individual functions) rather than full package imports
- None of the unused versions need to be code generated at runtime anymore, so also improving startup time

The new codegen is already covering around more than a third of the 900 ops. If you want to keep an eye on progress & discussion, follow this issue:

github.com/thi-ng/umbrella/iss

github.com

[vectors/color] Content Security Policy use of eval / Function · Issue #497 · thi-ng/umbrella

Hi @postspectacular , not sure how you think about this issue, since it goes bit deeper into your vector and color functions: I am using @thi.ng/color in frontend and it imports clamp and later on ...

@jani@fosstodon.org

Snooker is one of my favourite hobbies. I play (badly) and I watch it on TV.

And I've combined the snooker hobby with my programming hobby by writing a simple snooker scoreboard web app. TypeScript and Svelte 5 FTW.

There are many others, but this one's mine, it's free as in beer and free as in freedom. And it respects your privacy.

I call it Groovescore, with a hat-tip to my snooker club Groovetown Jack.

groovescore.app/

Screen shot of a snooker scoreboard application.
ALT text

Screen shot of a snooker scoreboard application.

@deno_land@fosstodon.org

Data analysis in Jupyter notebooks with... TypeScript?! 😱
✅ using `fetch` and other web standards
✅ fast dataframes with nodejs-polars
✅ easy charts with @observablehq
✅ rich interactive UIs with JavaScript

Learn more in this detailed walkthrough 👇
deno.com/blog/exploring-art-wi

deno.com

Exploring Art with TypeScript, Jupyter, Polars, and Observable Plot

With Deno's Jupyter support, you can explore, interact, and create interactive charts with TypeScript and HTML. Here's a tutorial featuring data of over 130,000 famous artworks.

@toxi@mastodon.thi.ng

Just pushed a new version of thi.ng/block-fs, now with additional multi-command CLI tooling to convert & bundle a local file system tree into a single block-based binary blob (e.g. for bundling assets, or distributing a virtual filesystem as part of a web app, or for snapshot testing, or as bridge for WASM interop etc.)

Also new, the main API now includes a `.readAsObjectURL()` method to wrap files as URLs to binary blobs with associated MIME types, thereby making it trivial to use the virtual filesystem for sourcing stored images and other assets for direct use in the browser...

(Ps. For more context see other recent announcement: mastodon.thi.ng/@toxi/11426498)

Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to convert/bundle as filesystem tree)
ALT text

Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to convert/bundle as filesystem tree)

Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to list contents of an already bundled filesystem)
ALT text

Screenshot excerpt from the project readme (link in post) containing information about the CLI wrapper, as well as example usage (here to list contents of an already bundled filesystem)

@deno_land@fosstodon.org

Data analysis in Jupyter notebooks with... TypeScript?! 😱
✅ using `fetch` and other web standards
✅ fast dataframes with nodejs-polars
✅ easy charts with @observablehq
✅ rich interactive UIs with JavaScript

Learn more in this detailed walkthrough 👇
deno.com/blog/exploring-art-wi

deno.com

Exploring Art with TypeScript, Jupyter, Polars, and Observable Plot

With Deno's Jupyter support, you can explore, interact, and create interactive charts with TypeScript and HTML. Here's a tutorial featuring data of over 130,000 famous artworks.

@zkat@toot.cat

my final project as part of my tenure at Microsoft, aside from that NPM patch (lol), is this lil' guy: github.com/microsoft/libsyncrpc

Just a small, but v v fast IPC lib that lets you make synchronous calls to a child process from node, while the child can execute callbacks from you before you return.

I optimized the everloving shit out of this thing, and it ended up being fast enough that the team will be able to use it for the thing that will let you use the Go typescript compiler from JS: you'll just be calling out directly to a Go child.

Literally hundreds of thousands of ops/s :)

github.com

GitHub - microsoft/libsyncrpc: synchronous RPC communication with callbacks for Node.js

synchronous RPC communication with callbacks for Node.js - microsoft/libsyncrpc

@zkat@toot.cat

my final project as part of my tenure at Microsoft, aside from that NPM patch (lol), is this lil' guy: github.com/microsoft/libsyncrpc

Just a small, but v v fast IPC lib that lets you make synchronous calls to a child process from node, while the child can execute callbacks from you before you return.

I optimized the everloving shit out of this thing, and it ended up being fast enough that the team will be able to use it for the thing that will let you use the Go typescript compiler from JS: you'll just be calling out directly to a Go child.

Literally hundreds of thousands of ops/s :)

github.com

GitHub - microsoft/libsyncrpc: synchronous RPC communication with callbacks for Node.js

synchronous RPC communication with callbacks for Node.js - microsoft/libsyncrpc

@davidbisset@phpc.social
@davidbisset@phpc.social
@SocketSecurity@fosstodon.org

Biome has released v2.0 beta with support for custom plugins, domain-specific linting, and multi-file analysis. The update brings type-aware rules to the Rust-powered toolchain. Next up: @biomejs plans to add HTML support and embedded languages in 2025. socket.dev/blog/biome-announce

socket.dev

Biome Announces v2.0 Beta with Plugin System and Type Inform...

Biome's v2.0 beta introduces custom plugins, domain-specific linting, and type-aware rules while laying groundwork for HTML support and embedded langu...

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@toxi@mastodon.thi.ng

Just made my day: "I somehow made it to March 2025 before being aware of thi.ng/ - an incredible mountain of code created primarily by a prolific genius, full of ideas that are like catnip to me."

😂

kylecordes.com/2025/typescript

(Also, to clarify, even though thi.ng/hiccup and a small selection of other thi.ng libs started out porting concepts widely used in Clojure (the language I spent 7 years with previously), in many cases the scope, features, usability & potential use cases have been far extended far beyond their "originals" and it sometimes saddens me that these are often just plainly ignored or mis-labeled/described...)

kylecordes.com

TypeScript HTML generation on the server – Kyle Cordes

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@jonn@social.doma.dev · Reply to Michael U

@jet what happened to ?

I roll out custom implementations based on left and right.

It's quite easy with , and .

Here is a fresh generic ecommerce demo where I was learning for frontend – github.com/cognivore/thegoodsh

Feel free to fork and run with it ♥️

github.com

GitHub - cognivore/thegoodshop

Contribute to cognivore/thegoodshop development by creating an account on GitHub.

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@jutty@bsd.cafe

> HarmonyOS initially began as a project based on the Android Open Source Project and the Linux kernel, allowing compatibility with existing Android apps. In 2023, Huawei introduced HarmonyOS NEXT, a new iteration built on a custom microkernel and proprietary technology frameworks.

> Unlike its predecessor, HarmonyOS NEXT does not support Android or Windows applications. Instead, it uses a native application format based on JavaScript, TypeScript, and an optimized compiler designed to accelerate JavaScript execution. In 2024, Huawei confirmed its plans to replace Windows with HarmonyOS for its upcoming PC models.

> In addition to its HarmonyOS-based PC, Huawei is developing a Linux-based system, according to MyDrivers. The upcoming MateBook D16 Linux Edition will feature the same hardware as the standard MateBook D16, with an unnamed Linux distribution replacing Windows.

techspot.com/news/107169-life-

techspot.com

Huawei to drop Windows, shifting to HarmonyOS and Linux for future PCs

Starting in April 2025, Huawei will launch new PC models that no longer use Windows as their default operating system. According to domestic sources cited by MyDrivers,...

@toxi@mastodon.thi.ng

To avoid a massive OpenCV dependency for a current project I'm involved in, I ended up porting my own homemade, naive optical flow code from 2008 and just released it as a new package. Originally this was written for a gestural UI system for Nokia retail stores (prior to the Microsoft takeover), the package readme contains another short video showing the flow field being utilized to rotate a 3D cube:

thi.ng/pixel-flow

I've also created a small new example project for testing with either webcam or videos:

demo.thi.ng/umbrella/optical-f

20 second screen recording of me waving my hand in camera and visualizing the resulting optical flow field (as blue arrows). The thick red line shows the field's average movement vector for the current frame.
ALT text

20 second screen recording of me waving my hand in camera and visualizing the resulting optical flow field (as blue arrows). The thick red line shows the field's average movement vector for the current frame.

@revathskumar@fosstodon.org

devs,

Since nextjs redirect can't be used inside `try/catch` block, How do you handle the redirections in server actions?

Especially when you don't want to handle `| undefined` in the return type of function in .

As of now I am doing redirection on client.

Is there a better way?

screenshot from nextjs documentation
ALT text

screenshot from nextjs documentation

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@deno_land@fosstodon.org

🚀 Deno v2.2.4 is released:

- Built-in OpenTelemetry support for span context propagators (tracecontext, baggage)
- Built-in OTel tracing for node:http.request
- LSP now starts the TypeScript server lazily

other improvements in the release notes:
github.com/denoland/deno/relea

Release v2.2.4 · denoland/deno

2.2.4 / 2025.03.14 feat(otel): span context propagators (#28460) feat(unstable/otel): add otel tracing to node:http.request (#28463) feat: support FORCE_COLOR (#28490) fix(bench): lower bench time...

@GerryT@mastodon.social
@GerryT@mastodon.social
@deno_land@fosstodon.org
@crnkovic@lor.sh

Made my first steps today with , without a doubt it's the beggining of a great new friendship. Lots of JS5 to Typescript porting ahead. The first thing I'll port is the sqlexecutor family, particularly the executor lib
github.com/allex-libs/postgres

github.com

GitHub - allex-libs/postgresqlexecutor: AllexJS SQL executor for Postgres

AllexJS SQL executor for Postgres. Contribute to allex-libs/postgresqlexecutor development by creating an account on GitHub.

@crnkovic@lor.sh

Made my first steps today with , without a doubt it's the beggining of a great new friendship. Lots of JS5 to Typescript porting ahead. The first thing I'll port is the sqlexecutor family, particularly the executor lib
github.com/allex-libs/postgres

github.com

GitHub - allex-libs/postgresqlexecutor: AllexJS SQL executor for Postgres

AllexJS SQL executor for Postgres. Contribute to allex-libs/postgresqlexecutor development by creating an account on GitHub.

@crnkovic@lor.sh

Made my first steps today with , without a doubt it's the beggining of a great new friendship. Lots of JS5 to Typescript porting ahead. The first thing I'll port is the sqlexecutor family, particularly the executor lib
github.com/allex-libs/postgres

github.com

GitHub - allex-libs/postgresqlexecutor: AllexJS SQL executor for Postgres

AllexJS SQL executor for Postgres. Contribute to allex-libs/postgresqlexecutor development by creating an account on GitHub.

@ekuber@hachyderm.io

I found myself agreeing with everything in this post from Steve:

steveklabnik.com/writing/choos

I don't think that the brigade of "Rewrite it in Rust" people is nearly as common or big as all too often claimed, but for if you ever appreciated what either Steve or I ever had to say, and have an impulse to brigade a project on GutHub or social media (even accidentally! If you arrive early you might not realize 2000 people are coming right after you), please don't. It's pointless. It's draining. It can be abusive. And it's counter productive.

steveklabnik.com

Choosing Languages

@ekuber@hachyderm.io

I found myself agreeing with everything in this post from Steve:

steveklabnik.com/writing/choos

I don't think that the brigade of "Rewrite it in Rust" people is nearly as common or big as all too often claimed, but for if you ever appreciated what either Steve or I ever had to say, and have an impulse to brigade a project on GutHub or social media (even accidentally! If you arrive early you might not realize 2000 people are coming right after you), please don't. It's pointless. It's draining. It can be abusive. And it's counter productive.

steveklabnik.com

Choosing Languages

@Eleandar@framapiaf.org · Reply to elloh

L’objectif est de faciliter le partage d’informations et d’activités.

Cela inclut l’automatisation de l’accueil des nvx membres, la mise en place de forums et chats, un calendrier, un système de petites annonces, des outils pour le reporting des activités, des outils de veille sur des flux RSS ainsi que des interconnexions entre assos et à des sites voisins.

Intéressé ?

avec l'aide des

@erick@gts.erick.sh

I think it’s fun to see all the support and rant reactions about Microsoft rewriting #TypeScript tooling in #Go instead of C# or Rust.

Notice that I said "fun", not "interesting". It’s fun because this is just the latest version of "vim vs. emacs" or "tabs vs. spaces". Everyone has opinions, everyone has their favorite programming language, but at the end of the day, 0% (or a very close number) of the people ranting about it are actually working on the project. It’s always easy to criticize someone else’s work when you have nothing at stake.

@erick@gts.erick.sh

I think it’s fun to see all the support and rant reactions about Microsoft rewriting #TypeScript tooling in #Go instead of C# or Rust.

Notice that I said "fun", not "interesting". It’s fun because this is just the latest version of "vim vs. emacs" or "tabs vs. spaces". Everyone has opinions, everyone has their favorite programming language, but at the end of the day, 0% (or a very close number) of the people ranting about it are actually working on the project. It’s always easy to criticize someone else’s work when you have nothing at stake.

@erick@gts.erick.sh

I think it’s fun to see all the support and rant reactions about Microsoft rewriting #TypeScript tooling in #Go instead of C# or Rust.

Notice that I said "fun", not "interesting". It’s fun because this is just the latest version of "vim vs. emacs" or "tabs vs. spaces". Everyone has opinions, everyone has their favorite programming language, but at the end of the day, 0% (or a very close number) of the people ranting about it are actually working on the project. It’s always easy to criticize someone else’s work when you have nothing at stake.

@kidsan@hachyderm.io

I think it is cool that is being rewritten in a faster language and in my opinion this is the kind of niche where excels. Their reasoning boiling down to Go providing 10x performance for low effort rewrite vs >10x for much more effort in <whatever-language> is what I'd call a pragmatic choice. Not everything needs to be hype-driven development, and I say that as a wannabe.

@josemigt@masto.es

Después de la noticia de que el compilador de TypeScript va a ser reescrito en Go, veo mucha gente de la comunidad de un poco enfadada porque el propio creador de CSharp no haya apostado por el lenguaje que él mismo creó.

Desde luego es curioso. Entiendo que parece que C# queda relegado a lenguaje de aplicaciones empresariales sencillas y si hace falta hacer algo que tenga más ingeniería, hay que ir a las opciones de los mayores.

Me sorprende también que Microsoft no haga
"dogfooding".

Pero quién mejor que el creador de C# para conocer las limitaciones del lenguaje.

@josemigt@masto.es

Después de la noticia de que el compilador de TypeScript va a ser reescrito en Go, veo mucha gente de la comunidad de un poco enfadada porque el propio creador de CSharp no haya apostado por el lenguaje que él mismo creó.

Desde luego es curioso. Entiendo que parece que C# queda relegado a lenguaje de aplicaciones empresariales sencillas y si hace falta hacer algo que tenga más ingeniería, hay que ir a las opciones de los mayores.

Me sorprende también que Microsoft no haga
"dogfooding".

Pero quién mejor que el creador de C# para conocer las limitaciones del lenguaje.

@toxi@mastodon.thi.ng

— One of the recent (already very useful!) new package additions to is:

thi.ng/leaky-bucket

Leaky buckets are commonly used in communication networks for rate limiting, traffic shaping and bandwidth control, but are equally useful in other domains requiring similar constraints.

A Leaky Bucket is a managed counter with an enforced maximum value (i.e. bucket capacity). The counter is incremented for each a new event to check if it can/should be processed. If the bucket capacity has already been reached, the bucket will report an overflow, which we can then handle accordingly (e.g. by dropping or queuing events). The bucket also has a configurable time interval at which the counter is decreasing (aka the "leaking" behavior) until it reaches zero again (i.e. until the bucket is empty). Altogether, this setup can be utilized to ensure both an average rate, whilst also supporting temporary bursting in a controlled fashion...

Related, I've also updated/simplified the rate limiter interceptor in thi.ng/server to utilize this new package...

thi.ng

Minimal HTTP server with declarative routing, static file serving and freely extensible via pre/post interceptors

@Yohei_Zuho@mstdn.y-zu.org
@deno_land@fosstodon.org
@garretble@mastodon.social

I feel stressed today at work.

Getting pushback from my desire to use in our project. Because it "takes too long" to write typings for components.

So in six months when we return to this code, it’ll be super easy to dig through it all if nothing is typed?

How is it easier to find errors in the application when you can fat finger any variable or object member and get away with it (until you run the app and it fails)?

@Yohei_Zuho@mstdn.y-zu.org
@Yohei_Zuho@mstdn.y-zu.org
@Yohei_Zuho@mstdn.y-zu.org
@Yohei_Zuho@mstdn.y-zu.org
@Yohei_Zuho@mstdn.y-zu.org
@hongminhee@hollo.social

Just released 0.9.0! 🎉

This version brings two major improvements to our zero-dependency library for :

  1. New Synchronous Configuration API: You can now configure LogTape synchronously with configureSync(), disposeSync(), and resetSync(). Perfect for simpler setups where you don't need async operations!

  2. Better Runtime Compatibility: We've moved all file-related components to a separate @logtape/file package. This means the core package now works flawlessly across all JavaScript environments—browsers, edge functions, and various bundlers without any file system dependencies.

Plus, we've added level mapping options for console sinks, giving you more control over how your logs appear.

Check out the full release notes for migration details:

https://hackers.pub/@hongminhee/2025/logtape-090

hackers.pub

Hackers' Pub

@hongminhee@hackers.pub

We're excited to announce the release of LogTape 0.9.0! This version brings important improvements to make LogTape more flexible across different JavaScript environments while simplifying configuration for common use cases.

What's New

  • Synchronous Configuration API: Added new synchronous configuration functions for environments where async operations aren't needed or desired
  • Improved Runtime Compatibility: Moved file-system dependent components to a separate package for better cross-runtime support

New Features

Synchronous Configuration API: Simplifying Your Setup

Added synchronous versions of the configuration functions:

These functions offer a simpler API for scenarios where async operations aren't needed, allowing for more straightforward code without awaiting promises. Note that these functions cannot use sinks or filters that require asynchronous disposal (such as stream sinks), but they work perfectly for most common logging configurations.

import { configureSync, getConsoleSink } from "@logtape/logtape";

configureSync({ 
  sinks: {
    console: getConsoleSink(),
  },
  loggers: [
    {
      category: "my-app",
      lowestLevel: "info",
      sinks: ["console"],
    },
  ],
});

Console Sink Enhancements

Breaking Changes

File Sinks Moved to Separate Package: Better Cross-Platform Support

To improve runtime compatibility, file-related sinks have been moved to the @logtape/file package:

This architectural change ensures the core @logtape/logtape package is fully compatible with all JavaScript runtimes, including browsers and edge functions, without introducing file system dependencies. You'll now enjoy better compatibility with bundlers like Webpack, Rollup, and Vite that previously had issues with the file system imports.

Migration Guide

If you were using file sinks, update your imports:

// Before
import { getFileSink, getRotatingFileSink } from "@logtape/logtape";

// After
import { getFileSink, getRotatingFileSink } from "@logtape/file";

Don't forget to install the new package:

# For npm, pnpm, Yarn, Bun
npm add @logtape/file

# For Deno
deno add jsr:@logtape/file

Looking Forward

This release represents our ongoing commitment to making LogTape the most flexible and developer-friendly logging solution for JavaScript and TypeScript applications. We're continuing to improve performance and extend compatibility across the JavaScript ecosystem.

Contributors

Special thanks to Murph Murphy for their valuable contribution to this release.


As always, we welcome your feedback and contributions! Feel free to open issues or pull requests on our GitHub repository.

Happy logging!

github.com

GitHub - dahlia/logtape: Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions - dahlia/logtape

0.9.0をリリースしました!🎉

今回のバージョンでは、TypeScript向けの依存関係ゼロのロギングライブラリに二つの大きな改善を加えました:

  1. 新しい同期設定APIconfigureSync()disposeSync()resetSync()を使って同期的にLogTapeを設定できるようになりました。非同期操作が不要なシンプルな環境に最適です!

  2. ランタイム互換性の向上:ファイル関連のコンポーネントをすべて別パッケージ@logtape/fileに移動しました。これにより、コアパッケージはファイルシステム依存なしで、ブラウザ、エッジ関数、各種バンドラーなど、あらゆるJavaScript環境でシームレスに動作します。

さらに、コンソールシンクにレベルマッピングオプションを追加し、ログの表示方法をより細かく制御できるようになりました。

移行の詳細については、リリースノートをご覧ください。

https://zenn.dev/hongminhee/articles/98989e400c5fcf

zenn.dev

LogTape 0.9.0 リリース:同期設定APIとランタイム互換性の向上

@hongminhee@hollo.social

Just released 0.9.0! 🎉

This version brings two major improvements to our zero-dependency library for :

  1. New Synchronous Configuration API: You can now configure LogTape synchronously with configureSync(), disposeSync(), and resetSync(). Perfect for simpler setups where you don't need async operations!

  2. Better Runtime Compatibility: We've moved all file-related components to a separate @logtape/file package. This means the core package now works flawlessly across all JavaScript environments—browsers, edge functions, and various bundlers without any file system dependencies.

Plus, we've added level mapping options for console sinks, giving you more control over how your logs appear.

Check out the full release notes for migration details:

https://hackers.pub/@hongminhee/2025/logtape-090

hackers.pub

Hackers' Pub

@hongminhee@hackers.pub

We're excited to announce the release of LogTape 0.9.0! This version brings important improvements to make LogTape more flexible across different JavaScript environments while simplifying configuration for common use cases.

What's New

  • Synchronous Configuration API: Added new synchronous configuration functions for environments where async operations aren't needed or desired
  • Improved Runtime Compatibility: Moved file-system dependent components to a separate package for better cross-runtime support

New Features

Synchronous Configuration API: Simplifying Your Setup

Added synchronous versions of the configuration functions:

These functions offer a simpler API for scenarios where async operations aren't needed, allowing for more straightforward code without awaiting promises. Note that these functions cannot use sinks or filters that require asynchronous disposal (such as stream sinks), but they work perfectly for most common logging configurations.

import { configureSync, getConsoleSink } from "@logtape/logtape";

configureSync({ 
  sinks: {
    console: getConsoleSink(),
  },
  loggers: [
    {
      category: "my-app",
      lowestLevel: "info",
      sinks: ["console"],
    },
  ],
});

Console Sink Enhancements

Breaking Changes

File Sinks Moved to Separate Package: Better Cross-Platform Support

To improve runtime compatibility, file-related sinks have been moved to the @logtape/file package:

This architectural change ensures the core @logtape/logtape package is fully compatible with all JavaScript runtimes, including browsers and edge functions, without introducing file system dependencies. You'll now enjoy better compatibility with bundlers like Webpack, Rollup, and Vite that previously had issues with the file system imports.

Migration Guide

If you were using file sinks, update your imports:

// Before
import { getFileSink, getRotatingFileSink } from "@logtape/logtape";

// After
import { getFileSink, getRotatingFileSink } from "@logtape/file";

Don't forget to install the new package:

# For npm, pnpm, Yarn, Bun
npm add @logtape/file

# For Deno
deno add jsr:@logtape/file

Looking Forward

This release represents our ongoing commitment to making LogTape the most flexible and developer-friendly logging solution for JavaScript and TypeScript applications. We're continuing to improve performance and extend compatibility across the JavaScript ecosystem.

Contributors

Special thanks to Murph Murphy for their valuable contribution to this release.


As always, we welcome your feedback and contributions! Feel free to open issues or pull requests on our GitHub repository.

Happy logging!

github.com

GitHub - dahlia/logtape: Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions - dahlia/logtape

@Eliot_L@social.coop

OMFG youtube.com/watch?v=0mCsluv5FX

It's not a port of to . It's a port of doom to the TypeScript type system 🤯

The program is 177 TB!!! 177 TERAbytes!!! It took 12 days to render a single frame, consuming over 100 GB of memory! This is mad science.

youtube.com

TypeScript types can run DOOM

Yep. We got the Doom engine running purely in TypeScript types. Like. For real. We’ve prepared two more videos, one answering “why we did this” (storytim...

@hongminhee@hollo.social

Just released 0.9.0! 🎉

This version brings two major improvements to our zero-dependency library for :

  1. New Synchronous Configuration API: You can now configure LogTape synchronously with configureSync(), disposeSync(), and resetSync(). Perfect for simpler setups where you don't need async operations!

  2. Better Runtime Compatibility: We've moved all file-related components to a separate @logtape/file package. This means the core package now works flawlessly across all JavaScript environments—browsers, edge functions, and various bundlers without any file system dependencies.

Plus, we've added level mapping options for console sinks, giving you more control over how your logs appear.

Check out the full release notes for migration details:

https://hackers.pub/@hongminhee/2025/logtape-090

hackers.pub

Hackers' Pub

@hongminhee@hackers.pub

We're excited to announce the release of LogTape 0.9.0! This version brings important improvements to make LogTape more flexible across different JavaScript environments while simplifying configuration for common use cases.

What's New

  • Synchronous Configuration API: Added new synchronous configuration functions for environments where async operations aren't needed or desired
  • Improved Runtime Compatibility: Moved file-system dependent components to a separate package for better cross-runtime support

New Features

Synchronous Configuration API: Simplifying Your Setup

Added synchronous versions of the configuration functions:

These functions offer a simpler API for scenarios where async operations aren't needed, allowing for more straightforward code without awaiting promises. Note that these functions cannot use sinks or filters that require asynchronous disposal (such as stream sinks), but they work perfectly for most common logging configurations.

import { configureSync, getConsoleSink } from "@logtape/logtape";

configureSync({ 
  sinks: {
    console: getConsoleSink(),
  },
  loggers: [
    {
      category: "my-app",
      lowestLevel: "info",
      sinks: ["console"],
    },
  ],
});

Console Sink Enhancements

Breaking Changes

File Sinks Moved to Separate Package: Better Cross-Platform Support

To improve runtime compatibility, file-related sinks have been moved to the @logtape/file package:

This architectural change ensures the core @logtape/logtape package is fully compatible with all JavaScript runtimes, including browsers and edge functions, without introducing file system dependencies. You'll now enjoy better compatibility with bundlers like Webpack, Rollup, and Vite that previously had issues with the file system imports.

Migration Guide

If you were using file sinks, update your imports:

// Before
import { getFileSink, getRotatingFileSink } from "@logtape/logtape";

// After
import { getFileSink, getRotatingFileSink } from "@logtape/file";

Don't forget to install the new package:

# For npm, pnpm, Yarn, Bun
npm add @logtape/file

# For Deno
deno add jsr:@logtape/file

Looking Forward

This release represents our ongoing commitment to making LogTape the most flexible and developer-friendly logging solution for JavaScript and TypeScript applications. We're continuing to improve performance and extend compatibility across the JavaScript ecosystem.

Contributors

Special thanks to Murph Murphy for their valuable contribution to this release.


As always, we welcome your feedback and contributions! Feel free to open issues or pull requests on our GitHub repository.

Happy logging!

github.com

GitHub - dahlia/logtape: Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions - dahlia/logtape

0.9.0をリリースしました!🎉

今回のバージョンでは、TypeScript向けの依存関係ゼロのロギングライブラリに二つの大きな改善を加えました:

  1. 新しい同期設定APIconfigureSync()disposeSync()resetSync()を使って同期的にLogTapeを設定できるようになりました。非同期操作が不要なシンプルな環境に最適です!

  2. ランタイム互換性の向上:ファイル関連のコンポーネントをすべて別パッケージ@logtape/fileに移動しました。これにより、コアパッケージはファイルシステム依存なしで、ブラウザ、エッジ関数、各種バンドラーなど、あらゆるJavaScript環境でシームレスに動作します。

さらに、コンソールシンクにレベルマッピングオプションを追加し、ログの表示方法をより細かく制御できるようになりました。

移行の詳細については、リリースノートをご覧ください。

https://zenn.dev/hongminhee/articles/98989e400c5fcf

zenn.dev

LogTape 0.9.0 リリース:同期設定APIとランタイム互換性の向上

@hongminhee@hollo.social

Just released 0.9.0! 🎉

This version brings two major improvements to our zero-dependency library for :

  1. New Synchronous Configuration API: You can now configure LogTape synchronously with configureSync(), disposeSync(), and resetSync(). Perfect for simpler setups where you don't need async operations!

  2. Better Runtime Compatibility: We've moved all file-related components to a separate @logtape/file package. This means the core package now works flawlessly across all JavaScript environments—browsers, edge functions, and various bundlers without any file system dependencies.

Plus, we've added level mapping options for console sinks, giving you more control over how your logs appear.

Check out the full release notes for migration details:

https://hackers.pub/@hongminhee/2025/logtape-090

hackers.pub

Hackers' Pub

@hongminhee@hackers.pub

We're excited to announce the release of LogTape 0.9.0! This version brings important improvements to make LogTape more flexible across different JavaScript environments while simplifying configuration for common use cases.

What's New

  • Synchronous Configuration API: Added new synchronous configuration functions for environments where async operations aren't needed or desired
  • Improved Runtime Compatibility: Moved file-system dependent components to a separate package for better cross-runtime support

New Features

Synchronous Configuration API: Simplifying Your Setup

Added synchronous versions of the configuration functions:

These functions offer a simpler API for scenarios where async operations aren't needed, allowing for more straightforward code without awaiting promises. Note that these functions cannot use sinks or filters that require asynchronous disposal (such as stream sinks), but they work perfectly for most common logging configurations.

import { configureSync, getConsoleSink } from "@logtape/logtape";

configureSync({ 
  sinks: {
    console: getConsoleSink(),
  },
  loggers: [
    {
      category: "my-app",
      lowestLevel: "info",
      sinks: ["console"],
    },
  ],
});

Console Sink Enhancements

Breaking Changes

File Sinks Moved to Separate Package: Better Cross-Platform Support

To improve runtime compatibility, file-related sinks have been moved to the @logtape/file package:

This architectural change ensures the core @logtape/logtape package is fully compatible with all JavaScript runtimes, including browsers and edge functions, without introducing file system dependencies. You'll now enjoy better compatibility with bundlers like Webpack, Rollup, and Vite that previously had issues with the file system imports.

Migration Guide

If you were using file sinks, update your imports:

// Before
import { getFileSink, getRotatingFileSink } from "@logtape/logtape";

// After
import { getFileSink, getRotatingFileSink } from "@logtape/file";

Don't forget to install the new package:

# For npm, pnpm, Yarn, Bun
npm add @logtape/file

# For Deno
deno add jsr:@logtape/file

Looking Forward

This release represents our ongoing commitment to making LogTape the most flexible and developer-friendly logging solution for JavaScript and TypeScript applications. We're continuing to improve performance and extend compatibility across the JavaScript ecosystem.

Contributors

Special thanks to Murph Murphy for their valuable contribution to this release.


As always, we welcome your feedback and contributions! Feel free to open issues or pull requests on our GitHub repository.

Happy logging!

github.com

GitHub - dahlia/logtape: Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions - dahlia/logtape

@SocketSecurity@fosstodon.org

🎮 INCREDIBLE achievement: Michigan TypeScript founder Dimitri Mitropoulos (@MiTypeScript) has gotten Doom running purely in TypeScript's type system! 177 TB of types processed over 12 days just for the first frame. 🤯

socket.dev/blog/typescript-typ

socket.dev

Michigan TypeScript Founder Successfully Runs Doom Inside Ty...

Michigan TypeScript founder Dmitri Mitropoulos implements WebAssembly runtime in TypeScript types, enabling Doom to run after processing 177 terabytes...

@deno_land@fosstodon.org

Is there a lint rule that you've always felt was missing? 🤔

With Deno 2.2's new lint plugin system, you can write and publish your own!

For the next week, if you publish a lint rule, you'll get a free prize. 👇

deno.com/blog/lint-rules-conte

deno.com

Publish a lint rule, get a prize

Deno's new lint plugin system means you can extend the deno lint functionality with your own rules. We're giving prizes for anyone who publishes a lint rule this week. Here's how to participate.

@deno_land@fosstodon.org

Is there a lint rule that you've always felt was missing? 🤔

With Deno 2.2's new lint plugin system, you can write and publish your own!

For the next week, if you publish a lint rule, you'll get a free prize. 👇

deno.com/blog/lint-rules-conte

deno.com

Publish a lint rule, get a prize

Deno's new lint plugin system means you can extend the deno lint functionality with your own rules. We're giving prizes for anyone who publishes a lint rule this week. Here's how to participate.

@SocketSecurity@fosstodon.org

🎮 INCREDIBLE achievement: Michigan TypeScript founder Dimitri Mitropoulos (@MiTypeScript) has gotten Doom running purely in TypeScript's type system! 177 TB of types processed over 12 days just for the first frame. 🤯

socket.dev/blog/typescript-typ

socket.dev

Michigan TypeScript Founder Successfully Runs Doom Inside Ty...

Michigan TypeScript founder Dmitri Mitropoulos implements WebAssembly runtime in TypeScript types, enabling Doom to run after processing 177 terabytes...

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@deno_land@fosstodon.org

Is there a lint rule that you've always felt was missing? 🤔

With Deno 2.2's new lint plugin system, you can write and publish your own!

For the next week, if you publish a lint rule, you'll get a free prize. 👇

deno.com/blog/lint-rules-conte

deno.com

Publish a lint rule, get a prize

Deno's new lint plugin system means you can extend the deno lint functionality with your own rules. We're giving prizes for anyone who publishes a lint rule this week. Here's how to participate.

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@deno_land@fosstodon.org

Is there a lint rule that you've always felt was missing? 🤔

With Deno 2.2's new lint plugin system, you can write and publish your own!

For the next week, if you publish a lint rule, you'll get a free prize. 👇

deno.com/blog/lint-rules-conte

deno.com

Publish a lint rule, get a prize

Deno's new lint plugin system means you can extend the deno lint functionality with your own rules. We're giving prizes for anyone who publishes a lint rule this week. Here's how to participate.

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

자매 프로젝트들을 소개해 드리고자 합니다. 애플리케이션 개발을 더 쉽게 만들어주는 관련 도구들입니다:

Fedify :fedify:

Fedify(@fedify)는 ActivityPub와 다른 () 표준을 기반으로 연합 서버 애플리케이션을 구축하기 위한 라이브러리입니다. Activity Vocabulary를 위한 타입 안전한 객체, WebFinger 클라이언트·서버, HTTP Signatures 등를 제공하여 반복적인 코드를 줄이고 애플리케이션 로직에 집중할 수 있게 해줍니다.

Hollo :hollo:

Hollo(@hollo)는 Fedify로 구동되는 1인 사용자용 마이크로블로깅 서버입니다. 1인 사용자를 위해 설계되었지만, ActivityPub를 통해 완전히 연합되어 연합우주 전체의 사용자들과 상호작용할 수 있습니다. Hollo는 Mastodon 호환 API를 구현하여 자체 웹 인터페이스 없이도 대부분의 Mastodon 클라이언트와 호환됩니다.

Hollo는 또한 정식 출시 전에 최신 Fedify 기능을 테스트하는 실험장으로도 활용되고 있습니다.

BotKit :botkit:

BotKit(@botkit)은 저희의 가장 새로운 구성원으로, ActivityPub 봇을 만들기 위해 특별히 설계된 프레임워크입니다. 전통적인 Mastodon 봇과 달리, BotKit은 플랫폼별 제한(글자 수 제한 등)에 구애받지 않는 독립적인 ActivityPub 서버를 만듭니다.

BotKit의 API는 의도적으로 단순하게 설계되어 단일 TypeScript 파일로 완전한 봇을 만들 수 있습니다!


세 프로젝트 모두 @fedify-dev GitHub 조직에서 오픈 소스로 공개되어 있습니다. 각기 다른 목적을 가지고 있지만, ActivityPub 개발을 더 접근하기 쉽게 만들고 연합우주 생태계를 확장한다는 공통된 목표를 공유합니다.

이러한 프로젝트를 사용해보거나 개발에 기여하는 데 관심이 있으시다면, 다음을 확인해보세요:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

We'd like to introduce the project family—a set of related tools that make building applications more accessible:

Fedify :fedify:

Fedify (@fedify) is a library for building federated server applications powered by ActivityPub and other standards. It provides type-safe objects for Activity Vocabulary, WebFinger client/server, HTTP Signatures, and more—eliminating boilerplate code so you can focus on your application logic.

Hollo :hollo:

Hollo (@hollo) is a single-user microblogging server powered by Fedify. While designed for individual users, it's fully federated through ActivityPub, allowing interaction with users across the fediverse. implements Mastodon-compatible APIs, making it compatible with most Mastodon clients without needing its own web interface.

Hollo also serves as our testing ground for bleeding-edge Fedify features before they're officially released.

BotKit :botkit:

BotKit (@botkit) is our newest family member—a framework specifically designed for creating ActivityPub bots. Unlike traditional Mastodon bots, creates standalone ActivityPub servers that aren't constrained by platform-specific limitations (like character counts).

BotKit's API is intentionally simple—you can create a complete bot in a single TypeScript file!


All three projects are open source and hosted under the @fedify-dev GitHub organization. While they serve different purposes, they share common goals: making ActivityPub development more accessible and expanding the fediverse ecosystem.

If you're interested in trying any of these projects or contributing to their development, check out:

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@mapache@hachyderm.io

Very likely today I will start the gen-AI related project for SOMOS.tech. I'll be building from scratch using TypeScript/JavaScript. And when I say from scratch, I mean from ZERO—creating the repo and setting up my VSCode and extensions. Just a fair warning, I'm not a Javascript expert, so expect some learning pains, frustration, and maybe a few cursed words along the way.

@mapache@hachyderm.io

Very likely today I will start the gen-AI related project for SOMOS.tech. I'll be building from scratch using TypeScript/JavaScript. And when I say from scratch, I mean from ZERO—creating the repo and setting up my VSCode and extensions. Just a fair warning, I'm not a Javascript expert, so expect some learning pains, frustration, and maybe a few cursed words along the way.

@mapache@hachyderm.io

I'm going to build building an AI-powered app from scratch, focusing on javascript/typescript/azure and possibly dotnet for SOMOS.tech. I've got about a month to get it done, so it's going to be a wild ride!

I'm going to stream the process live and build in public.

However, due to my peculiar hours, the streaming might come with little to no notice.

@deno_land@fosstodon.org

Heard of Deno but haven't had the time to try it out?

Join Jo Frank at TheJam.dev
where she'll give an introduction to the runtime and its built in tooling to make your developer experience delightful.

Tickets are free, so what are you waiting for?

cfe.dev/events/the-jam-2025/

cfe.dev

TheJam.dev 2025

TheJam.dev is a 2-day virtual conference focused on building modern web applications using full stack JavaScript, static site generators, serverless and more.

@deno_land@fosstodon.org

The next version of Deno will have a super fast JS/TS plugin API for the linter 🎉

Watch @lcasdev write a lint rule to ban string literals in <60 seconds.

This, plus many other goodies, to land next week with Deno 2.2.

@hongminhee@hollo.social

Haven't talked about LogTape in a while—it's a library I made for and . You know how logging can be a pain point in JavaScript/TypeScript development? Well, I tried to address some common frustrations.

What makes it special

Zero dependencies

We've all been there with dependency hell, right? has absolutely no external dependencies. Install it without worrying about bloating your node_modules.

Hierarchical categories

You can organize your logs in a tree structure. Want to save only database-related logs to a file? Easy to do. Child categories can inherit settings from their parents too, which keeps things clean and manageable.

Library-friendly

Writing a library and want to include logs without stepping on your users' toes? LogTape lets you add logging to your library while giving end users complete control over how those logs are handled.

Structured logging

Plain text logs not cutting it? LogTape supports structured logging. Makes log analysis way easier down the road.

Runs anywhere

Works smoothly in Node.js, Deno, Bun, browsers, and even edge functions. No special configuration needed.


Check out https://logtape.org/ if you're interested in learning more.

logtape.org

LogTape

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

@hongminhee@hollo.social

Haven't talked about LogTape in a while—it's a library I made for and . You know how logging can be a pain point in JavaScript/TypeScript development? Well, I tried to address some common frustrations.

What makes it special

Zero dependencies

We've all been there with dependency hell, right? has absolutely no external dependencies. Install it without worrying about bloating your node_modules.

Hierarchical categories

You can organize your logs in a tree structure. Want to save only database-related logs to a file? Easy to do. Child categories can inherit settings from their parents too, which keeps things clean and manageable.

Library-friendly

Writing a library and want to include logs without stepping on your users' toes? LogTape lets you add logging to your library while giving end users complete control over how those logs are handled.

Structured logging

Plain text logs not cutting it? LogTape supports structured logging. Makes log analysis way easier down the road.

Runs anywhere

Works smoothly in Node.js, Deno, Bun, browsers, and even edge functions. No special configuration needed.


Check out https://logtape.org/ if you're interested in learning more.

logtape.org

LogTape

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

@hongminhee@hollo.social

Haven't talked about LogTape in a while—it's a library I made for and . You know how logging can be a pain point in JavaScript/TypeScript development? Well, I tried to address some common frustrations.

What makes it special

Zero dependencies

We've all been there with dependency hell, right? has absolutely no external dependencies. Install it without worrying about bloating your node_modules.

Hierarchical categories

You can organize your logs in a tree structure. Want to save only database-related logs to a file? Easy to do. Child categories can inherit settings from their parents too, which keeps things clean and manageable.

Library-friendly

Writing a library and want to include logs without stepping on your users' toes? LogTape lets you add logging to your library while giving end users complete control over how those logs are handled.

Structured logging

Plain text logs not cutting it? LogTape supports structured logging. Makes log analysis way easier down the road.

Runs anywhere

Works smoothly in Node.js, Deno, Bun, browsers, and even edge functions. No special configuration needed.


Check out https://logtape.org/ if you're interested in learning more.

logtape.org

LogTape

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

@hongminhee@hollo.social

Haven't talked about LogTape in a while—it's a library I made for and . You know how logging can be a pain point in JavaScript/TypeScript development? Well, I tried to address some common frustrations.

What makes it special

Zero dependencies

We've all been there with dependency hell, right? has absolutely no external dependencies. Install it without worrying about bloating your node_modules.

Hierarchical categories

You can organize your logs in a tree structure. Want to save only database-related logs to a file? Easy to do. Child categories can inherit settings from their parents too, which keeps things clean and manageable.

Library-friendly

Writing a library and want to include logs without stepping on your users' toes? LogTape lets you add logging to your library while giving end users complete control over how those logs are handled.

Structured logging

Plain text logs not cutting it? LogTape supports structured logging. Makes log analysis way easier down the road.

Runs anywhere

Works smoothly in Node.js, Deno, Bun, browsers, and even edge functions. No special configuration needed.


Check out https://logtape.org/ if you're interested in learning more.

logtape.org

LogTape

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

@hongminhee@hollo.social

Haven't talked about LogTape in a while—it's a library I made for and . You know how logging can be a pain point in JavaScript/TypeScript development? Well, I tried to address some common frustrations.

What makes it special

Zero dependencies

We've all been there with dependency hell, right? has absolutely no external dependencies. Install it without worrying about bloating your node_modules.

Hierarchical categories

You can organize your logs in a tree structure. Want to save only database-related logs to a file? Easy to do. Child categories can inherit settings from their parents too, which keeps things clean and manageable.

Library-friendly

Writing a library and want to include logs without stepping on your users' toes? LogTape lets you add logging to your library while giving end users complete control over how those logs are handled.

Structured logging

Plain text logs not cutting it? LogTape supports structured logging. Makes log analysis way easier down the road.

Runs anywhere

Works smoothly in Node.js, Deno, Bun, browsers, and even edge functions. No special configuration needed.


Check out https://logtape.org/ if you're interested in learning more.

logtape.org

LogTape

Simple logging library with zero dependencies for Deno, Node.js, Bun, browsers, and edge functions

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 Fedifyで独自のフェディバースサーバーを構築しましょう!

FedifyはActivityPubプロトコルの実装を簡単にするTypeScriptフレームワークです。連合プロトコルの複雑な実装に困っていませんか?Fedifyがお手伝いします!

✨ 主な機能

🔧 CLIツール

🚀 ランタイムサポート

📚 学習が簡単

MITライセンスで自由に利用可能なオープンソースプロジェクトです!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

📢 여러분만의 서버를 Fedify로 만들어보세요!

Fedify 프로토콜 구현을 도와주는 프레임워크입니다. 복잡한 연합 프로토콜을 쉽게 구현하고 싶으신가요? Fedify가 도와드립니다!

✨ 주요 기능

🔧 CLI 도구

🚀 런타임 지원

📚 배우기 쉽습니다

오픈소스 라이선스로 누구나 자유롭게 사용할 수 있습니다!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

Build your own server with !

Fedify is a framework that simplifies implementation. Want to build a federated server without the complexity? Fedify has got you covered!

✨ Key features

🔧 CLI toolchain

🚀 Runtime support

📚 Easy to learn

Available under the license—free and open source!

discord.com

Join the Fedify/Hollo Discord Server!

Check out the Fedify/Hollo community on Discord - hang out with 81 other members and enjoy free voice and text chat.

@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@noim@noc.social

I hope someday we can expand types in the language server

Shows image of language server hover menu with multiple types hidden away with “…” by the typescript language server.
ALT text

Shows image of language server hover menu with multiple types hidden away with “…” by the typescript language server.

@toxi@mastodon.thi.ng

Latest attempt at building better documentation for thi.ng/umbrella (also to make it available offline!): Having noticed that recent versions of TypeDoc support extracting & merging of doc strings from monorepos, over the past few weeks I've been updating/cleaning docstrings in hundreds of source files across all 200+ packages and started building a small tool to assemble a single/mega-page documentation (currently ~4.3MB of just HTML). The tool translates existing docstrings and references contained therein (and still used for the existing API docs) to support proper cross-package references.

I've uploaded an early preview here:
docs.thi.ng/umbrella/

Please be aware that so far this is only an early stage prototype and only contains very limited docs. I.e. there are no generics/typeparams, no details about classes/interfaces... But at least I know now HOW to add this all, as well as all the additional metadata I've already got (currently still only available via other custom tools/examples).

For example, there're links to the tag-based browser[1] and I'm also planning to add the fuzzy doc search engine/index[2] to this new documentation... The tag browser integration still needs more work in terms of correctly matching package names to tags. The underlying system is there already, just needs more work in terms of actually doing/assigning the concept mapping. Since most package names in thi.ng/umbrella are very plain/boring (for a reason), for many (most?) packages this already works pretty well:

Example: Visiting the WebGL package docs: docs.thi.ng/umbrella/#webgl and then clicking on "examples" for this package, then opens the tag browser for WebGL: demo.thi.ng/umbrella/thing-bro where you can then see all other packages and examples related to this topic...

More updates on this all soon! Excited! 🤩

(EDIT: added screenshots...)

[1] demo.thi.ng/umbrella/thing-bro
[2] demo.thi.ng/umbrella/rdom-sear

Screenshot of the documentation tool/page mentioned in the post, showing the API docs for this function (dark color scheme): https://docs.thi.ng/umbrella/#fuzzy-viz:instrumentStrategy
ALT text

Screenshot of the documentation tool/page mentioned in the post, showing the API docs for this function (dark color scheme): https://docs.thi.ng/umbrella/#fuzzy-viz:instrumentStrategy

Screenshot of the documentation tool/page mentioned in the post, showing the API docs for this function (light color scheme): https://docs.thi.ng/umbrella/#fuzzy-viz:instrumentStrategy
ALT text

Screenshot of the documentation tool/page mentioned in the post, showing the API docs for this function (light color scheme): https://docs.thi.ng/umbrella/#fuzzy-viz:instrumentStrategy

@bnijbakker@mastodon.social
@bnijbakker@mastodon.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust foundation.

https://botkit.fedify.dev/

import {
  createBot,
  InProcessMessageQueue,
  MemoryKvStore,
  mention,
  text,
} from "@fedify/botkit";

// Create a bot instance:
const bot = createBot<void>({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the display name:
  name: "Greet Bot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  summary: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social")}.`,
  // Store data in memory (for development):
  kv: new MemoryKvStore(),
  // Use in-process message queue (for development):
  queue: new InProcessMessageQueue(),
});

// A bot can respond to a mention:
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}!`);
};

// Or, a bot also can actively publish a post:
const session = bot.getSession("https://mydomain/");
setInterval(async () => {
  await session.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, InProcessMessageQueue, MemoryKvStore, mention, text, } from "@fedify/botkit"; // Create a bot instance: const bot = createBot<void>({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the display name: name: "Greet Bot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: summary: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social")}.`, // Store data in memory (for development): kv: new MemoryKvStore(), // Use in-process message queue (for development): queue: new InProcessMessageQueue(), }); // A bot can respond to a mention: bot.onMention = async (session, message) => { await message.reply(text`Hi, ${message.actor}!`); }; // Or, a bot also can actively publish a post: const session = bot.getSession("https://mydomain/"); setInterval(async () => { await session.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@weltraumpoet@nerdculture.de

Hallo,

ich suche zur Zeit einen als im Raum oder
Ich bin Diplom- -er mit 12 Jahren Berufserfahrung.
Bisher arbeitete ich mit








&
, &

Auch , Gitlab- oder Azure DevOps sind mir nicht fremd. Ich bewegte mich bisher auf , , und auch ein wenig auf MacOS.

Irgendwo anzukommen und mich in einem konstruktiven Umfeld einzubringen, fände ich sehr schön.

Ich arbeite mich gerne in neue Felder ein, so würde mich unter Anderem die Embedded-Entwicklung interessieren, aber auch Sprachen wie Rust.

Ich spreche mich gern im Team ab oder lasse mich durch Kollegen in meiner Arbeit inspirieren, und bringe gerne meine Erfahrungen ein.

Auf Anfrage mit ein paar Informationen schicke ich gerne eine Bewerbung oder Ähnliches.

Vielleicht findet sich ja etwas über diese Plattform.

Vielen Dank.

@weltraumpoet@nerdculture.de

Hallo,

ich suche zur Zeit einen als im Raum oder
Ich bin Diplom- -er mit 12 Jahren Berufserfahrung.
Bisher arbeitete ich mit








&
, &

Auch , Gitlab- oder Azure DevOps sind mir nicht fremd. Ich bewegte mich bisher auf , , und auch ein wenig auf MacOS.

Irgendwo anzukommen und mich in einem konstruktiven Umfeld einzubringen, fände ich sehr schön.

Ich arbeite mich gerne in neue Felder ein, so würde mich unter Anderem die Embedded-Entwicklung interessieren, aber auch Sprachen wie Rust.

Ich spreche mich gern im Team ab oder lasse mich durch Kollegen in meiner Arbeit inspirieren, und bringe gerne meine Erfahrungen ein.

Auf Anfrage mit ein paar Informationen schicke ich gerne eine Bewerbung oder Ähnliches.

Vielleicht findet sich ja etwas über diese Plattform.

Vielen Dank.

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@hongminhee@hollo.social

Hello, I'm an open source software engineer in my late 30s living in , , and an avid advocate of and the .

I'm the creator of @fedify, an server framework in , @hollo, an ActivityPub-enabled microblogging software for single users, and @botkit, a simple ActivityPub bot framework.

I'm also very interested in East Asian languages (so-called ) and . Feel free to talk to me in , (), or (), or even in Literary Chinese (, )!

@rauschma@fosstodon.org
@deno_land@fosstodon.org

The next version of Deno will have a super fast JS/TS plugin API for the linter 🎉

Watch @lcasdev write a lint rule to ban string literals in <60 seconds.

This, plus many other goodies, to land next week with Deno 2.2.

@deno_land@fosstodon.org

The next version of Deno will have a super fast JS/TS plugin API for the linter 🎉

Watch @lcasdev write a lint rule to ban string literals in <60 seconds.

This, plus many other goodies, to land next week with Deno 2.2.

@deno_land@fosstodon.org

The next version of Deno will have a super fast JS/TS plugin API for the linter 🎉

Watch @lcasdev write a lint rule to ban string literals in <60 seconds.

This, plus many other goodies, to land next week with Deno 2.2.

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@rauschma@fosstodon.org
@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@qiita@rss-mstdn.studiofreesia.com
@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

🎉 Announcing BotKit 0.1.0: A new framework for creating ActivityPub bots!

We're thrilled to announce the initial release of , a framework that makes creating standalone bots simpler than ever before. With BotKit, you can create a complete fediverse bot in just a single TypeScript file!

Key features:

  • 🔋 Standalone bot creation—no need for a Mastodon/Misskey account
  • 🧩 Simple, developer-friendly API
  • 🚀 Easy deployment on Deno Deploy, Fly.io, Railway, or your own server
  • :fedify: Powered by @fedify for robust ActivityPub protocol handling

Getting started is as simple as:

deno add jsr:@fedify/botkit@^0.1.0

Here's a quick example of a weather bot:

const kv = await Deno.openKv();

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new DenoKvStore(kv),
  queue: new DenoKvMessageQueue(kv),
});

// Reply to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Current temperature in Seoul is 18°C!`);
};

// Post scheduled updates
const session = bot.getSession("https://weather.example.com");
setInterval(async () => {
  await session.publish(
    text`Seoul Weather Update 🌡️
    Current: 18°C
    Humidity: 65%
    Forecast: Clear skies ☀️`
  );
}, 1000 * 60 * 60); // Hourly updates

While BotKit currently supports , we're working on bringing Node.js and Bun support in future releases.

Ready to create your first fediverse bot? Check out our docs at https://botkit.fedify.dev/ to get started! 🚀

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@deno_land@fosstodon.org
@deno_land@fosstodon.org
@deno_land@fosstodon.org
@deno_land@fosstodon.org
@deno_land@fosstodon.org
@rauschma@fosstodon.org
@rauschma@fosstodon.org
@tjdraper@phpc.social

I've worked with dates and times in several programming languages, and I have to say that the best is easily PHP (since the big refactor in, what was it, 5.6?).

The worst is easily Javascript.

@jonn@social.doma.dev · Reply to alexandra

@xandra I'm so happy that someone's doing what I wanted to[1]. I'd be happy to write as well as contribute during review process if someone needs contributions.

Sadly, I've decided to post what I have worked on for in my blog, but in the spirit of 5th code jam[2], I could write a how-to article about setting up swarms of virtual machines on .

Alternatively, I can write an entry-level article about how to archive web pages and scrape stuff easily with (ugh) and/or .

Even more alternatively, as the most "good-interenetey" option, I can write an article about how and why to use for team and community management: guidelines, topic structures, etc.

[1]: social.doma.dev/@jonn/11220204
[2]: 32bit.cafe/~xandra/events/code

32bit.cafe

32-Bit Cafe's Community Jam #5: Back to School

@julian@fietkau.social

Made a little bit of progress on my project yesterday. Spun my wheels testing a few ORMs and running into compatibility problems with each of them. By the time I went to bed, the preferences page was capable of storing and loading account-local form data for the first time. 🥳

For this project, when progress looks slow from the outside, it's because I'm learning the ecosystem pretty much from scratch. Not letting myself get discouraged. 🙂

@julian@fietkau.social

Made a little bit of progress on my project yesterday. Spun my wheels testing a few ORMs and running into compatibility problems with each of them. By the time I went to bed, the preferences page was capable of storing and loading account-local form data for the first time. 🥳

For this project, when progress looks slow from the outside, it's because I'm learning the ecosystem pretty much from scratch. Not letting myself get discouraged. 🙂

@qiita@rss-mstdn.studiofreesia.com
@deno_land@fosstodon.org
@deno_land@fosstodon.org
@qiita@rss-mstdn.studiofreesia.com
@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@constantorbit@hachyderm.io

uggggh I'm in ES module vs CommonJS hell in nodejs. With Typescript layered on top.

Is it just me, or is this whole JS/TS environment a sh*tshow and nobody will admit it? It feels like a huge ball of duct tape and baling wire.

Maybe I should see if I can convince my org to explore Deno.

@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@qiita@rss-mstdn.studiofreesia.com
@qiita@rss-mstdn.studiofreesia.com
@adrianc@hachyderm.io

Hi!

I'm Adrian, a FullStack looking for a job either in (or from it if you allow for remote work), with a permanent and open visa

I have experience building and maintaining web apps and APIs, designing systems, doing and a bit of , and

I'm experienced using , , , , , , and ; and on the DevOps side in CI/CD pipelines (either and Gitlab CI/CD), and a bit of

I was tasked with a lot of the happening in my previous company, researching tools, librairies, patterns or general technologies either for our own or for our products

I also wrote a lot of technical and non technical documentation and internal presentations, and even participated in a few meetups. You can read some of my writing on my blog: blog.adrianc.eu

You might also have seen me on a few Elixir-related Discord servers, or even Bluesky (@adrianc.eu) and Twitter ; either sharing tech news, helping people, reading in book clubs or just chatting

I’m open to full-time right now, contracting work can be discussed.

I'm looking for any developer position, not only , even though it represents most of my experience. And if the technology you're using isn't on my resume, give me a chance! I'm a fast learner and I might anyway have studied it in class :P

DM me for more info, like github link, my resume or anything :)

Boosts, responses and DM welcome, of course!

blog.adrianc.eu

AdrianC

Curiosity propelled

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

Fedify 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:

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

https://fedify.dev/

@adrianc@hachyderm.io

Hi!

I'm Adrian, a FullStack looking for a job either in (or from it if you allow for remote work), with a permanent and open visa

I have experience building and maintaining web apps and APIs, designing systems, doing and a bit of , and

I'm experienced using , , , , , , and ; and on the DevOps side in CI/CD pipelines (either and Gitlab CI/CD), and a bit of

I was tasked with a lot of the happening in my previous company, researching tools, librairies, patterns or general technologies either for our own or for our products

I also wrote a lot of technical and non technical documentation and internal presentations, and even participated in a few meetups. You can read some of my writing on my blog: blog.adrianc.eu

You might also have seen me on a few Elixir-related Discord servers, or even Bluesky (@adrianc.eu) and Twitter ; either sharing tech news, helping people, reading in book clubs or just chatting

I’m open to full-time right now, contracting work can be discussed.

I'm looking for any developer position, not only , even though it represents most of my experience. And if the technology you're using isn't on my resume, give me a chance! I'm a fast learner and I might anyway have studied it in class :P

DM me for more info, like github link, my resume or anything :)

Boosts, responses and DM welcome, of course!

blog.adrianc.eu

AdrianC

Curiosity propelled

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

Fedify 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:

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

https://fedify.dev/

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@botkit@hollo.social

Are you interested in creating bots for the ? Meet , a framework that makes bot development easier than ever!

Key Features:

True Independence

  • Create standalone bots
  • No need for a Mastodon or Misskey account
  • Free from platform-specific limitations

Simple and Intuitive API

  • Create a complete bot in a single TypeScript file
  • Intuitive event handlers for mentions, follows, and messages
  • Rich text formatting with Markdown support

Modern Deployment

  • Deploy on Deno Deploy, Fly.io, Railway, or any virtual server
  • Minimal dependencies
  • Designed for modern cloud platforms

Enterprise-Ready Foundation

  • Built on Fedify, a rock-solid ActivityPub framework
  • Seamless federation with Mastodon, Misskey, and other platforms
  • Robust compatibility across the fediverse

Developer Experience

  • Full TypeScript support with great IDE integration
  • Comprehensive documentation
  • Built-in testing utilities

Here's a quick example of how simple it is to create a bot:

import { createBot, mention, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "greetbot",
  name: "Greet Bot",
  summary: text`A friendly bot that greets people!`,
  // ... configuration ...
});

// Respond to mentions
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}! Thanks for saying hello!`);
};

export default bot;

Getting Started:

  1. Install
  2. Run: deno add jsr:@fedify/botkit@^0.1.0-dev
  3. Create your bot with just a few lines of code

Check out our documentation at https://botkit.fedify.dev/ to learn more!

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@deno_land@fosstodon.org

Deno supports the new URL.parse() web API, which provides a simpler control flow for parsing URLs 👇

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.
ALT text

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.

@deno_land@fosstodon.org

Deno supports the new URL.parse() web API, which provides a simpler control flow for parsing URLs 👇

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.
ALT text

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.

@MastodonEngineering@mastodon.social

New year, new role @Mastodon!

Our core team is looking for a senior Front-end Developer to elevate the web UI/UX experience for our users.

Ideally:

1. You are highly skilled in accessible and semantic
2. Proficient in modern
3. Experienced with , and complex React/Redux applications

This remote full-time position requires a 4-hour overlap with the CET timezone.

For more info/to apply:
jobs.ashbyhq.com/mastodon/6a09

jobs.ashbyhq.com

Front-end Developer (m/f/d)

We're looking for a Front-end Developer to work with us remotely on our free and open-source Mastodon software.

@deno_land@fosstodon.org

Deno supports the new URL.parse() web API, which provides a simpler control flow for parsing URLs 👇

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.
ALT text

The new Web API URL.parse() provides a simpler control flow when you need to parse URLs.

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust foundation.

https://botkit.fedify.dev/

import {
  createBot,
  InProcessMessageQueue,
  MemoryKvStore,
  mention,
  text,
} from "@fedify/botkit";

// Create a bot instance:
const bot = createBot<void>({
  // The bot will have fediverse handle "@greetbot@mydomain":
  username: "greetbot",
  // Set the display name:
  name: "Greet Bot",
  // Set the profile icon (avatar):
  icon: new URL("https://mydomain/icon.png"),
  // Set the bio:
  summary: text`Hi, there! I'm a simple fediverse bot created by ${
    mention("@hongminhee@hollo.social")}.`,
  // Store data in memory (for development):
  kv: new MemoryKvStore(),
  // Use in-process message queue (for development):
  queue: new InProcessMessageQueue(),
});

// A bot can respond to a mention:
bot.onMention = async (session, message) => {
  await message.reply(text`Hi, ${message.actor}!`);
};

// Or, a bot also can actively publish a post:
const session = bot.getSession("https://mydomain/");
setInterval(async () => {
  await session.publish(text`Hi, forks! It's an hourly greeting.`);
}, 1000 * 60 * 60);

export default bot;
ALT text

import { createBot, InProcessMessageQueue, MemoryKvStore, mention, text, } from "@fedify/botkit"; // Create a bot instance: const bot = createBot<void>({ // The bot will have fediverse handle "@greetbot@mydomain": username: "greetbot", // Set the display name: name: "Greet Bot", // Set the profile icon (avatar): icon: new URL("https://mydomain/icon.png"), // Set the bio: summary: text`Hi, there! I'm a simple fediverse bot created by ${ mention("@hongminhee@hollo.social")}.`, // Store data in memory (for development): kv: new MemoryKvStore(), // Use in-process message queue (for development): queue: new InProcessMessageQueue(), }); // A bot can respond to a mention: bot.onMention = async (session, message) => { await message.reply(text`Hi, ${message.actor}!`); }; // Or, a bot also can actively publish a post: const session = bot.getSession("https://mydomain/"); setInterval(async () => { await session.publish(text`Hi, forks! It's an hourly greeting.`); }, 1000 * 60 * 60); export default bot;

@rauschma@fosstodon.org
@kur0den0010@chpk.kur0den.net
@botkit@hollo.social

:botkit: Introducing : A framework for creating truly standalone bots!

Unlike traditional Mastodon bots, BotKit lets you build fully independent bots that aren't constrained by platform limits. Create your entire bot in a single TypeScript file using our simple, expressive API.

Currently -only, with Node.js & Bun support planned. Built on the robust @fedify foundation.

https://botkit.fedify.dev/

botkit.fedify.dev

BotKit by Fedify

A framework for creating your ActivityPub bots

@deno_land@fosstodon.org
@qiita@rss-mstdn.studiofreesia.com