From e884fe6898c023a7b87b207e5bb2ec74ee68be3b Mon Sep 17 00:00:00 2001 From: syui Date: Sun, 18 Jan 2026 16:48:29 +0900 Subject: [PATCH] cleanup --- .github/workflows/cf-pages.yml | 7 +- config.json | 8 - {lexicon => lexicons}/ai.syui.log.post.json | 0 network.json | 12 - readme.md | 345 +------------------- src/commands/post.rs | 2 +- 6 files changed, 6 insertions(+), 368 deletions(-) delete mode 100644 config.json rename {lexicon => lexicons}/ai.syui.log.post.json (100%) delete mode 100644 network.json diff --git a/.github/workflows/cf-pages.yml b/.github/workflows/cf-pages.yml index 2e2661c..80d3d23 100644 --- a/.github/workflows/cf-pages.yml +++ b/.github/workflows/cf-pages.yml @@ -23,11 +23,8 @@ jobs: - name: Install dependencies run: npm install - - name: Fetch content from ATProto - run: npm run fetch - - - name: Generate static site - run: npm run generate + - name: Build content from ATProto + run: npm run build - name: Deploy to Cloudflare Pages uses: cloudflare/pages-action@v1 diff --git a/config.json b/config.json deleted file mode 100644 index a5358af..0000000 --- a/config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "title": "syui.ai", - "handle": "syui.syui.ai", - "collection": "ai.syui.log.post", - "network": "syu.is", - "color": "#EF454A", - "siteUrl": "https://syui.ai" -} diff --git a/lexicon/ai.syui.log.post.json b/lexicons/ai.syui.log.post.json similarity index 100% rename from lexicon/ai.syui.log.post.json rename to lexicons/ai.syui.log.post.json diff --git a/network.json b/network.json deleted file mode 100644 index 62de6a3..0000000 --- a/network.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "bsky.social": { - "plc": "https://plc.directory", - "bsky": "https://public.api.bsky.app", - "web": "https://bsky.app" - }, - "syu.is": { - "plc": "https://plc.syu.is", - "bsky": "https://bsky.syu.is", - "web": "https://syu.is" - } -} diff --git a/readme.md b/readme.md index a2fb7bf..4fa9092 100644 --- a/readme.md +++ b/readme.md @@ -1,346 +1,7 @@ # ailog -ATProto-based blog platform built on at-browser. - -## Concept - -**Data lives in ATProto, not on this server.** - -This is not a traditional blog generator. It's a **viewer (client)** for ATProto records. - -``` -Traditional blog: - Server DB ← article data ← user - -ATProto blog: - User's PDS ← article data (ai.syui.log.post) - ↓ - at-browser (this site) → displays records +```sh +$ vim public/config.json +$ npm run build ``` -## Architecture - -``` -┌─────────────────────────────────────────┐ -│ at-browser │ -│ (ATProto record viewer/editor) │ -├─────────────────────────────────────────┤ -│ │ -│ / → admin (config.json) │ -│ /@alice → user page │ -│ /@bob.bsky → user page │ -│ │ -└─────────────────────────────────────────┘ -``` - -## Roles - -| Role | Path | Data Source | -|------|------|-------------| -| **admin** | `/` (root) | local + remote | -| **user** | `/@handle` | remote only | - -### Admin (Site Owner) - -- Defined in `config.json` -- Has root (`/`) access -- Can reference **local files** (static assets, custom styles) -- Can reference **remote** (ATProto records) - -### User (Any ATProto User) - -- Accessed via `/@handle` path -- **Remote only** (ATProto records from their PDS) -- No registration required -- Anyone with an ATProto account can be displayed - -## Features - -### 1. at-browser (Core) - -- Search by handle/DID -- Browse PDS collections -- Navigate ATProto records - -### 2. ai.syui.log.post View - -- Markdown rendering -- Syntax highlighting -- Blog-style display - -### 3. OAuth - -- Login with ATProto -- Post to ai.syui.log.post collection - -## Use Cases - -### Personal Blog - -```json -// config.json -{ - "did": "did:plc:xxxxx", - "handle": "syui.syui.ai" -} -``` - -- Deploy to `syui.ai` -- Root shows your profile + posts -- You are the admin (local + remote) -- Others can view via `/@handle` - -### Blog Service - -```json -// config.json -{ - "admin": "service.example.com", - "handle": null -} -``` - -- Deploy to `blog.example.com` -- Root shows landing/search -- All users via `/@handle` (remote only) -- Platform for any ATProto user - -## Data Flow - -``` -┌──────────────┐ ┌──────────────┐ -│ User's PDS │────→│ at-browser │ -│ (ATProto) │←────│ (this site) │ -└──────────────┘ └──────────────┘ - ↑ │ - │ ↓ - ai.syui.log.post ┌──────────┐ - collection │ Display │ - │ - Profile│ - │ - Posts │ - └──────────┘ -``` - -## Local = Remote (Same Format) - -**Critical design principle: local files use the exact same format as ATProto API responses.** - -This allows the same code to handle both data sources. - -### Remote (ATProto API) - -```bash -curl "https://syu.is/xrpc/com.atproto.repo.listRecords?repo=did:plc:xxx&collection=ai.syui.log.post" -``` - -```json -{ - "records": [ - { - "uri": "at://did:plc:xxx/ai.syui.log.post/3xxx", - "cid": "bafyrei...", - "value": { - "title": "Hello World", - "content": "# Hello\n\nThis is my post.", - "createdAt": "2025-01-01T00:00:00Z" - } - } - ] -} -``` - -### Local (Static File) - -``` -content/ -└── did:plc:xxx/ - ├── describe.json # describeRepo (special) - ├── app.bsky.actor.profile/ - │ └── self.json # {collection}/{rkey}.json - └── ai.syui.log.post/ - └── 3xxx.json # {collection}/{rkey}.json -``` - -```json -// content/did:plc:xxx/ai.syui.log.post/3xxx.json -{ - "uri": "at://did:plc:xxx/ai.syui.log.post/3xxx", - "cid": "bafyrei...", - "value": { - "title": "Hello World", - "content": "# Hello\n\nThis is my post.", - "createdAt": "2025-01-01T00:00:00Z" - } -} -``` - -### ATProto API Reference - -| API | Path | Description | -|-----|------|-------------| -| getRecord | `/xrpc/com.atproto.repo.getRecord` | Get single record | -| listRecords | `/xrpc/com.atproto.repo.listRecords` | List records in collection | -| describeRepo | `/xrpc/com.atproto.repo.describeRepo` | Get repo info + collections list | - -See: [com.atproto.repo.describeRepo](https://docs.bsky.app/docs/api/com-atproto-repo-describe-repo) - -### Resolution Strategy - -``` -at-browser - │ - ├── admin (config.json user) - │ ├── 1. Check local: /content/{did}/{collection}/{rkey}.json - │ └── 2. Fallback to remote: PDS API - │ - └── user (/@handle) - └── remote only: PDS API -``` - -### Why Same Format? - -- **One codebase**: No branching logic for local vs remote -- **Easy testing**: Copy API response to local file -- **Offline support**: Admin can work with local files -- **Migration**: Local → Remote (just POST to PDS) - -## Config - -### config.json - -```json -{ - "did": "did:plc:xxxxx", - "handle": "syui.syui.ai", - "pds": "syu.is", - "collection": "ai.syui.log.post" -} -``` - -## Tech Stack - -- **CLI**: Rust (ailog) -- **Frontend**: Vite + TypeScript -- **ATProto**: @atproto/api -- **OAuth**: @atproto/oauth-client-browser -- **Markdown**: marked + highlight.js - -## CLI (ailog) - -### Install - -```bash -cargo build --release -cp target/release/ailog ~/.local/bin/ -``` - -### Commands - -```bash -# Login to ATProto PDS -ailog login -p [-s ] - -# Post a record -ailog post -c [-r ] - -# Get records from collection -ailog get -c [-l ] - -# Delete a record -ailog delete -c -r - -# Sync PDS data to local content directory -ailog sync [-o ] - -# Generate lexicon Rust code from ATProto lexicons -ailog gen [-i ] [-o ] -``` - -### Example - -```bash -# Login -ailog login syui.syui.ai -p "app-password" -s syu.is - -# Post -echo '{"title":"Hello","content":"World","createdAt":"2025-01-01T00:00:00Z"}' > post.json -ailog post post.json -c ai.syui.log.post - -# Sync to local -ailog sync -o content -``` - -### Project Structure - -``` -src/ -├── main.rs -├── commands/ -│ ├── mod.rs -│ ├── auth.rs # login, refresh session -│ ├── token.rs # token management -│ ├── post.rs # post, get, delete, sync -│ └── gen.rs # lexicon code generation -└── lexicons/ - └── mod.rs # auto-generated from ATProto lexicons -``` - -### Lexicon Generation - -Generate Rust endpoint definitions from ATProto lexicon JSON files: - -```bash -# Clone atproto repo (if not exists) -git clone https://github.com/bluesky-social/atproto repos/atproto - -# Generate lexicons -ailog gen -i ./repos/atproto/lexicons -o ./src/lexicons - -# Rebuild -cargo build -``` - -## Collection Schema - -### ai.syui.log.post - -```json -{ - "title": "Post Title", - "content": "Markdown content...", - "createdAt": "2025-01-01T00:00:00Z" -} -``` - -## Assets - -### PNG to SVG Conversion (Vector Trace) - -Convert PNG images to true vector SVG using vtracer (Rust): - -```bash -# Install vtracer -cargo install vtracer - -# Convert PNG to SVG (color mode) -vtracer --input input.png --output output.svg --colormode color - -# Convert PNG to SVG (black and white) -vtracer --input input.png --output output.svg -``` - -**Options:** -- `--colormode color` : Preserve colors (recommended for icons) -- `--colormode binary` : Black and white only -- `--filter_speckle 4` : Remove small artifacts -- `--corner_threshold 60` : Adjust corner detection - -**Alternative tools:** -- potrace: `potrace input.pbm -s -o output.svg` (B&W only, requires PBM input) -- Inkscape CLI: `inkscape input.png --export-type=svg` (embeds image, no trace) - -**Note:** Inkscape's CLI `--export-type=svg` only embeds the PNG, it does not trace. For true vectorization, use vtracer or potrace. - -## License - -MIT diff --git a/src/commands/post.rs b/src/commands/post.rs index 378bd4f..d8293df 100644 --- a/src/commands/post.rs +++ b/src/commands/post.rs @@ -234,7 +234,7 @@ struct DescribeRepoResponse { /// Sync PDS data to local content directory pub async fn sync_to_local(output: &str) -> Result<()> { - let config_content = fs::read_to_string("config.json") + let config_content = fs::read_to_string("public/config.json") .context("config.json not found")?; let config: Config = serde_json::from_str(&config_content)?;