nsyte

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

nsyte — Decentralized Static Site Deployment

nsyte — 去中心化静态站点部署

nsyte is a Deno-based CLI that publishes static websites to the Nostr network using Blossom servers for file storage. Sites are content-addressed (SHA-256), censorship-resistant, and discoverable via Nostr relays.
Key concepts: For Nostr/Blossom domain knowledge (relays, pubkeys, nsec, NIP-46, events), see references/nostr-concepts.md.

nsyte是一款基于Deno的CLI工具,可将静态网站发布到Nostr网络,使用Blossom服务器进行文件存储。站点采用内容寻址(SHA-256)、具备抗审查特性,可通过Nostr中继节点搜索访问。
核心概念: 如需了解Nostr/Blossom领域知识(relays、pubkeys、nsec、NIP-46、events),请查看references/nostr-concepts.md

Installation

安装

Check if installed

检查是否已安装

bash
nsyte --version
If this prints a version string, skip to Project Setup.
bash
nsyte --version
如果输出版本号,可直接跳转到项目设置

Linux / macOS (recommended — no Deno required)

Linux / macOS(推荐方案 — 无需安装Deno)

bash
curl -fsSL https://nsyte.run/get/install.sh | bash
Installs to
/usr/local/bin/nsyte
. Use
sudo
if that directory is not writable.
bash
curl -fsSL https://nsyte.run/get/install.sh | bash
默认安装到
/usr/local/bin/nsyte
。如果该目录没有写入权限,可在命令前加
sudo

Linux / macOS (alternative — requires Deno 2.x)

Linux / macOS(备选方案 — 需要Deno 2.x)

bash
deno install -A -f -g -n nsyte jsr:@nsyte/cli
bash
deno install -A -f -g -n nsyte jsr:@nsyte/cli

Windows

Windows

Download the latest binary from
https://github.com/sandwichfarm/nsyte/releases
, place in
%USERPROFILE%\bin\
, and add that directory to PATH.
https://github.com/sandwichfarm/nsyte/releases
下载最新的二进制文件,放到
%USERPROFILE%\bin\
目录下,并将该目录添加到系统PATH中。

Troubleshooting installation

安装故障排查

  • Command not found: Add
    /usr/local/bin
    to PATH in
    ~/.bashrc
    or
    ~/.zshrc
    and reload.
  • Permission denied: Use
    sudo
    for the curl install, or install to a user-writable location.
  • Deno version too old: Run
    deno upgrade
    or use the binary install instead.

  • 找不到命令:
    /usr/local/bin
    添加到
    ~/.bashrc
    ~/.zshrc
    的PATH配置中,然后重载配置。
  • 权限不足: curl安装命令前加
    sudo
    ,或者安装到用户可写的目录下。
  • Deno版本过低: 运行
    deno upgrade
    ,或者改用二进制安装方案。

Project Setup

项目设置

bash
cd /path/to/your/project
nsyte init
Interactive prompts ask for:
  1. Auth method — generate new key, enter existing nsec/hex key, or connect NIP-46 bunker
  2. Relay URLs — one or more
    wss://
    relay WebSocket URLs
  3. Blossom server URLs — one or more
    https://
    Blossom server URLs
On success, creates
.nsite/config.json
. See Configuration for the schema.

bash
cd /path/to/your/project
nsyte init
交互提示会要求你配置以下内容:
  1. 身份验证方式 — 生成新密钥、输入已有的nsec/十六进制密钥,或者连接NIP-46 bunker
  2. 中继节点URL — 一个或多个
    wss://
    协议的中继WebSocket URL
  3. Blossom服务器URL — 一个或多个
    https://
    协议的Blossom服务器URL
初始化成功后会生成
.nsite/config.json
文件。配置项说明请查看配置部分。

Configuration

配置

Config file:
.nsite/config.json
For the full JSON Schema, see assets/config.schema.json.
配置文件路径:
.nsite/config.json
完整的JSON Schema请查看assets/config.schema.json

Required fields

必填字段

FieldTypeDescription
relays
string[]
Nostr relay URLs (
wss://
), unique items
servers
string[]
Blossom server URLs (
https://
), unique items
字段类型描述
relays
string[]
Nostr中继节点URL(
wss://
协议),不可重复
servers
string[]
Blossom服务器URL(
https://
协议),不可重复

