旅した国・街をマップで表示できるサイトを作った。

行った国や街を登録してマップに表示できるサイトを作ったので、紹介します。

https://bokenmap.com

## イントロ

今回作ったのは、行ったことのある国と街を登録して、地図に表示することができるWebアプリケーションです。使い方としては、プロフィールページのリンクをSNSに載せたり、地図をiframeタグで他のサイトに埋め込むことを想定しています。

プロフィールページの具体例
[https://bokenmap.com/hikaru](https://bokenmap.com/hikaru)

![](https://storage.googleapis.com/zenn-user-upload/1a137814df90-20240408.jpg)
*こういう感じの地図が作れる*

[自分の個人ホームページに埋め込んでみた例](https://hikaruimai.vercel.app/travel)


## 課題

僕は旅行が好きなんですが、ウェブ上で「行ったことのある国」をパッと見せたい時に毎回困ります。ブログやSNSなどで自分の旅の経歴みたいなものを公開したいときに、最適解がないのです。文字で国名を書いてみたり、人によってはプロフィール文に国旗の絵文字を並べまくったり、地図画像を作ってそれを貼るなどの方法がメインで、どれも正直パッとしません。

地図で表現するのは良いんだけど、地図を作るプロセスも現状だと結構きつい。地図を表示する既存の選択肢としては、[visitedplaces.com](https://visitedplaces.com/)のように地図画像やコードを生成するサイトか、[Googleマイマップ](https://www.google.com/intl/ja/maps/about/mymaps/)みたいな細かい機能がついているツールがあったりしますが、どれも自分の求めるものとは少し離れています。前者の地図作るよ系サイトはその都度画像やコードを生成するので、**行った国が増える度に毎回画像やコードを出力し直さないといけず、更新していくというのが面倒**。後者のツールはルートを作ったりするのは便利だけど、他の人に行った場所を見せるという観点からすると**見た目が微妙だし機能的にもオーバーキル**な気がする。

理想的なのは、インターネット上にとりあえず自分の行った国や街を表示しているWebページがあり、どこに行ったことがあるの？と聞かれたらそれをパッと見せるみたいな状況。あるいはSNSとかでもリンク一つで自分の旅の経験を見せられるみたいな。国や街の登録が簡単で、変な機能がついてない(行った日付入力とかいらない)シンプルな仕組みのWebアプリが欲しかったので、今回それを作ったという感じです。

## 機能

メインの機能は、国または街を登録するとそれが地図やリストでプロフィールページに表示されること。

[![](https://storage.googleapis.com/zenn-user-upload/ad973c429084-20240408.jpg)](https://bokenmap.com/hikaru)

フォロー機能もあって、他のアカウントをフォローする/されることもできます。旅先で出会った人をフォローする的な使い方が実現すれば良いなと思ってます。

機能面でのポイントは、

* 他のサービスのように一時的ではなく、長期間更新していけること
* Webページなので世界のどこからでも、どのデバイスからも見れること
* シンプルでわかりやすいこと

各国や街のステータスには三種類あって、Lived(住んだことある)、Visited(行ったことある)、Transited(トランジット・経由したことがある)で色が違う。

![](https://storage.googleapis.com/zenn-user-upload/d367297e832c-20240408.jpg)

それぞれの明確な定義は特になくて、各自が適宜考えて使う仕様。例えば、住んだことあるは1年以上とか、行ったことあるは宿泊したとか、トランジットは空港だけで入国してないとか。

## 使った技術

### デプロイ関連

Vercelにデプロイしていて、データベースはSupabaseをはじめて使いました。Supabaseはとてもわかりやすくてファンになったので今後も使っていこうと思ってます。
今期のYCombinatorでもスタートアップの[約3分の1弱がSupabaseを使ってる](https://twitter.com/kiwicopple/status/1775331025041997980)らしく、とりあえず早く物を作る上ではとても良さそうです。

ちなみに最初Supabaseのサーバーの場所を`ap-northeast-1`(日本)に設定していたらなんだが遅くて、それを`us-east-1`(アメリカ東海岸)でやり直したら体感的にかなり早くなりました。おそらくVercelのデフォルトのサーバー位置がアメリカの`us-east-1`で、僕がそれを変更していなかったらだと思います。SupabaseもVercelもAWSの小売事業みたいな感じで、AWSの`us-east-1`を使ってるということだから下手したら同じ建物内にアプリケーションとデータベースを置けたくらいの距離感じゃないかな。

https://vercel.com/guides/choosing-deployment-regions

### amCharts (Maps)

国の地図を表示するために使いました。

![](https://storage.googleapis.com/zenn-user-upload/75f7c3fba409-20240408.jpg)

シンプルながら色や動作面で色々細かい設定ができて便利でした。クリックしたら何かデータが表示されるとかもやりたかったんですが、とりあえず該当するWikipediaのページに飛ばすという挙動にしました。
地図の図法に関してはデフォルトのものの中で良いのが無かったのでd3(d3-geo-projection)というライブラリを調べて`geoCylindricalStereographic`というものにしました。メルカトル図法だと高緯度があまりに拡大されすぎて見た目が悪く、円形に寄せてるものはUI的に似合わなかったので。

### MapLibre

amChartsのmapではより細かいレベルの表示に向かないので街の地図を表示するためにMapLibreを使いました。もともとオープンソースだったMapBoxがオープンじゃなくなった時にフォークしてOSSとして継続しているものです。MapBoxは金がかかりそうで怖かったのでMapLibreにしました。
ちなみに当初は素のOpenStreetMapにしようと思ったんですが、地図の画質があまりにもクソだったのでやめました。

![](https://storage.googleapis.com/zenn-user-upload/e9735cac6f63-20240408.jpg)
*こっちはメルカトル図法から変えられんかった。Geoapifyが理由かも。*

これは今回初めて知ったのですが、MapLibre上で色々な見た目の地図を表示するためにはタイルというものを別途用意する必要があって、それをホスティングしているサービスに頼る必要がありました。てっきりMapLibreだけ色々な設定をして完結すると思っていたら、デフォルトの選択肢以外の見た目にするにはタイルが必要なようです。MapTilerやらStadiaMapsなど色々な選択肢を比較検討して、最終的に[Geoapify](https://www.geoapify.com/map-tiles)というものを使いました。APIを都度叩く感じですが、無料枠があってクレカ登録も不要だったのでこれにしました。
タイルをセルフホスティングという手もあるらしいけど、さすがに高度すぎるので今回はスルーしました。

![](https://storage.googleapis.com/zenn-user-upload/d8da41e9b7e9-20240408.jpg)
*比較検討の痕跡。情報間違ってるかもしれんから気をつけて。*

### Geonames

街の検索用APIとして使っています。無料で使えるけどリミットがあるっぽくて、今回のサービス内での最大のボトルネックです。全然普通に使えてるけど、保証があるというわけでもない。ただすごく便利で、文字を送ると候補順に街のデータ(座標とか)を含んだリストを返してくれるから神。他にも山とか川も検索できるから今後他の用途にも使ってみたい。npmの[これ](https://www.npmjs.com/package/geonames.js)経由で使ってます。

ちなみに国の方は街に比べて圧倒的に母数が少ないので深いこと考えずにjsonファイルを自分のアプリで持ってる感じです。

![](https://storage.googleapis.com/zenn-user-upload/26796133d957-20240408.jpg)
*こういう感じで使ってる*


## 今回学んだこと

### ソートはすごい

色々な種類のソートがあることは知っていたのだですが、今までその威力を体感したことがあまり無かったのを今回体感できました。街のリストをアルファベット順で並び替える機能を作る時に、もともとBubble SortだったのをMerge Sortに変えたら爆速になって、Big O Notationとかって大事だなと思いました。コンピュータサイエンスやってる人にとっては当たり前だろうけど。

### 依存はだるい

色々なサービスに依存している感じになってしまって今回のプロジェクトはダルさが結構ありました。ライブラリを使うとかは良いと思うんですけど、APIに首根っこを掴まれるとかはやっぱり気持ち良くないですよね。まあ自分では到底できないことをやってもらってるので文句は言えませんが、できれば独立自尊・自己完結のコードを書いていきたいものです。

### テンプレートエンジンはやめる

EJSを使ったんですが、普通にReactとかNextjsで物を作るということをしようと思いました。テンプレートエンジンは初心者的にはすごいわかりやすいシンプルな仕組みなのですが、UIを色々やるみたいなことが難しいというのがようやく体感的に理解できました。VanillaのクライアントJSコードがかなりわかりにくい複雑な感じになってしまったので、次回以降はさすがに変えようと思います。

### 自分が使う物を作る

今まで「自分が使う物を作ってる」ようで作っていなかったのが、今回はガチで自分が使う物を作ってみました。世の中で全く欲しいと思う人がいなくても最悪自分が使うから無駄にはならない、自分が欲しいということは数人くらいは欲しいと考える人がいるくらいのマインドが大事かなと思います。

## その他

### 制作期間

2ヶ月。

### 英語

国名とか街の名前を多言語化するのがダルそうだったので全部英語で作りました。旅行好きならどの国の人も英語できると思うので問題でもない気がする。

### かかったお金

ドメイン代だけ。あとは無料枠とかでやりくり。

## 旅人は使ってみてね

1ヶ月後にサービスを閉じるとかは(おそらく)しないと思うので、長期的に旅を記録していくツールとしてぜひ使ってみてね。

https://bokenmap.com