Deploy web app to satsprice.app/app/ and link it from the website
Deploy website to GitHub Pages / deploy (push) Canceled after 0s
Deploy website to GitHub Pages / deploy (push) Canceled after 0s
The GitHub Pages workflow now builds the Compose wasmJs web app and publishes it alongside the marketing site, so it's reachable at /app/. Add nav/hero/download links to it and list Web among the supported platforms. Add website/serve-local.sh to reproduce the production layout locally, and document the setup in README/AGENTS. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,14 @@ on:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- "website/**"
|
||||
- "shared/**"
|
||||
- "webApp/**"
|
||||
- "gradle/**"
|
||||
- "gradlew"
|
||||
- "gradlew.bat"
|
||||
- "build.gradle.kts"
|
||||
- "settings.gradle.kts"
|
||||
- "gradle.properties"
|
||||
- ".github/workflows/pages.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -26,12 +34,26 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "21"
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
- name: Build web app
|
||||
run: ./gradlew :webApp:wasmJsBrowserDistribution
|
||||
- name: Assemble site
|
||||
run: |
|
||||
mkdir -p _site/app
|
||||
cp -r website/. _site/
|
||||
cp -r webApp/build/dist/wasmJs/productionExecutable/. _site/app/
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: "./website"
|
||||
path: "./_site"
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
@@ -5,6 +5,7 @@ xcodebuild*.log
|
||||
|
||||
.gradle/
|
||||
.idea/
|
||||
/website/app/
|
||||
.*.swp
|
||||
.*.swo
|
||||
.DS_Store
|
||||
|
||||
@@ -8,11 +8,14 @@ real trial-and-error to get right.
|
||||
## What this is
|
||||
|
||||
SatsPrice is a Kotlin Multiplatform app, currently released on iOS, macOS,
|
||||
and Android (see README's Supported Platforms/Download and Install). Web and
|
||||
Desktop/JVM are real future release targets too — `desktopApp` already has
|
||||
full native packaging configured (DMG/MSI/DEB, see its `build.gradle.kts`) —
|
||||
but neither has a release/CI pipeline set up yet, so treat them as
|
||||
not-yet-shipped rather than dev-only. The app converts between BTC, Sats,
|
||||
and Android (see README's Supported Platforms/Download and Install).
|
||||
Desktop/JVM is a real future release target — `desktopApp` already has full
|
||||
native packaging configured (DMG/MSI/DEB, see its `build.gradle.kts`) — but
|
||||
has no release/CI pipeline set up yet, so treat it as not-yet-shipped rather
|
||||
than dev-only. Web is a step ahead of Desktop: `.github/workflows/pages.yml`
|
||||
builds `:webApp:wasmJsBrowserDistribution` and publishes it alongside the
|
||||
marketing site to `satsprice.app/app/` on every push to `main` — see
|
||||
"Website and web app deployment" below. The app converts between BTC, Sats,
|
||||
and fiat currencies using live exchange rates (Coinbase, CoinGecko, or a
|
||||
manually typed-in rate).
|
||||
|
||||
@@ -149,6 +152,27 @@ fallback instead (`data/db/LocalStorageStores.kt`), which does survive page
|
||||
reloads, just scoped to the browser profile/origin (cleared by clearing
|
||||
site data, not shared across browsers/devices).
|
||||
|
||||
## Website and web app deployment
|
||||
|
||||
`website/` is a static marketing site (plain HTML/CSS/JS, no build step of
|
||||
its own) deployed to `satsprice.app` via GitHub Pages
|
||||
(`.github/workflows/pages.yml`). That workflow does more than upload
|
||||
`website/` as-is: it also runs `./gradlew :webApp:wasmJsBrowserDistribution`
|
||||
and copies the result into `website/app/` before publishing, so the live
|
||||
Compose web app is reachable at `satsprice.app/app/` and linked from the
|
||||
site (nav, hero, download section) via `/app/`.
|
||||
|
||||
- `website/app/` is git-ignored — it's build output, generated fresh by CI
|
||||
(and locally by the script below), never committed.
|
||||
- To reproduce the production layout locally (site + web app together,
|
||||
`/app/` links working): `./website/serve-local.sh [port]`. It builds the
|
||||
wasmJs distribution, copies it into `website/app/`, and serves
|
||||
`website/` with `python3 -m http.server`.
|
||||
- If you change the Pages workflow, remember `paths:` in the trigger
|
||||
includes `webApp/**`/`shared/**`/Gradle files, not just `website/**` —
|
||||
a shared-code change that affects the web app should also redeploy the
|
||||
site.
|
||||
|
||||
## Testing and verification
|
||||
|
||||
- `shared/src/commonTest` holds the real unit test suite (pure Kotlin,
|
||||
|
||||
@@ -27,7 +27,7 @@ height="70">](https://github.com/tyiu/sats-price/releases)
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
iOS 16.0+ • macOS 13.0+ • Android 7.0+
|
||||
iOS 16.0+ • macOS 13.0+ • Android 7.0+ • [Web](https://satsprice.app/app/) (any modern browser)
|
||||
|
||||
## Screenshots
|
||||
|
||||
@@ -75,6 +75,9 @@ options:
|
||||
- Wasm target (faster, modern browsers): `./gradlew :webApp:wasmJsBrowserDevelopmentRun`
|
||||
- JS target (slower, supports older browsers): `./gradlew :webApp:jsBrowserDevelopmentRun`
|
||||
- iOS app: open the [/iosApp](./iosApp) directory in Xcode and run it from there.
|
||||
- [Website](./website) (with the web app built and served at `/app/`, matching production):
|
||||
`./website/serve-local.sh` (serves at http://localhost:8000 by default; pass a port number to
|
||||
override)
|
||||
|
||||
### Running tests
|
||||
|
||||
|
||||
+20
-2
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>SatsPrice — Bitcoin Price & Sats Converter</title>
|
||||
<meta name="description" content="SatsPrice converts Bitcoin, satoshis, and fiat currency in real time, sourced from Coinbase and CoinGecko. Free and open source for Android, iOS, and macOS." />
|
||||
<meta name="description" content="SatsPrice converts Bitcoin, satoshis, and fiat currency in real time, sourced from Coinbase and CoinGecko. Free and open source for Android, iOS, macOS, and Web." />
|
||||
<link rel="icon" href="assets/app-icon.png" type="image/png" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
@@ -22,6 +22,7 @@
|
||||
<a href="#features">Features</a>
|
||||
<a href="#platforms">Screenshots</a>
|
||||
<a href="#download">Download</a>
|
||||
<a href="/app/" target="_blank" rel="noopener">Web App</a>
|
||||
<a href="https://github.com/tyiu/sats-price" target="_blank" rel="noopener">Code</a>
|
||||
</nav>
|
||||
|
||||
@@ -37,6 +38,7 @@
|
||||
<a href="#features">Features</a>
|
||||
<a href="#platforms">Screenshots</a>
|
||||
<a href="#download">Download</a>
|
||||
<a href="/app/" target="_blank" rel="noopener">Web App</a>
|
||||
<a href="https://github.com/tyiu/sats-price" target="_blank" rel="noopener">GitHub</a>
|
||||
</div>
|
||||
</header>
|
||||
@@ -60,6 +62,11 @@
|
||||
<a href="#platforms" class="btn btn-ghost">See screenshots</a>
|
||||
</div>
|
||||
|
||||
<p class="hero-webapp">
|
||||
Don't want to install anything?
|
||||
<a href="/app/" target="_blank" rel="noopener">Try it in your browser →</a>
|
||||
</p>
|
||||
|
||||
<div class="platform-pills">
|
||||
<span class="pill">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.05 12.536c-.03-3.06 2.5-4.53 2.61-4.6-1.42-2.08-3.63-2.37-4.42-2.4-1.88-.19-3.68 1.11-4.63 1.11-.96 0-2.42-1.09-3.98-1.06-2.05.03-3.94 1.19-5 3.02-2.13 3.7-.55 9.18 1.53 12.18 1.02 1.47 2.23 3.11 3.82 3.05 1.53-.06 2.11-.99 3.96-.99 1.84 0 2.37.99 3.98.96 1.65-.03 2.69-1.5 3.7-2.98 1.17-1.71 1.65-3.37 1.67-3.45-.04-.02-3.2-1.23-3.24-4.84zM14.15 3.6c.84-1.02 1.41-2.43 1.25-3.6-1.22.06-2.69.84-3.55 1.85-.78.9-1.46 2.34-1.28 3.57 1.2.09 2.75-.61 3.58-1.82z"/></svg>
|
||||
@@ -73,6 +80,10 @@
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.6 9.48l1.84-3.18c.16-.31.04-.69-.26-.85-.29-.15-.65-.06-.83.22l-1.88 3.24a11.43 11.43 0 0 0-8.94 0L5.65 5.67c-.18-.28-.54-.37-.83-.22-.3.16-.42.54-.26.85L6.4 9.48C3.3 11.25 1.28 14.44 1 18h22c-.28-3.56-2.3-6.75-5.4-8.52zM7 15.25a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5zm10 0a1.25 1.25 0 1 1 0-2.5 1.25 1.25 0 0 1 0 2.5z"/></svg>
|
||||
Android
|
||||
</span>
|
||||
<span class="pill">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
|
||||
Web
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="trust-row">
|
||||
@@ -162,7 +173,7 @@
|
||||
<div class="feature-card wide">
|
||||
<div class="icon">💻</div>
|
||||
<h3>Native on every platform</h3>
|
||||
<p>SwiftUI on iOS and macOS, Compose Multiplatform on Android — built with Kotlin Multiplatform to feel right at home on each device, not like a port.</p>
|
||||
<p>SwiftUI on iOS and macOS, Compose Multiplatform on Android and Web — built with Kotlin Multiplatform to feel right at home on each device, not like a port.</p>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
@@ -279,10 +290,17 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="webapp-divider"><span>or</span></div>
|
||||
|
||||
<div class="webapp-cta">
|
||||
<a href="/app/" class="btn btn-ghost" target="_blank" rel="noopener">Open the web app — no install required</a>
|
||||
</div>
|
||||
|
||||
<div class="version-row">
|
||||
<span class="pill">🍎 iOS 16.0+</span>
|
||||
<span class="pill">🖥️ macOS 13.0+</span>
|
||||
<span class="pill">🤖 Android 7.0+</span>
|
||||
<span class="pill">🌐 Web — any modern browser</span>
|
||||
</div>
|
||||
|
||||
<p class="oss-note">
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Builds the web app, drops it into website/app/, and serves the whole
|
||||
# website locally so the /app/ links behave like they do in production.
|
||||
set -euo pipefail
|
||||
|
||||
PORT="${1:-8000}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "Building web app (wasmJs)..."
|
||||
"$REPO_ROOT/gradlew" -p "$REPO_ROOT" :webApp:wasmJsBrowserDistribution
|
||||
|
||||
echo "Copying web app into website/app/..."
|
||||
mkdir -p "$SCRIPT_DIR/app"
|
||||
cp -r "$REPO_ROOT/webApp/build/dist/wasmJs/productionExecutable/." "$SCRIPT_DIR/app/"
|
||||
|
||||
echo "Serving website at http://localhost:$PORT/ (web app at http://localhost:$PORT/app/)"
|
||||
cd "$SCRIPT_DIR" && python3 -m http.server "$PORT"
|
||||
@@ -268,6 +268,20 @@ h1, h2, h3, h4 {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.hero-webapp {
|
||||
margin-top: 18px;
|
||||
font-size: 14px;
|
||||
color: var(--text-faint);
|
||||
}
|
||||
|
||||
.hero-webapp a {
|
||||
color: var(--gold);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.hero-webapp a:hover { text-decoration: underline; }
|
||||
|
||||
.platform-pills {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -652,6 +666,26 @@ h1, h2, h3, h4 {
|
||||
.badge-link.obtainium img,
|
||||
.badge-link.github img { height: 56px; }
|
||||
|
||||
.webapp-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 14px;
|
||||
margin-top: 30px;
|
||||
color: var(--text-faint);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.webapp-divider::before,
|
||||
.webapp-divider::after {
|
||||
content: "";
|
||||
height: 1px;
|
||||
width: 80px;
|
||||
background: var(--border);
|
||||
}
|
||||
|
||||
.webapp-cta { margin-top: 18px; }
|
||||
|
||||
.version-row {
|
||||
margin-top: 38px;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user