Skip to content

Commit f55fb18

Browse files
committed
Add free-tier deploy scaffolding (Community Cloud + Xserver redirect)
1 parent 36b14db commit f55fb18

6 files changed

Lines changed: 178 additions & 5 deletions

File tree

.streamlit/config.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Streamlit runtime + theme defaults used by the public deployment.
2+
#
3+
# The theme palette matches ``app/_common.py::apply_theme`` so the first
4+
# paint (before custom CSS kicks in) is already on-brand.
5+
6+
[theme]
7+
base = "dark"
8+
primaryColor = "#38bdf8"
9+
backgroundColor = "#05060a"
10+
secondaryBackgroundColor = "#0b1120"
11+
textColor = "#e2e8f0"
12+
font = "sans serif"
13+
14+
[server]
15+
maxUploadSize = 20
16+
enableCORS = false
17+
enableXsrfProtection = true
18+
19+
[browser]
20+
gatherUsageStats = false
21+
22+
[client]
23+
showErrorDetails = false

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,59 @@ The dashboard has four pages:
110110
- **Compare** — run a small hyper-parameter grid and inspect the result
111111
with parallel-coordinates and overlaid trajectories.
112112

113+
## Deploy to the public web (free)
114+
115+
The dashboard can be published for free via **Streamlit Community Cloud**
116+
(or Hugging Face Spaces) and bridged from any domain you already own
117+
(Xserver / お名前ドットコム / Cloudflare / …).
118+
119+
### 1. Deploy to Streamlit Community Cloud
120+
121+
The repository already ships the two files needed by Community Cloud:
122+
123+
- [`requirements.txt`](requirements.txt) — CPU-only PyTorch pin plus the
124+
minimal runtime. Installs this repo as the `qqa` package via the
125+
trailing `.`.
126+
- [`.streamlit/config.toml`](.streamlit/config.toml) — on-brand dark
127+
theme and telemetry off.
128+
129+
Then:
130+
131+
1. Go to <https://share.streamlit.io> and sign in with GitHub.
132+
2. **New app** → Repository `Yuma-Ichikawa/QQA4CO`, Branch `main`,
133+
Main file path `app/streamlit_app.py`.
134+
3. Click **Deploy**. Your app will be served at
135+
`https://<something>.streamlit.app` after a 3–5 min build.
136+
137+
The custom-problem editor is **off by default** on public deployments
138+
(it evaluates arbitrary Python via `exec`). Re-enable it on a trusted
139+
machine with:
140+
141+
```bash
142+
QQA_ALLOW_CUSTOM=1 uv run qqa gui
143+
```
144+
145+
### 2. Point your own domain at the app
146+
147+
If you own a domain on a shared rental host (e.g. Xserver), drop this
148+
snippet into the `public_html/` of the subdomain that you want to use
149+
(adjust the target URL):
150+
151+
```apache
152+
RewriteEngine On
153+
RewriteRule ^(.*)$ https://qqa4co.streamlit.app/$1 [R=301,L]
154+
```
155+
156+
A ready-to-copy template with both `301` and `iframe` variants lives at
157+
[`deploy/xserver-htaccess.example`](deploy/xserver-htaccess.example).
158+
159+
### Other targets
160+
161+
The repository is portable enough to drop onto any of the usual
162+
platforms: Hugging Face Spaces (Streamlit SDK), Fly.io / Render
163+
(Docker), Google Cloud Run. The same `requirements.txt` and
164+
`app/streamlit_app.py` serve as the entry points.
165+
113166
## Visualization
114167

