wayBetter Store

(FOSS) 풀 리퀘스트가 곧 제출이에요

내 것을 게시하세요.

테마는 JSON 파일 하나예요. 플러그인은 JavaScript 파일 하나고요. 만들고, 앱에서 써 본 다음 스토어에 추가하세요. 풀 리퀘스트 하나에 폴더 하나, git을 쓰지 않는다면 이슈에 파일을 첨부하면 돼요. 둘 다 무료 git.crt.fyi 계정만 있으면 돼요.

1

만들기

동작하는 파일에서 시작하세요. 스캐폴더가 하나 만들어 줘요. 앱의 만들기 섹션(wayBetter → 만들기)에는 예시와 현재 테마 값이 있어요.

테마

색, 글꼴, 모서리, 밀도, 레이아웃, 배경, 효과. 색 세 개면 충분해요. 나머지는 거기서 계산되고, 글자는 잘 읽히게 유지돼요.

앱에서 만들 수도 있어요: 화면 스타일 → 테마 빌더 → 내보내기. 테마로 설정할 수 있는 모든 것은 THEMES.md에 있어요.

플러그인

start() 및 stop() 메서드를 가진 클래스, 그리고 누가 만들었고 무엇을 쓰는지 알려 주는 헤더.

TypeScript 프로젝트라면 --ts를 붙이세요. API, 권한, 라이브 리로드는 PLUGINS.md에 있어요.

hide-trends.plugin.js
/**
 * @name Hide Trends
 * @description Hides the trends box in the right column, so the timeline is the only thing moving.
 * @version 1.0.0
 * @author you
 * @permissions network:none
 */
module.exports = class HideTrends {
  start() { wayBetter.api.injectCSS('hide-trends', '[data-testid="sidebarColumn"] section { display: none }'); }
  stop()  { wayBetter.api.clearCSS('hide-trends'); }
};

스토어는 플러그인의 이름, 작성자, 버전, 설명, 권한을 이 헤더에서 읽고, 테마의 이름, 작성자, 설명은 그 JSON에서 읽어요. 설치 화면도 같은 값을 보여 주니, 둘이 어긋날 일이 없어요.

2

써 보기

스토어는 선택 사항이에요. 동작하는 파일은 그 자체로 공유할 수 있어요.

  • 파일을 wayBetter 창에 끌어다 놓으세요. 스토어 항목과 같은 설치 화면이 나와요: 이름, 작성자, 버전, SHA-256, 권한, 코드.
  • 작업하는 동안 개발자 모드를 켜세요(설정 → 개발자). 저장한 플러그인, 테마 파일, custom.css가 모든 탭에서 한꺼번에 다시 로드돼요.
  • 스토어 없이 공유하기. 파일을 보내거나, waybetter.fyi, cdn1.crt.fyi의 https URL 또는 git.crt.fyi의 raw 파일을 가리키는 waybetter://install 링크를 보내세요. 설치 화면 없이 설치되는 일은 없어요.
3

폴더 하나 추가

스토어의 모든 항목은 저장소의 store/<app>/ 아래에 있는 폴더예요. 폴더 이름이 항목의 id이자 여기서의 주소가 돼요: /store/plugins/<id>/.

store/x/ — wayBetter for X의 항목
store/x/plugins/hide-trends/
  hide-trends.plugin.js   the plugin, exactly as it installs
  item.json               { "category": "focus", "tags": ["trends", "sidebar"] }
  preview.svg             optional, 640×400 (.svg or .png); drawn for you without one

store/x/themes/midnight-mint/
  theme.json              the theme, as Appearance → Export writes it
  item.json               { "version": "1.0.0" }
  preview.svg             optional; drawn from the theme without one
category
플러그인: reading, writing, filters, focus 또는 tools. 테마: dark 또는 light. 비워 두면 테마의 mode에서 가져와요.
tags
사람들이 검색할 만한 단어, 최대 12개.
version
테마에만 필요해요(플러그인의 버전은 헤더에 있어요). 파일을 바꿀 때 올리세요.
설명
무엇을 하는지 알려 주는 한두 문장, 50자 이상. 처음 160자가 그 페이지의 검색 엔진용 설명이 돼요.

제출은 이게 전부예요. 페이지, 카드, 검색 항목, 링크 미리 보기, 구조화된 데이터, 사이트맵 항목은 사이트를 빌드할 때 서명된 카탈로그에서 생성돼요. 전체 규칙은 store/README.md에 있어요.

4

검사 실행

호스팅되는 CI는 없어요. 검사는 보내기 전에 직접 실행하는 명령이고, 병합 전에 관리자가 다시 실행해요.

