わいえむねっと

Contents
Categories
Calendar
2026/08
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Monthly Archives
~2000/01
Recent Entries
RSS1.0
Templates
Information
Processed: 0.102 sec
Chashed: -
2026/08/12 Wed

TweetVault


GitHub - helioLJ/TweetVault: A full-stack bookmark manager for Twitter/X posts with tagging, search, and archiving capabilities. Built with Next.js, Go, and PostgreSQL. · GitHub
https://github.com​/helioLJ/TweetVault​


インストール

Docker の利用が推奨されている。
手持ちの Linux 環境が古いものばかりだったので新規構築しようとしたけど、どうも最近の Ubuntu は Windows Server 2012 の Hyper-V だとカーネルパニックでこける。
仕方ないので、Windows 11 の Hyper-V で構築。
Ubuntu 26.04 Server install image を使用。


2026年版:UbuntuへのDocker & Docker Compose 推奨インストール手順 - TUKUMO工房
https://tukumolog.​com/ubuntu-docker-compose-install-2026/

を参考に Docker をインストール。
続けてコンテナをビルド。


実行

Access the application:
Frontend: http://localhost:3000
Backend API: http://localhost:8080
Database: localhost:5432

マニュアルに従い、仮想環境のポート3000にアクセス。
画面は表示されたが、

TypeError: Failed to fetch

といったエラーが表示される。
デバッガで見た感じ、バックエンドへのアクセスが仮想環境ではなく localhost になってしまっている。

設定でどうにかできそうな気がしたけど、いったんターミナルソフトのポートフォワードで localhost に対するアクセスを仮想環境に流す。
エラーは変わらず。

ログを見ると起動途中でバックエンドが

Failed to load configuration: error loading .env file: open .env: no such file or directory

を吐いている。
確かに .env ファイルはない。

Docker を利用しない場合のインストール手順に .env ファイルについて記載があったので、そちらに従い配置。
これでエラーは解消。


ブックマークのインポート

ブックマークは別ツールでエクスポートしたファイルをインポートする形式なので、そちらのツールの導入から。
Tampermonkey か Violentmonkey が必要ということなので、Violentmonkey をインストール。

GitHub - prinsss/twitter-web-exporter: Export tweets, bookmarks, lists and much more from Twitter(X) web app. (推文/书签/收藏/列表导出工具) · GitHub
https://github.com​/prinsss/twitter-web-exporter


WebExporter の「データをエクスポート」で JSON ファイルを出力。
続いて TweetVault の「Upload Bookmarks」からアップロードしようとしたところはじかれた。
メディアのエクスポートファイルとセットでアップロードする必要があるらしい。

WebExporter から「メディアをエクスポート」をするにあたり、ブックマーク数がアホみたいにあるのでお試しで数件だけ選択してエクスポート。
ブックマークの JSON ファイルとメディアの ZIP ファイルを両方指定することでアップロードは通った。
表示もOK。
ブックマークは全量あり、画像はメディアをエクスポートした対象だけ表示されている状態。


画像の補完

わざわざ画像をインポートさせているのだからその画像を表示しているのかと思いきや、画像は元のアドレスから表示されていた。
テーブルの構造を見た感じ、バイナリは保持しているようだけど、なくてもいけそうな?

列名 内容
id 連番
tweet_id JSON内の id
type JSON内の media->type
url JSON内の media->url
thumbnail JSON内の media->thumbnail
original JSON内の media->original
file_data ZIP内のファイル実体
file_name ZIP内のファイル名
created_at作成日時
updated_at更新日時


file_data と file_name を除外した状態でデータを補完してみたところ、問題なく表示された。

import json

with open('export.json', encoding='utf-8') as file:
    obj = json.load(file)
    i = 0
    for x in obj:
        for media in x['media']:
            i += 1
            sql = "insert into media (id,tweet_id,type,url,thumbnail,original,created_at,updated_at)" \
                  " values ('{}','{}','{}','{}','{}','{}',current_timestamp,current_timestamp);".format( \
            i, \
            x['id'], \
            media['type'], \
            media['url'], \
            media['thumbnail'], \
            media['original'])
            print(sql)


画像表示のカスタマイズ

画像の縦横サイズが一律になっており、縦長の画像だと中央部分だけの表示になっている。
これをどうにかしたい。

高さを指定している場所が見つからず悩んだけど、幅と縦横比から決定されていて直接指定されてなかった。ああ。

frontend/src/components/bookmarks/BookmarkCard.tsx の下記を修正して解決。
  • img タグの親 div に指定されている aspect-video クラスが縦横比の指定なのでこれを外す
  • 親 div で高さが決定されなくなると fill で付与される position:absolute が原因で表示がおかしくなるので fill は外す
  • fill を外すと幅と高さを求められるので別途指定

@@ -343 +343 @@
-                  className="relative aspect-video cursor-pointer overflow-hidden rounded-lg w-full"
+                  className="relative cursor-pointer overflow-hidden rounded-lg w-full"
@@ -352 +352,3 @@
-                    fill
+                    width={0}
+                    height={0}
+                    style={{ width: "100%", height: "auto" }}



ブックマークの同期が手動なのは手間だけど、自前でカスタマイズできるってのはいいかなと。