115168
```python

app/streamlit_app.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
import os
1718
import sys
1819
from pathlib import Path
1920

@@ -29,6 +30,12 @@
2930

3031
import qqa # noqa: E402
3132

33+
# The custom-problem editor runs user-supplied Python via ``exec``. Disable
34+
# it on public deployments by setting ``QQA_ALLOW_CUSTOM=0`` (this is the
35+
# default on Streamlit Community Cloud / Hugging Face Spaces). Set it to
36+
# ``1`` to re-enable on a trusted machine.
37+
ALLOW_CUSTOM = os.getenv("QQA_ALLOW_CUSTOM", "0") == "1"
38+
3239
st.set_page_config(
3340
page_title="QQA dashboard",
3441
page_icon="⚛️",
@@ -54,11 +61,18 @@
5461
with st.sidebar:
5562
st.header("1 · Problem definition")
5663

57-
use_custom = st.toggle(
58-
"Use custom problem",
59-
value=False,
60-
help="Plug in your own loss_fn directly from this UI.",
61-
)
64+
if ALLOW_CUSTOM:
65+
use_custom = st.toggle(
66+
"Use custom problem",
67+
value=False,
68+
help="Plug in your own loss_fn directly from this UI.",
69+
)
70+
else:
71+
use_custom = False
72+
st.caption(
73+
"Custom-loss editor is disabled on this deployment. "
74+
"Set `QQA_ALLOW_CUSTOM=1` to enable it on a trusted machine."
75+
)
6276

6377
extra: dict = {}
6478
if use_custom:

deploy/xserver-htaccess.example

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# --------------------------------------------------------------------------
2+
# Xserver (shared rental) redirect for the QQA Streamlit dashboard
3+
# --------------------------------------------------------------------------
4+
#
5+
# Xserver の共用レンタルサーバーでは Streamlit プロセスを常駐できないため、
6+
# 計算部分は Streamlit Community Cloud / Hugging Face Spaces に置き、
7+
# Xserver のドメインはユーザーを外部ホスティングにリダイレクトする役割だけ
8+
# を担います。
9+
#
10+
# 使い方:
11+
#
12+
# 1) share.streamlit.io (または huggingface.co/spaces) に
13+
# app/streamlit_app.py をデプロイする。
14+
# 2) 発行された URL を下の TARGET に差し替える。
15+
# 3) このファイルを `.htaccess` にリネームし、Xserver の対象サブドメイン
16+
# の `public_html/` 直下に FTP またはファイルマネージャでアップロード。
17+
#
18+
# 301 リダイレクト方式 (アドレスバーに Streamlit 側の URL が表示される)
19+
# --------------------------------------------------------------------------
20+
21+
RewriteEngine On
22+
# TARGET: replace with your deployed URL, for example:
23+
# https://qqa4co.streamlit.app
24+
# https://huggingface.co/spaces/<you>/qqa4co
25+
RewriteRule ^(.*)$ https://qqa4co.streamlit.app/$1 [R=301,L]
26+
27+
28+
# --------------------------------------------------------------------------
29+
# iframe 方式を使う場合 (アドレスバーに Xserver 側ドメインが残る)
30+
# --------------------------------------------------------------------------
31+
# 上記 RewriteRule をコメントアウトし、同じ public_html/ に以下の
32+
# index.html を置く:
33+
#
34+
# <!doctype html>
35+
# <html lang="ja">
36+
# <head>
37+
# <meta charset="utf-8">
38+
# <title>QQA dashboard</title>
39+
# <style>html,body,iframe{margin:0;height:100%;width:100%;border:0}</style>
40+
# </head>
41+
# <body>
42+
# <iframe src="https://qqa4co.streamlit.app"
43+
# allowfullscreen
44+
# allow="clipboard-read; clipboard-write"></iframe>
45+
# </body>
46+
# </html>
47+
#
48+
# 注: Streamlit Community Cloud は X-Frame-Options: SAMEORIGIN を
49+
# 返さないので iframe 埋め込みは通常問題なく動作しますが、公式保証は
50+
# されていません。301 リダイレクトの方が確実です。

requirements.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Streamlit Community Cloud / lightweight deployment dependency list.
2+
#
3+
# Notes
4+
# -----
5+
# * We pin the CPU wheel of PyTorch to avoid pulling the ~900 MB CUDA build
6+
# (which blows through the 1 GB Community Cloud image budget).
7+
# * The trailing `.` installs this repository itself as the ``qqa`` package
8+
# so ``import qqa`` works inside the Streamlit app.
9+
#
10+
# Local development should still use ``uv sync --all-extras``; this file is
11+
# only consumed by pip-based deploy targets (Streamlit Community Cloud,
12+
# Hugging Face Spaces, Render, etc.).
13+
14+
--extra-index-url https://download.pytorch.org/whl/cpu
15+
torch==2.4.1+cpu
16+
17+
numpy>=1.24
18+
networkx>=3.1
19+
scipy>=1.11
20+
matplotlib>=3.8
21+
tqdm>=4.66
22+
23+
# Interactive plots + GUI
24+
plotly>=5.17
25+
pandas>=2.0
26+
streamlit>=1.30
27+
28+
# Install this repository (reads pyproject.toml)
29+
.

tests/test_gui_apptest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414

1515
from __future__ import annotations
1616

17+
import os
1718
from pathlib import Path
1819

1920
import pytest
2021

22+
# The Home page hides the custom-problem toggle unless this env var is set.
23+
os.environ.setdefault("QQA_ALLOW_CUSTOM", "1")
24+
2125
pytest.importorskip("streamlit", minversion="1.29.0")
2226

2327
from streamlit.testing.v1 import AppTest # noqa: E402

0 commit comments

Comments
 (0)