내 클론에서
git submodule update --init
bun install --frozen-lockfile
bun run check:store      # your folder, against the Store's rules
bun run test             # everything else, including the site's SEO test
  • id와 이름폴더 id(a-z 0-9 -, 최대 40자), name.plugin.js, 같은 앱 안에서 중복 없음
  • 크기항목 파일은 2 MiB까지, 미리 보기는 16:10 비율로 300 KB까지
  • 헤더@name, @version, 설명, 그리고 network 또는 network:none를 밝히는 @permissions 줄
  • 정직한 권한코드가 fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon 중 하나를 호출하면 network:none은 거부돼요. 제한된 API 호출은 선언해야 해요
  • 원격 코드 없음eval, new Function, import() 금지. 미리 보기에 스크립트나 외부 파일 금지. 테마 CSS에 @import나 외부 URL 금지
  • 카탈로그항목들이 앱이 받아들이는 카탈로그로 빌드되고(프레임워크 자체 규칙), 게시된 카탈로그가 여전히 서명 및 해시와 일치해야 해요
  • 검색과 공유페이지 제목은 60자까지, 설명은 50~160자, 둘 다 중복 없이
5

보내기

참여 방법은 두 가지. 둘 다 무료 git.crt.fyi 계정이 필요합니다. 누구나 가입할 수 있고, 새 계정은 관리자가 하나씩 직접 승인합니다.

풀 리퀘스트

  1. git.crt.fyi에서 저장소를 포크해요.
  2. 브랜치에 폴더를 추가하고 검사를 실행해요.
  3. 풀 리퀘스트를 열어요. 템플릿이 무엇을 하는지, 무엇을 쓰는지 물어봐요.

git을 안 쓰나요? 이슈를 여세요

  1. 테마 또는 플러그인 템플릿을 고르세요.
  2. 파일을 첨부하세요(미리 보기가 있다면 함께).
  3. 관리자가 대신 폴더를 추가해 줘요.

그다음 관리자가 서명해요

스토어의 서명 키는 일부러 오프라인에 두기 때문에, 병합이 곧 게시는 아니에요. 병합 뒤에 관리자가 코드를 읽고, 키가 있는 컴퓨터에서 waybetter store build 및 waybetter store sign 명령을 실행한 다음 푸시해요. 사이트가 다시 빌드되고, 내 항목에 페이지가 생기고, 모든 앱이 다음에 서명된 카탈로그를 읽을 때 그 항목을 보게 돼요.

서명된 카탈로그에 있는 것은 모두 그 키가 보증해요. 그래서 모든 플러그인은 서명 전에 사람이 직접 읽어요.

{ }

카탈로그 형식

모든 wayBetter 앱이 쓰는 파일 하나. 손으로 고칠 일은 없어요. 폴더에서 빌드되니까요.

catalog.json(형식 2)오픈
{ "format": 2, "name": "wayBetter Store", "generatedAt": "2026-09-30T…Z", "items": [
  { "apps": ["x"], "kind": "plugin", "id": "thread-reader", "name": "Thread Reader",
    "author": "wayBetter", "version": "1.2.0", "description": "…",
    "category": "reading", "tags": ["threads"],
    "url": "https://waybetter.fyi/store/plugins/bt-thread-reader.plugin.js",
    "file": "bt-thread-reader.plugin.js", "sha256": "<64 hex>", "size": 10961,
    "preview": "https://waybetter.fyi/store/previews/plugin-thread-reader.svg",
    "permissions": ["ui", "clipboard", "commands", "network:none"] }
] }
  • 서명됨. catalog.json.sig는 catalog.json의 바이트 그대로에 대한 Ed25519 서명이에요. 앱은 내장된 공개 키로 이를 검증한 다음, 내려받는 모든 파일의 크기와 SHA-256을 확인해요.
  • 엄격함. 알 수 없는 필드, 500개가 넘는 항목, 1 MiB를 넘는 파일이 있으면 카탈로그 전체가 거부돼요. JSON Schema는 store-catalog.schema.json이고, 모든 규칙은 프레임워크의 STORE.md에 있어요.
  • 공유됨. 각 항목은 자신의 apps를 밝혀요. 앱은 파일 전체를 검증하고 자기 항목만 남겨요.
Aa

언어

스토어 항목이 아니에요. 51개 언어 모두 앱에 내장돼 있고, 필요할 때 불러와요.

  • apps/desktop/locales/<tag>.json에서 번역을 고치거나 마무리하세요. 풀 리퀘스트로, 또는 바꾼 파일을 첨부한 이슈로 보내면 돼요.
  • bun run i18n:check로 검사하세요: 키, 자리 표시자, 복수형, 마크업 없음. 0 error(s)가 출력돼야 해요.
  • 다음 앱 업데이트에 포함돼요. 스토어를 거치지 않아요. 메시지 문법과 내 번역을 앱에서 확인하는 방법은 TRANSLATING.md에 있어요.

이미 있는 것을 살펴보세요.

스토어의 모든 항목은 코드를 보여 줘요. 기본 포함 플러그인은 API를 잘 쓰는 방법을 보여 주는 가장 좋은 예시예요.