はじめに
Busker Beat は路上ライブ演者の「出没情報」を地図上に可視化し、演者が日々の演奏記録をつけ、ファンとつながることができるアプリです。
- 技術スタック
- Flask (Python3)
- PostgreSQL (Renderでホスト)
- HTML/CSS/JavaScript/Leaflet.js
- Git/GitHub + Render でデプロイ・管理
- 完成イメージ: 地図クリックで投稿場所の緯度経度を自動入力 → モーダルからDBへ登録 → 即時マップに反映
アプリ概要
1. 地図(Leaflet.js)
- 地図上で投稿ポイントを可視化
- ダークなタイルレイヤーで独特な雰囲気
2. 投稿機能
- モーダルを使って演者名・投げ銭額・セトリなどを入力
- マップクリックで緯度経度取得
- Ajaxで即反映し、リロードなしでマーカーが増える
3. ユーザー認証
- ログイン・新規登録はモーダルで完結
- Flaskセッションでログイン状態を管理
- ログインユーザーだけが投稿可能
UIのコンセプトは「地図が中心」かつ「オブジェクト指向の直感的操作」です。
ディレクトリ構成
busker_beat/
├── myapp.py # Flaskのエントリポイント
├── requirements.txt
├── static/
│ └── css/
│ └── styles.css # ダークテーマ+モノトーン+赤
├── templates/
│ ├── index.html
│ ├── _map.html
│ ├── _post_cards.html
│ └── _auth_modal.html
└── config.py # DB接続情報
- _map.html: 地図 + 投稿フォームモーダル
- _post_cards.html: 投稿一覧(左カラム表示)
- _auth_modal.html: ログイン/新規登録のモーダル
- styles.css: 黒背景+赤要素のUIテーマを定義
Flaskのルート処理
以下は主要ルートのみ抜粋。
@app.route("/")
def home():
conn = psycopg2.connect(...)
cur = conn.cursor()
cur.execute("SELECT * FROM bb_posts ORDER BY id DESC;")
posts = cur.fetchall()
# postsをテンプレートへ
return render_template("index.html", posts=posts)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
# DBからユーザー取得
# check_password_hashで照合
# セッションにuser_idを保存
return redirect("/")
return render_template("login.html")
@app.route("/signup", methods=["GET", "POST"])
def signup():
if request.method == "POST":
# generate_password_hashでハッシュ化
# DBにINSERT
return redirect("/")
return render_template("signup.html")
@app.route("/logout")
def logout():
session.clear()
return redirect("/")
@app.route("/posting", methods=["POST"])
def posting():
# Ajaxで受け取ったFormDataをDBにINSERT
# 成功ならJSONで { success: True, ...} 返す
return jsonify(...)
ポイント:
- /posting は画面表示しないバックエンド処理
- /login / /signup はモーダル想定だが、従来の画面遷移にも対応
- session["user_id"] があるかどうかでログイン判定
PostgreSQLでのデータ管理
DB構成は以下。SQLを管理しやすいようにシンプルに作成。
CREATE TABLE bb_users (
id SERIAL PRIMARY KEY,
uname TEXT UNIQUE NOT NULL,
email TEXT UNIQUE NOT NULL,
pw TEXT NOT NULL
);
CREATE TABLE bb_posts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES bb_users(id),
artist_name TEXT,
lat FLOAT NOT NULL,
lng FLOAT NOT NULL,
audience INTEGER,
setlist TEXT,
amount INTEGER,
event_date DATE,
created_at TIMESTAMP DEFAULT now()
);
- ハッシュ化されたパスワードを pw に保存(werkzeug.security利用)
- user_id で bb_users と紐づけ → 投稿者追跡可能
- lat, lng は FLOAT。地図クリック→AjaxでINSERT
SQLの具体的なINSERT/SELECTはFlaskのコードに埋め込んだ。
レイアウト:オブジェクト指向UI
- 地図を画面右側、左に投稿一覧
- クリックで投稿: マップオブジェクトそのものに手を触れるイメージ
- モーダルを多用し、「画面遷移」を最小限に抑えた
これにより、「オブジェクトを配置する感覚」+「入力フォーム」が直感的にマッチ。
企画図:
ラフ:
Git/GitHub + Renderでのデプロイ
- git add . && git commit -m "feat: add map + modals"
- git push origin main → Renderが自動デプロイ
- Render でDBを作り、環境変数に SECRET_KEY を設定
- 公開URL: https://busker-beat.onrender.com
継続的に変更しても、GitHub連携で自動ビルドされるのが便利。
まとめ & 所感
- Flaskでのルート処理は非常にシンプルに書ける
- Leafletとの連携で直感的な投稿が実現
- PostgreSQLでのリレーション管理により、ユーザー認証と投稿がしっかり紐づく
- オブジェクト指向UI (地図クリック→モーダル投稿→非同期DB保存) は、使ってみるとかなり直感的
今回の制作で学んだのは、シンプルな設計 + UI/UXを意識することで、少ないコード量でも便利なアプリができるということです。
今後の拡張
- ログインユーザー別のマイページ
- コメント機能 or いいね機能
- Tailwind導入でUIをさらに洗練
- Docker化で開発環境を安定化
もし似たような機能を作りたい人がいれば、ぜひ参考にしてみてください!
以上、「Busker Beat」開発の備忘録でした。