garden.ooo

ロゴ:永良新さんデザインの Aratana というフォントをベースに2分でつくったロゴタイプ
baku89.iconが開発しているホームページ作成、ノートテイキング、Wiki、ナレッジベースシステム。
garden.oooというURLそのものがシステム名であり、サービス名。baku89.icon自身や友人のWebサイトの構築に使いながら開発を続けている
- Featured Projects(2025 March–WIP)
- baku89.com
- Spacenotblank(2026 Feb.–WIP)
旧名:Morion
要するに
- 「個人ホームページ」をつくるための仕組み
- ハイパーテキストの再発見
- カテゴリや投稿タイプという階層構造や、ブログや日記といったタイムライン構造に縛られた今日のWebから、WWW本来のリゾーム性を取り戻す
- Local First
- 全情報はローカルにテキストファイルとして保存される
- データをクラウドに人質にとらない。むしろ、ローカルこそがsource of truthで、クラウドはそれをミラーする存在
- データの実体はただのテキストファイルだから、garden.ooo に限らず色んなシステムで編集したり開くことができる
- ダダ漏れをアフォードする
- 公的な文章から私的なメモまで、色んなものを安心して綯い交ぜに載せておけるシステム
- 公開範囲を細かく設定できる
- 見られることを意識したアーカイブページ)と個人的で無責任なメモとを混在させる
設計原則
階層性と線形性を信じない
普通のCMS開発のように、work、event、member のような投稿タイプや、 /2025/some-post といったディレクトリに分類したりはしない。そうした設計はその瞬間の見立てにすぎず、「workでもありeventでもある」ような中間的なコンテンツの登場とともに破綻する運命にある。コンテンツ同士の連関は「AがBに属する」のような含有関係ではなく、「AがBを指し示す」というリンクによってのみ決まる。また、garden.ooo では「ページ(エンティティ)」と「タグ(タクソノミー、分類子)」の区別をしない。(Cosenseを参照)
ローカル・ファースト
ページは常にローカルに置かれたテキストファイルとして保存され、相互同期する。ローカルは単なるバックアップではなく、オリジナルそのもの。書き手の「第二の脳」をクラウド上に人質に取らない。
プレーンテキストは普遍的なインターフェース
ページのソースはプレーンテキストによって表現される。CMSの管理画面だけではなく、メモ帳からも編集出来るし、ほかのCMSにインポートすることも、コマンドで一括置換することも、AIに喰わせることもできる。このサイトはbaku89.iconの好みでMarkdownを採用したが、HTMLに変換できさえすれば、Cosenseのブラケット記法でもなんでも好きな構文をユーザーは採用することができる(予定)。
ちょうど今日、The VergeにObsidian CEOのSteph Angoへのインタビューを読んでいて、面白い下りがあった。
「ひとつ面白い展開として、ぼくはステフにこう尋ねた。多くの競合が生産性ソフトに次々とAI機能を詰め込もうとしているのに、なぜ Obsidian はそれに倣おうと急いでいないように見えるのか、と。
Obsidian’s CEO on why productivity tools need community more than AI | The Verge
これは的外れも良いところで、「プレーンテキストを用いる」という設計がその答えだろうと思っている。だって、Obsidianの実体は手元のPCに保存されたただのテキストファイルなんだから。文字通り Notion AI 連携できない Notion と違って、ObsidianはCursorでもVS Code + GitHub Copilotでも、どんなIDEやAIシステムとも統合することができる。
Obsidianには、多くのプラットフォーマーが口にする「エコシステム」なんて意識はなくて、プレーンテキストを介した、人類がこれまでに築き上げてきたコンピューティング文化という、より大きなものの一部であるっていう自覚と謙虚さがあるんだと思う。OpenDocやUNIX思想にも通ずるものを感じる。
ダダ漏れをアフォードする
コンテンツの階層構造同様に、その書き手の気分もまた、公か私か、寄稿かつぶやきかといった境界で割り切れるものではない、連続的なもの。garden.oooでは、そうした曖昧さを切り捨てず、そのままに受け止められる「構造のなさ」を大事にしている。ブログとニュース、リサーチとブックマークは区別なく保管でき、両方のタグをもたせればその中間的な性質をもたせることができる。ページの公開設定やクロール設定も多段階でセットできるし、気まぐれで変えることもでる。だからこそ、書き手は自分の思考や制作の過程を「ダダ漏れ」のまま残しておけるし、読み手はその連続性を含めてアクセスできる。
- Archival フラグの導入
- Archival pages: 見られることを意識したアーカイブページ)
- Scrachpads: 個人的で無責任なメモ
メモたち
利用モード
- Browser mode: まずは、アカウント作成すらせずに使い始めらる。データはユーザーのブラウザに直接保管される
- Origin Private File System (OPFS)、あるいはIndexedDB + mysqlite3 on wasmで
- Local mode: ディレクトリを選択すれば、自動的にローカルの
.mdとも同期される- それをDropboxとかで他のデバイスと同期すれば複数端末からでも編集できる。
- あるいはそのフォルダをまるごとObsidianのVaultにするとか。
- Browser modeにおいても、OPFS上に.mdファイルは保存されているから、実装は殆ど変わらない
- Server mode: サーバーにデータを保管したくなって初めてアカウント登録をする
- たとえば:
- モバイル端末との同期をしたい時(iOSはFile System Access APIでiCloudドライブにアクセスとか出来ないので)、
- Web上に公開したい時
- 複数人で簡単に共同編集したい時
- そのアカウントとページが作られている事自体は公表され、検索可能であり、
/index.mdは常に見られる - オリジナルの
.mdはE2Eで保管される- エンベロープ暗号
- 限定公開コンテンツは
- 一般公開サイトだけがSSRされる。それ以外は、クライアントサイドで
.mdのパースとDOMレンダリングが行われる。
- エンベロープ暗号
- 基本的にはOAuthだけ。専用のアカウントを作る必要がない(その方が開発楽だし)
foobar.garden.oooのようにサブドメインが与えられる- 画像は、適当に上限を決めてアップロードは可能
- アップロード上限を超えたいときは、
クライアントサイドで復号可能なWordpressのAPI Keyなどを与えて、自前のサーバーにアップロードするか、課金モデルに移行する
- アップロード上限を超えたいときは、
- Headless CMSとして使うためのAPIは、
localhost等の開発環境には常に開放されている。
もし外部ドメインから呼び出したい際は、後述の課金モデルに移行する。(これってドメイン偽造可能なの?)
- たとえば:
名前
Digital Gardeningから。トンチキでナンセンスな感じ。Cosenseは素敵な名前だと思うけど、「言霊」を込めすぎているのがbaku89.iconの感覚だと惜しい。Helpfeelという社名からしてそうだけど……。
サービス名表記は一貫して garden.ooo。読み方はそれぞれに任せる。「ガーデン」でも「ガーデン・オー・オー・オー」、「ガーデン・トリプルオー」でもなんでもいい。
雑多なメモ
- Obsidian, Cosense, Notion, Evernote, Wordpressといったものの中間
- 中間というか、ディレクトリで整理されたmarkdownというデータを中心としたOpenDoc的なエコシステムに対して「CMS」という角度から補完するものっていう感覚?
- 投稿タイプやタグ、カテゴリ、フォルダ分けという概念のない、ただのテキストファイルで相互リンクするページの集まりとしてサイトを構築できる
- コアにあるのはAPI
- https://featuredprojects.jp のために開発し、このサイトで投入しながら安定化を図っている
- 使えそうなMarkdown拡張
設計
→ Principles for Digital Gardening
各ページは本質的には以下の情報から成り立つ
- ユニークなpath (e.g.,
/hello,/2025/some-posts) - DBにシリアライズ可能な何らかのデータ(JSONなど)
畢竟、本文すら必要ない。英単語のデーターベースサイトとかだと実際そうなると思う。Nuxt ContentはYML, CSVファイルをページデータとして使用することができる。
ただし、一般的にはページからなるサイトの構築にも使うものなので、プレーンテキストからHTMLの構文木にパース可能な言語を選定しておく。
以下、Lightweight markup language (LM言語) と呼ぶ。
- HTMLそのもの
- Markdown
- Cosenseブラケット記法
- Textile
- 以下のVDOMそのものを表したJSONテキスト(何らかのリッチテキストエディタで編集される前提で)
構文木は例えばこういう感じ。(Nuxt Contentにおける内部表現の例。rehypeでもremarkでもどの表現方法でもOK)
{
type: 'root',
children: [
{
type: 'element',
tag: 'p',
children: [
{type: 'text', text: 'Hello, World!'}
]
},
{
type: 'element',
tag: 'img',
attributes: {
src: 'https://example.com/some-image.jpg'
}
}
]
}
これをVueでもReactでも、VDOMを実際のDOMに変換可能なフロントエンドライブラリに流し込み、Webを表示させる(あるいはCGIでもいい)
投稿タイプやメタデータのスキームは、流動的に変化させられるようにする。NoSQLで構築したいところ。Markdownだと、Frontmatterにこういう感じのものを書き込める。
ここはObsidianとできるだけ互換性をもたせたい。
created: 2025-08-20
title: Hello World
title_locale:
ja: こんにちは、世界!
layout: grid
sort_by: modified
visibility: public
tags:
- video
- diary
linkとbacklink
ページ同士は、本文のリンク、あるいはtagsを介して関連性をもたせる。たとえば、「メンバーA」のページを「チーム」に関連付けるには、
単ページの中で「チーム」のpathにリンクを貼ればいい。
CMSにおけるタグ分類と違うのは、「チーム」と「メンバーA」のページに本質的な違いは無いこと。オブジェクト(括られるもの、対象)と
タクソノミー(分類子)を区別しない。カテゴリやフォルダによる木構造の分類に対して、タグによる分類はいわば二部グラフではあるが、
MorionについてはCosense同様有向グラフの構造をもたせる。
そして、「リンクされたもの」から「リンクしたもの」には自動的にバックリンクが貼られる。この機能をうまく使うことで、従来のCMSにおける
カテゴリや投稿リストいったものを表現する。
→ Backlink
Morionの現状の実装では、「タグによるリンク」と「本文中からのリンク」を便宜的に区別している。
タグリンクのほうが本文リンクよりもより高い関連性を示唆する。
- タグリンク: 所属、包摂、共通性
- 本文リンク: 言及
例えば、「チーム」というページをカテゴリのように運用したいときには、チームメンバーからタグリンクを貼ることとする。
かつ、ページのレイアウトをデフォルトのpageからそれ以外のもの(FPとこのサイトではgrid, tableを用意)に加えることで、
本文後に追記されるbacklinksから本文リンクを除外することができる。
layout: grid
sort_by: title
sort_order: asc
こうすることで、「チームメンバーはこちらを御覧ください!」という関係のないページがチーム一覧に表示されるのを防ぐ。
公開設定
public: 誰からもみることができ、リストにも表示されるunlsited: 一切のページリストには表示されず、URLの直接入力や直リンクのみで表示できるproteced: 何らかの認証(パスワード、OAuth、WebAuthn等)越しに見ることができる- 数人への共有、メンバーシップ制、あるいは同じCMSを使うメンバー間でのみ閲覧可能
github:baku89,mail:b@baku89.comとか。
private: 書き手だけが見ることができる
archivalフラグ
全てのページは、公開設定とは別にarhivalというフラグを持つ。
これによって、永続化したいものと、エフェメラルなものを区別する。
- Archival: 公開ページ(不変のURLで公開され続け、引用可能なもの)
- permalink
- Scratchpad: メモ書きページ(一応見ることのできる個人的なメモ書き)
- no-index, no-follow
詳細はそれぞれのページを参照。
そして、archivalページは、バージョン管理が出来るようにする。SemVerで。
${major}.${minor}.${patch}
patch: 誤字修正。編集のたびに勝手にインクリメントされるminor: 普通の改稿major: 文章全体の構造が一変するくらいの大きなアップデート。
一度 1.0.0 を付与したテキストは、できる限り取り下げられないようにする。
多言語対応
LMLは多言語を扱えるように拡張してもいい。FPとbaku89.comではこうした、WordpressのqTranslatorに則ってこういう記法を採用している。
[\:ja]
**なんらかの強調文字**
[\:en]
**Some emphasized texts**
[\:]
「\」は無視して! プリプロセッサ的に正規表現置換しているから、このタグを普通に入力するとそれ自体が多言語ブロックとして解釈されちゃう
けどなんでもいいかも。今ならぼくはこうするかな。
<!--ja-->日本語<!--:en-->English<!--:-->
あるいはMDC記法にのっとって
::en
some texts
::
::ja
何かの文章
::
とか、
::locale
#en
some texts
#ja
::
だっていい。
API
いや、これはいらないなぁ。RxDBを使うんだもの
/api/pages?tags=tools&limit=5- まちがえた、取得件数に上限を設けるのを忘れてて、そのままアクセスすると(公開されている)全ページがdumpされてしまう
/api/page?path=&2Fmorion- 常にpathにleading slashをつけるか迷う。やめたほうがいいと思う
/api/search-index/api/pages-count
仲間の募集
興味がある人としたいな
フロント、バックエンド、デザインで数名で。

