「『半年ROMれ』『荒らしに反応する奴も荒らし』――2ちゃんねる文化の核心は、自治ではなく個人のスルー力にある」
令和に自作した2ちゃんねる風掲示板「つゔぁいちゃんねる(2ch.biz)」開発秘話の第16弾。今回は、サーバーに頼らずブラウザ(localStorage)だけで完結させ、見たくないコテハンや荒らしレスを瞬時に消し去る2大表示モード(行あぼーん / 透明あぼーん)の実装テクニックを公開します。
💡 はじめに:なぜ「クライアント側NG」が最高なのか?
匿名掲示板を運営していると、必ずユーザーから「〇〇というコテハンがうざいから管理人が削除してください」「アニメのネタバレを書いた奴をアク禁にしてください」という要望が届きます。
しかし、明らかな規約違反(脅迫や違法行為)ならともかく、「単に気に食わない意見」や「個人的に嫌いなノリ」まで管理者がいちいち手動で削除していたらキリがありません。管理者が個人の好みに介入しすぎると、掲示板は息苦しい検閲社会になってしまいます。
古き良き2ちゃんねるには、この問題を解決する最高の知恵がありました。
「嫌なものは、自分の画面から見えなくしてしまえばいい(あぼ〜ん)」
専用ブラウザ(JaneStyle等)を使っていた人なら誰もがお世話になった「ローカルNG機能」。
これを、外部アプリ不要・ブラウザのWeb標準機能だけで完璧に再現するため、開発初期(2026年8月18日夜)に 「個人用ローカルNGシステム」 を開発しました。
🏗️ 完全クライアントサイド(localStorage)設計の3大メリット
つゔぁいちゃんねるのNGシステムは、 サーバー通信を1バイトも行いません 。
すべての設定とお気に入りは、ユーザーのブラウザの localStorage 内にのみ保存されます。
graph TD
A[サーバーからスレッドレス一覧取得] --> B[ブラウザのJavaScript描画ループ]
B --> C{localStorage のNGリストと照合}
C -->|NG ID・NGワードにヒット| D{あぼーん設定モード}
D -->|通常: 行あぼーん| E[「あぼーん [クリックで一時表示]」として描画]
D -->|透明あぼーん| F[DOM要素をスキップ (完全消去)]
C -->|該当なし| G[通常のレスとして描画]
1. 究極のプライバシー保護
「誰がどの単語やIDをNG登録しているか」は、サーバーの管理者(私)にすら絶対に分かりません。完全に個人の秘密として保護されます。
2. サーバー負荷ゼロ・API遅延ゼロ
NG判定はすべてクライアント(ブラウザのCPU)で実行されるため、1万人のユーザーがそれぞれ100個のNGワードを登録していても、サーバーのデータベース負荷は 完全ゼロ です。
3. ログイン不要で即座に使える
アカウント登録やクッキー承諾を一切求めず、サイトを開いたその瞬間から誰でも自分専用のNGリストを構築できます。
👀 2つの「あぼ〜ん」表示モードの実装
専ブラ愛用者のこだわりを満たすため、伝統の 「2種類のあぼーんモード」 を搭載しました。
1. 行あぼーん(デフォルト)
レス番号とヘッダーだけを残し、本文を伏字にして折りたたむモードです。
12 :あぼーん :あぼーん [NG設定(NGワード: ネタバレ)により非表示 (クリックで一時表示)]
- アコーディオン展開 : 行をクリックすると、その場で「シュッ」と元の本文が展開され、もう一度クリックすると再び折りたたまれます。
- 安心感 : 「あ、ここで誰かが荒らしていたんだな」という空気感だけを把握しつつ、不快な文言は視界に入りません。
2. 透明あぼーん
「あぼーんという文字すら見たくない!」というストイックなユーザー向けのモードです。
該当するレスをDOMツリーから完全に排除し、 レス11の次が即座にレス13になる ように表示を詰め込みます。
💻 描画ループとNG判定の実装
最大の技術的ポイントは、 「DOMを描画した後に消す」のではなく、「DOMを生成するループの段階で判定して差し替える」 ことです。
一度描画してから消すと、画面が一瞬チカッと点滅するFOUC(Flash of Unstyled Content)が発生してしまうからです。
// LocalStorageからのNGデータ読み込み
function getNgSettings() {
const defaultSettings = {
mode: 'line', // 'line' (行あぼーん) または 'transparent' (透明あぼーん)
words: [],
ids: [],
names: []
};
try {
const stored = localStorage.getItem('2ch_local_ng_settings');
return stored ? JSON.parse(stored) : defaultSettings;
} catch {
return defaultSettings;
}
}
// レスがNGに該当するかを判定する関数
function checkIsNgPost(post, ngSettings) {
// 1. NG ID チェック
if (ngSettings.ids.includes(post.user_id_hash)) {
return { isNg: true, reason: `NG ID: ${post.user_id_hash}` };
}
// 2. NG ワード チェック(本文)
for (const word of ngSettings.words) {
if (word && post.content.includes(word)) {
return { isNg: true, reason: `NGワード: ${word}` };
}
}
// 3. NG 名前 チェック
for (const name of ngSettings.names) {
if (name && post.name.includes(name)) {
return { isNg: true, reason: `NG名前: ${name}` };
}
}
return { isNg: false };
}
// レス一覧の描画ループ
function renderPosts(postsContainer, postsList) {
const ngSettings = getNgSettings();
postsContainer.innerHTML = '';
postsList.forEach(post => {
const ngCheck = checkIsNgPost(post, ngSettings);
if (ngCheck.isNg) {
// 透明あぼーんの場合はDOM要素自体を作らずスキップ
if (ngSettings.mode === 'transparent') {
return;
}
// 行あぼーんの場合は折りたたみDOMを生成
const abornElement = createAbornPostElement(post, ngCheck.reason);
postsContainer.appendChild(abornElement);
return;
}
// 通常レスの描画
const postElement = createNormalPostElement(post);
postsContainer.appendChild(postElement);
});
}
⚡ ワンクリックNG登録と設定モーダル
操作性を極限まで高めるため、各レスのヘッダーにある投稿者IDの横に小さな [NG] ボタン を設置しました。
名無しさん 2026/08/18 20:30 ID:m9Ka1L0q [NG]
荒らしを見つけたら、この [NG] を1タップするだけで、ダイアログ確認を経て即座に localStorage のNG IDリストに追加され、その場で画面全体の該当レスがあぼーんへと切り替わります。
さらに、ヘッダー右上の 「⚙️ NG設定」 ボタンを開くと、以下のような管理モーダルが表示されます。
- 表示モード切替 : ラジオボタンで「行あぼーん」と「透明あぼーん」を瞬時に切り替え
- NGワード一覧 : 登録されている単語の確認、手動追加、個別削除
- 一括消去 : 誤って登録しすぎた場合のクリーンアップ
🎯 まとめと次回予告
第16回となる今回は、2ch文化の神髄である「スルー力」をブラウザ上で完全自動化する 「個人用ローカルNG(あぼ〜ん)」 の設計と実装について解説しました。
今回の学び・ポイント
- スルーを技術で支援する :検閲に頼らず、ユーザー一人ひとりが自分好みのタイムラインをカスタマイズできる自由を提供する。
- localStorageによるプライバシーと性能の両立 :サーバーを介さない設計が、最高の速度とセキュリティを生む。
- チラつきゼロの描画設計 :DOM構築ループ内での判定により、ネイティブアプリのように滑らかな表示を実現。
自分の視界を快適にする手段は手に入りました。
しかし、明らかな犯罪予告や深刻な名誉毀損など、 「個人でスルーするだけでは済まされない悪質なレス」 はどうすればいいでしょうか?
次回、 【第17回】自律的コミュニティ運営へ!ワンクリック通報機能と管理者モデレーションキュー へと続きます!
🔗 関連リンク
- 本番サービス : https://2ch.biz/