Authentication

身份验证相关

FieldTypeDescription
bunkerPubkey
string
64-char hex pubkey for NIP-46 bunker. Pattern:
^[0-9a-fA-F]{64}$
. Always set via
nsyte bunker use
, never manually.
字段类型描述
bunkerPubkey
string
NIP-46 bunker的64位十六进制公钥,格式规则:
^[0-9a-fA-F]{64}$
必须通过
nsyte bunker use
设置,禁止手动修改。

Site identity

站点标识

FieldTypeDefaultDescription
id
string | null
null
null
/empty = root site (kind 15128). Non-empty = named site (kind 35128)
title
string
Site title for manifest event
description
string
Site description for manifest event
fallback
string
404 fallback HTML path (e.g.,
/index.html
for SPAs)
字段类型默认值描述
id
string | null
null
null
/空值 = 根站点(kind 15128)。非空值 = 命名站点(kind 35128)
title
string
清单事件中的站点标题
description
string
清单事件中的站点描述
fallback
string
404 fallback HTML路径(例如SPA站点设置为
/index.html

Publishing flags (root sites only —
id
must be null/empty)

发布标记(仅根站点可用 —
id
必须为null/空)

FieldTypeDescription
publishProfile
boolean
Publish kind 0 profile metadata. Requires non-empty
profile
object
publishRelayList
boolean
Publish kind 10002 relay list
publishServerList
boolean
Publish kind 10063 Blossom server list
publishAppHandler
boolean
Publish NIP-89 handler. Requires
appHandler
with
kinds
字段类型描述
publishProfile
boolean
发布kind 0的个人资料元数据,要求
profile
对象非空
publishRelayList
boolean
发布kind 10002的中继节点列表
publishServerList
boolean
发布kind 10063的Blossom服务器列表
publishAppHandler
boolean
发布NIP-89 handler,要求
appHandler
包含
kinds
字段

Optional objects

可选对象

FieldTypeDescription
profile
object
Nostr profile:
name
,
display_name
,
about
,
picture
,
banner
,
website
,
nip05
,
lud16
,
lud06
appHandler
object
NIP-89 config:
kinds
(required),
id
,
name
,
description
,
icon
,
platforms
gatewayHostnames
string[]
Gateway hostnames (default:
["nsite.lol"]
)
字段类型描述
profile
object
Nostr个人资料:
name
display_name
about
picture
banner
website
nip05
lud16
lud06
appHandler
object
NIP-89配置:必填字段
kinds
,可选字段
id
name
description
icon
platforms
gatewayHostnames
string[]
网关域名(默认:
["nsite.lol"]

Example configs

配置示例

Minimal (root site):
json
{
  "relays": ["wss://relay.damus.io", "wss://nos.lol"],
  "servers": ["https://cdn.hzrd149.com"]
}
Named site (blog):
json
{
  "relays": ["wss://relay.damus.io"],
  "servers": ["https://cdn.hzrd149.com"],
  "id": "blog",
  "title": "My Blog",
  "description": "A blog about decentralized applications"
}
With profile publishing:
json
{
  "relays": ["wss://relay.damus.io", "wss://nos.lol"],
  "servers": ["https://cdn.hzrd149.com"],
  "publishProfile": true,
  "publishRelayList": true,
  "publishServerList": true,
  "profile": {
    "name": "Alice",
    "display_name": "Alice",
    "about": "Decentralization enthusiast",
    "picture": "https://example.com/avatar.jpg",
    "nip05": "alice@example.com",
    "lud16": "alice@getalby.com"
  }
}
With NIP-89 app handler:
json
{
  "relays": ["wss://relay.damus.io"],
  "servers": ["https://cdn.hzrd149.com"],
  "publishAppHandler": true,
  "appHandler": {
    "kinds": [1, 30023],
    "name": "My Nostr Viewer",
    "description": "A viewer for notes and articles",
    "icon": "https://example.com/logo.png"
  }
}
最简配置(根站点):
json
{
  "relays": ["wss://relay.damus.io", "wss://nos.lol"],
  "servers": ["https://cdn.hzrd149.com"]
}
命名站点(博客):
json
{
  "relays": ["wss://relay.damus.io"],
  "servers": ["https://cdn.hzrd149.com"],
  "id": "blog",
  "title": "我的博客",
  "description": "一个关于去中心化应用的博客"
}
配置个人资料发布:
json
{
  "relays": ["wss://relay.damus.io", "wss://nos.lol"],
  "servers": ["https://cdn.hzrd149.com"],
  "publishProfile": true,
  "publishRelayList": true,
  "publishServerList": true,
  "profile": {
    "name": "Alice",
    "display_name": "Alice",
    "about": "去中心化爱好者",
    "picture": "https://example.com/avatar.jpg",
    "nip05": "alice@example.com",
    "lud16": "alice@getalby.com"
  }
}
配置NIP-89 app handler:
json
{
  "relays": ["wss://relay.damus.io"],
  "servers": ["https://cdn.hzrd149.com"],
  "publishAppHandler": true,
  "appHandler": {
    "kinds": [1, 30023],
    "name": "我的Nostr查看器",
    "description": "用于查看笔记和文章的查看器",
    "icon": "https://example.com/logo.png"
  }
}

Interactive config editor

交互式配置编辑器

bash
nsyte config
Requires an interactive terminal. Keys:
/
navigate,
Enter
edit,
s
save,
r
reset,
q
quit.
For non-interactive contexts, edit
.nsite/config.json
directly and validate:
bash
nsyte validate

bash
nsyte config
需要交互式终端支持。操作按键:
/
导航,
Enter
编辑,
s
保存,
r
重置,
q
退出。
非交互式场景下可直接编辑
.nsite/config.json
,然后执行以下命令验证配置:
bash
nsyte validate

Authentication

身份验证

NIP-46 Bunker (recommended)

NIP-46 Bunker(推荐方案)

Connect via QR code

通过二维码连接

bash
nsyte bunker connect
Choose "Scan QR Code", enter a relay URL, scan with signer app (Amber, nsec.app), approve.
bash
nsyte bunker connect
选择「扫描二维码」,输入中继节点URL,使用签名应用(Amber、nsec.app)扫描并授权即可。

Connect via bunker URL

通过bunker URL连接

bash
nsyte bunker connect 'bunker://pubkey?relay=wss://relay.example.com&secret=xxx'
CRITICAL: Always single-quote the URL —
?
and
&
are shell metacharacters.
bash
nsyte bunker connect 'bunker://pubkey?relay=wss://relay.example.com&secret=xxx'
重要提示: URL必须用单引号包裹 —
?
&
是Shell特殊字符,不包裹会被解析错误。

Link bunker to project

将bunker关联到项目

bash
nsyte bunker use [pubkey]
Sets
bunkerPubkey
in config and stores nbunksec in OS keychain. Never manually edit
bunkerPubkey
.
bash
nsyte bunker use [pubkey]
该命令会在配置中设置
bunkerPubkey
,并将nbunksec存储到系统钥匙串中。禁止手动编辑
bunkerPubkey

Bunker management commands

Bunker管理命令

CommandPurpose
nsyte bunker connect
Connect interactively (QR or URL)
nsyte bunker connect '<url>'
Connect via bunker URL
nsyte bunker import nbunksec1...
Import existing nbunksec
nsyte bunker export [pubkey]
Export stored bunker as nbunksec
nsyte bunker list
List stored bunkers
nsyte bunker use [pubkey]
Set project to use a bunker
nsyte bunker remove [pubkey]
Remove a bunker from storage
nsyte bunker migrate [pubkeys...]
Rebuild keychain index
命令用途
nsyte bunker connect
交互式连接(二维码或URL)
nsyte bunker connect '<url>'
通过bunker URL连接
nsyte bunker import nbunksec1...
导入已有的nbunksec
nsyte bunker export [pubkey]
导出已存储的bunker为nbunksec格式
nsyte bunker list
列出所有已存储的bunker
nsyte bunker use [pubkey]
设置当前项目使用的bunker
nsyte bunker remove [pubkey]
从存储中删除指定bunker
nsyte bunker migrate [pubkeys...]
重建钥匙串索引

Secrets storage

密钥存储

nsyte auto-selects the best backend:
  1. macOS: Keychain
  2. Linux: Secret Service (fallback: encrypted file)
  3. Windows: Credential Manager (fallback: encrypted file)
Override with
NSYTE_FORCE_ENCRYPTED_STORAGE=true
.

nsyte会自动选择最优的存储后端:
  1. macOS: 钥匙串(Keychain)
  2. Linux: 秘密服务(Secret Service),降级方案:加密文件
  3. Windows: 凭据管理器(Credential Manager),降级方案:加密文件
可通过设置环境变量
NSYTE_FORCE_ENCRYPTED_STORAGE=true
强制使用加密文件存储。

Deployment

部署

Basic deploy

基础部署

bash
nsyte deploy ./dist
bash
nsyte deploy ./dist

Auth resolution order

身份验证优先级顺序

  1. --sec
    flag
    (highest priority):
    bash
    nsyte deploy ./dist --sec "nsec1..."
    nsyte deploy ./dist --sec "${NBUNK_SECRET}"
    Auto-detects format:
    nsec1...
    ,
    nbunksec1...
    ,
    bunker://...
    , or 64-char hex.
  2. Stored bunker from
    .nsite/config.json
    bunkerPubkey
    + OS keychain.
  3. If neither available, nsyte exits with an error.
  1. --sec
    参数
    (最高优先级):
    bash
    nsyte deploy ./dist --sec "nsec1..."
    nsyte deploy ./dist --sec "${NBUNK_SECRET}"
    自动识别格式:
    nsec1...
    nbunksec1...
    bunker://...
    或者64位十六进制密钥。
  2. 已存储的bunker:从
    .nsite/config.json
    bunkerPubkey
    + 系统钥匙串中读取。
  3. 如果以上两种方式都不可用,nsyte会报错退出。

Common flags

常用参数

FlagPurpose
--sec <value>
Provide signing key/credential
--force
Re-upload all files (skip diff)
--fallback=/index.html
SPA fallback for 404s
--non-interactive
CI mode — no prompts, fail fast
参数用途
--sec <value>
提供签名密钥/凭证
--force
重新上传所有文件(跳过差异比对)
--fallback=/index.html
SPA站点404 fallback配置
--non-interactive
CI模式 — 无交互提示,出错直接退出

Interpreting output

输出结果说明

  • Full success:
    {N} files uploaded successfully ({size})
    — all files to all servers
  • Partial success:
    {uploaded}/{total} files uploaded
    — some servers failed
  • Total failure:
    Failed to upload any files
    — check relay/server/auth errors
Gateway URL printed after deploy:
https://{npub}.nsite.lol/

  • 完全成功:
    {N} files uploaded successfully ({size})
    — 所有文件已上传到所有服务器
  • 部分成功:
    {uploaded}/{total} files uploaded
    — 部分服务器上传失败
  • 完全失败:
    Failed to upload any files
    — 请检查中继节点/服务器/身份验证错误
部署成功后会打印网关URL:
https://{npub}.nsite.lol/

CI/CD

CI/CD

Step 1: Generate CI credential (one-time, on dev machine)

步骤1:生成CI凭证(在开发机上执行一次即可)

bash
nsyte ci
bash
nsyte ci

or with bunker URL:

或使用bunker URL:

nsyte ci 'bunker://pubkey?relay=wss://relay.example.com&secret=xxx'

The `nbunksec1...` string is printed once and never stored. Copy it immediately and save as a CI secret.
nsyte ci 'bunker://pubkey?relay=wss://relay.example.com&secret=xxx'

生成的`nbunksec1...`字符串只会输出一次,不会存储,请立即复制保存为CI密钥。

Step 2: Deploy in pipeline

步骤2:在流水线中部署

bash
nsyte deploy ./dist --non-interactive --sec "${NBUNK_SECRET}"
CRITICAL: Use
--sec
(not
--nbunksec
).
bash
nsyte deploy ./dist --non-interactive --sec "${NBUNK_SECRET}"
重要提示: 使用
--sec
参数(不是
--nbunksec
)。

GitHub Actions example

GitHub Actions示例

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: denoland/setup-deno@v1
      - run: nsyte deploy ./dist --non-interactive --sec "${{ secrets.NBUNK_SECRET }}"
yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: denoland/setup-deno@v1
      - run: nsyte deploy ./dist --non-interactive --sec "${{ secrets.NBUNK_SECRET }}"

CI checklist

CI检查清单

  • .nsite/config.json
    committed or provided as artifact
  • NBUNK_SECRET
    secret set to
    nbunksec1...
    string
  • --non-interactive
    flag present
  • Optionally run
    nsyte validate
    before deploy

  • .nsite/config.json
    已提交到仓库,或作为构建产物提供
  • NBUNK_SECRET
    密钥已设置为生成的
    nbunksec1...
    字符串
  • 命令包含
    --non-interactive
    参数
  • 可选择在部署前执行
    nsyte validate
    验证配置

Other Commands

其他命令

CommandPurpose
nsyte ls
List published files
nsyte browse
Interactive TUI file browser with relay/server propagation tracking
nsyte download <dir>
Download published files
nsyte serve -d <dir>
Local dev server
nsyte run
Start resolver server with npub subdomains
nsyte debug <npub>
Debug nsite setup (relays, servers, integrity)
nsyte validate
Validate config (exit 0 = valid, 1 = invalid)
nsyte purge
Remove published files from relays/servers
nsyte sites
List available sites (root + named)

命令用途
nsyte ls
列出已发布的文件
nsyte browse
交互式TUI文件浏览器,可查看中继/服务器的传播状态
nsyte download <dir>
下载已发布的文件
nsyte serve -d <dir>
本地开发服务器
nsyte run
启动带npub子域名的解析服务器
nsyte debug <npub>
调试nsite配置(中继、服务器、完整性检查)
nsyte validate
验证配置(退出码0 = 有效,1 = 无效)
nsyte purge
从中继/服务器删除已发布的文件
nsyte sites
列出所有可用站点(根站点+命名站点)

Troubleshooting

故障排查

Auth errors

身份验证错误

  • "No valid signing method": Provide
    --sec
    or configure bunker via
    nsyte bunker use
    .
  • "No stored credential":
    bunkerPubkey
    set in config but keychain entry missing. Fix:
    nsyte bunker use [pubkey]
    .
  • Bunker URL rejected: Shell ate metacharacters. Use single quotes:
    'bunker://...'
    .
  • "No valid signing method": 请提供
    --sec
    参数,或通过
    nsyte bunker use
    配置bunker。
  • "No stored credential": 配置中设置了
    bunkerPubkey
    但钥匙串中缺少对应条目。修复方法:执行
    nsyte bunker use [pubkey]
  • Bunker URL被拒绝: Shell解析了特殊字符,请用单引号包裹URL:
    'bunker://...'

Deploy errors

部署错误

  • Relay issues: Check
    relays
    array in config has valid
    wss://
    URLs. Try
    --use-fallback-relays
    .
  • Blossom server rejection: Check
    servers
    array. Try adding a different server via
    nsyte config
    .
  • Config missing: Run
    nsyte init
    first.
  • 中继节点问题: 检查配置中的
    relays
    数组是否包含有效的
    wss://
    URL,可尝试添加
    --use-fallback-relays
    参数。
  • Blossom服务器拒绝请求: 检查
    servers
    数组,可通过
    nsyte config
    添加其他可用服务器。
  • 缺少配置文件: 先执行
    nsyte init
    初始化项目。

Config errors

配置错误

  • "Config editor requires interactive terminal": Edit JSON directly +
    nsyte validate
    .
  • Validation fails: Common causes: malformed URLs,
    publishAppHandler: true
    without
    appHandler.kinds
    ,
    publish*
    on named site.
  • bunkerPubkey format: Must be 64 hex chars, not npub. Always use
    nsyte bunker use
    .
  • "Config editor requires interactive terminal": 直接编辑JSON配置文件,然后执行
    nsyte validate
    验证。
  • 验证失败: 常见原因:URL格式错误、
    publishAppHandler: true
    但缺少
    appHandler.kinds
    、命名站点使用了
    publish*
    参数。
  • bunkerPubkey格式错误: 必须是64位十六进制字符,不是npub,请始终通过
    nsyte bunker use
    设置。