{e(d['title']).replace(chr(10),'
')}
{e(d['body'])}
{e(d['detail'])}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5624149..55fc523 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+# 0.1.0 release restored — 2026-09-25
+
+- Rebuilt and signed the APK locally with explicitly supplied runtime authentication assets.
+- Restored release downloads; no app behavior or version-code change from 0.1.0.
+- Accessory identity remains in the APK only. No credential files enter Git or the source archive.
+- Retained generated test identities and public-source credential checks.
+- Source/CI builds omit runtime identity assets by default; local packaging requires an explicit external directory.
+
# Source reset — 2026-09-25
- Withdrew the 0.1.0 APK and removed its release tag.
@@ -7,4 +15,4 @@
- Added a build guard rejecting credential asset files.
- Replaced the download site with a five-language suspension notice.
-No replacement APK has been released. Existing copies cannot be recalled by a Git history reset.
+The APK was subsequently rebuilt and restored as described above. Existing copies cannot be recalled by a Git history reset.
diff --git a/README.md b/README.md
index 02be52c..64a10c3 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,43 @@
# DiPlay
-Independent CarPlay receiver research for Android head units, based on xcertplay with a DiAuto-style interface.
+**CarPlay for compatible Android head units.** Wired and wireless, with the familiar DiAuto interface. Independent app: `com.shihab.diplay`.
-## Downloads suspended
+[Download & website](https://shihabal3amri.github.io/DiPlay/) · [Release](https://github.com/shihabal3amri/DiPlay/releases/tag/v0.1.0) · [Report a problem](https://github.com/shihabal3amri/DiPlay/issues/new/choose)
-The 0.1.0 APK was withdrawn because it bundled a recovered third-party accessory identity. Do not redistribute that APK or extract its identity for new builds. No replacement APK is available.
+
-Public branch history has been reset to this reviewed source snapshot. The previous release and tag are removed; restricted local incident records are retained. Rewriting history does not recall downloaded copies or invalidate an exposed credential.
+## 0.1.0 — public preview
-This source snapshot contains no accessory private-key files. Synthetic test identities are generated at test runtime. Automatic private-asset packaging has been removed and the build rejects credential asset files. A source-only build does not provide working standalone CarPlay without an authorized authentication design.
+Install on the **car**, not the iPhone. No jailbreak, dongle, Mac, account or authentication server is required for use. ADB is not needed during everyday use; your head unit must permit APK installation. Wireless requires Android 10+ and working Wi-Fi Direct; the APK supports Android 9+ for wired use.
-[Project status](https://shihabal3amri.github.io/DiPlay/) · [Build instructions](docs/BUILD.md) · [Security](SECURITY.md) · [Privacy](docs/PRIVACY.md)
+- Wired USB and wireless CarPlay with local authentication.
+- Automatic address discovery, fixed-channel Wi-Fi fallbacks and successful-configuration memory.
+- Icon/text size, resolution and frame rate; applying a display change reconnects CarPlay.
+- Local diagnostic export. Reports are sent only if you choose to share them.
+- Separate installation alongside DiAuto. Run one projection app at a time.
-## Credits
+This is **not an Apple-certified product**. The APK bundles an experimental accessory identity recovered from public Carlinkit firmware, not a newly provisioned MFi identity for DiPlay. A bundled private key is extractable. Acceptance after future iOS updates, reliability across head units and suitability of that identity for general distribution are unresolved. This release invites community testing; it is not a guarantee of universal compatibility.
-Based on [xcertplay](https://github.com/shilapi/xcertplay), GPL-3.0. Home/settings UI and website adapt [DiAuto](https://github.com/shihabal3amri/DiAuto), AGPL-3.0. License texts and attribution remain in this repository. CarPlay and its icon belong to Apple Inc. No affiliation with Apple or BYD is implied.
+Prior private builds have completed physical wired/wireless picture, touch and audio tests. Some testers still report stuttering or icon-size changes that do not take effect. The 0.1.0 changes passed automated and emulator checks; a new physical-car session was not available at publication. Start with H.264 / 30 fps and Default icon size. See the compatibility notes before testing.
+
+## Documentation
+
+- [Install and connect](docs/INSTALL.md)
+- [Compatibility and troubleshooting](docs/COMPATIBILITY.md)
+- [Privacy and diagnostic reports](docs/PRIVACY.md)
+- [Build from source](docs/BUILD.md)
+- [Validation](docs/VALIDATION.md)
+- [Release notes](CHANGELOG.md)
+- [Credits and licenses](docs/THIRD_PARTY_NOTICES.md)
+
+The website is available in English, Arabic, Russian, Spanish and Simplified Chinese. The current app interface is English.
+
+## Source and credits
+
+Based on [xcertplay](https://github.com/shilapi/xcertplay), GPL-3.0. The home/settings UI and website adapt [DiAuto](https://github.com/shihabal3amri/DiAuto), AGPL-3.0; that license is included in `docs/licenses`. Preserve those notices when distributing modifications. CarPlay and its icon belong to Apple Inc.; no Apple or BYD affiliation or endorsement is implied.
+
+This repository starts with a clean public source snapshot. Local research, tester reports and release-signing secrets are excluded. The complete source corresponding to the APK is provided with every release; experimental runtime identity assets are described separately in the build instructions and notices.
+
+## Local release packaging
+
+The release APK intentionally contains the experimental accessory identity. The Git repository and source archive exclude all accessory and Android signing keys; tests generate synthetic identities at runtime. Source/CI builds omit runtime identity assets by default. Local release builds explicitly select an external asset directory. Publishing the APK makes its bundled identity extractable; building locally does not preserve that identity's confidentiality.
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 7d177ba..8bba89f 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,7 +1,9 @@
# DiPlay
-APK 下载已暂停。0.1.0 版本包含提取自第三方固件的配件身份,现已撤下。请勿继续分发该 APK 或提取其中的身份用于新构建。目前没有替代 APK。
+为兼容安卓车机提供有线及无线 CarPlay,采用 DiAuto 风格界面。
-公开分支已重置为经过审查的源代码快照。删除历史记录不会撤回已下载的副本,也不会使已泄露的凭据失效。测试密钥现在在测试运行时生成,不再存储于仓库。
+[下载与中文网站](https://shihabal3amri.github.io/DiPlay/zh-Hans/) · [完整说明](README.md) · [报告问题](https://github.com/shihabal3amri/DiPlay/issues/new/choose)
-[项目状态](https://shihabal3amri.github.io/DiPlay/zh-Hans/) · [完整说明](README.md)
+0.1.0 为公开预览版,未经 Apple 认证。请安装在车机上,而非 iPhone。无需越狱、转接盒或认证服务器。无线连接需要 Android 10 或更高版本及可用的 Wi-Fi Direct。
+
+认证使用从公开固件中提取的实验性配件身份,无法保证未来持续可用。部分车机仍可能卡顿或无法应用图标大小设置。应用界面目前为英文。源代码、构建说明及许可证随版本提供。
diff --git a/SECURITY.md b/SECURITY.md
index 396ff2f..62a3571 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,15 +1,9 @@
-# Distribution suspended
+# Credentials and release packaging
-The 0.1.0 APK was withdrawn after identifying exposure of a recovered third-party accessory private key bundled in the APK. Do not redistribute the APK or reuse that identity in new packages.
+Public release distribution has resumed at the maintainer's request. The APK intentionally bundles the experimental accessory certificate and matching key described in docs/THIRD_PARTY_NOTICES.md. Anyone with the APK can extract them. Local compilation, Git history removal and obfuscation do not make a bundled shared key confidential or revoke previous copies.
-The public branch has been reset and the old release/tag removed. Restricted local release records and the original repository bundle are preserved for investigation. These steps reduce exposure through project-controlled links; they do not recall existing copies or revoke the credential.
+The public Git tree and corresponding source archive exclude accessory keys and Android release-signing secrets. CI checks reject credential containers and private-key blocks in tracked files. Synthetic test identities are generated at runtime. Source builds have no automatic private-asset import; release packaging requires an explicit local directory and permits only the two expected runtime files.
-A review of the original published Git objects found no copy of the exposed key in binary or common text encodings, including the private scalar. The original Git tree did contain a different synthetic test key; that file has also been removed. Tests now generate self-signed identities at runtime.
+The Android APK-signing key is separate, stays local and is never bundled in the APK. Current acceptance of the experimental accessory identity does not establish Apple certification or guarantee future compatibility.
-The Android APK-signing key is separate. No evidence of its publication was found in the audited source or release contents. Changing that signing key would not remediate the accessory-key exposure.
-
-Do not include credentials, pairing records or personal information in public issues. Use GitHub private vulnerability reporting for sensitive findings. Credential revocation or replacement must be coordinated with the verified credential owner/provider; this project cannot declare those actions completed.
-
-A future release requires authorized authentication provisioning. Obfuscating an already exposed shared key, encrypting it with a key shipped in the app, or rewriting Git history does not restore confidentiality.
-
-GitHub guidance: https://docs.github.com/en/code-security/tutorials/remediate-leaked-secrets/remediating-a-leaked-secret
+Review diagnostic reports before posting. Never include credentials or pairing records in public issues. Use GitHub private vulnerability reporting for sensitive findings.
diff --git a/docs/BUILD.md b/docs/BUILD.md
index 9971a25..f210bba 100644
--- a/docs/BUILD.md
+++ b/docs/BUILD.md
@@ -1,17 +1,25 @@
-# Source-only builds
-
-Public APK distribution is suspended while accessory authentication is reviewed.
-The recovered identity must not be extracted from old releases, imported or bundled again.
-Local compilation does not make a distributed private key confidential.
+# Building DiPlay
Requirements: JDK 25, Android SDK 37, NDK 28.2.13676358 and the included Gradle wrapper.
+## Source and CI builds
+
```sh
./gradlew :shared:testDebugUnitTest :common:testDebugUnitTest :mobile:lintDebug :mobile:assembleDebug
```
-This produces a development APK without accessory identity assets. The current product bootstrap requires authentication provisioning, so this build does not provide a working standalone CarPlay connection. It is for source validation only.
+The resulting source-only APK contains no accessory identity. Standalone CarPlay requires runtime authentication provisioning. Tests generate synthetic identities at runtime; no test private-key files are tracked.
-The automatic `.private/assets` import has been removed. The mobile pre-build check rejects credential files in APK asset source directories. The retired `scripts/build-beta.py` exits without building. Tests generate fresh self-signed synthetic identities at runtime; no static private key is stored in this repository.
+## Local release packaging
-A future distributable build needs an authorized authentication/provisioning design. The separate Android release-signing key remains local and must never be committed. See SECURITY.md.
+Provide an external asset directory using `DIPLAY_AUTH_ASSETS_DIR`. The directory must contain exactly the intended runtime files under `offline-mfi/identity.pk8` and `offline-mfi/certificate.p7b`. Neither file belongs in Git. The build permits those two files only when this explicit input is set and rejects unexpected credential containers elsewhere in APK assets.
+
+Set `ANDROID_KEYSTORE_PATH`, `ANDROID_KEYSTORE_PASSWORD`, `ANDROID_KEY_ALIAS`, and `ANDROID_KEY_PASSWORD` locally for your Android signing key. Never commit these values or the keystore. Different signing keys cannot update an existing project-signed installation.
+
+```sh
+./gradlew :shared:testDebugUnitTest :common:testDebugUnitTest :mobile:lintRelease :mobile:assembleRelease
+```
+
+Output: `mobile/build/outputs/apk/release/mobile-release.apk`. The release APK deliberately contains the experimental identity described in the notices; it is extractable by recipients. The separate Android signing key is not included. The retired build-beta.py helper is not used; this Gradle workflow uses explicit environment inputs.
+
+The public release source archive corresponds to the tagged source and excludes runtime identities, signing keys, local configuration and build output.
diff --git a/docs/COMPATIBILITY.md b/docs/COMPATIBILITY.md
index 309b801..799eb9b 100644
--- a/docs/COMPATIBILITY.md
+++ b/docs/COMPATIBILITY.md
@@ -1,3 +1,26 @@
-# Distribution suspended
+# Compatibility
-The 0.1.0 APK has been withdrawn. Do not install or redistribute it. No replacement APK is available. See [SECURITY.md](../SECURITY.md) and [source-only build instructions](BUILD.md).
+This public preview is an independent receiver, not an Apple-certified CarPlay accessory. The experimental bundled accessory identity is extractable and its future acceptance is not guaranteed.
+
+| Area | Current scope |
+| --- | --- |
+| Head unit | Android 9+ APK; wireless Wi-Fi Direct path needs Android 10+ |
+| Phone | Standard, non-jailbroken iPhone with CarPlay enabled; device/iOS compatibility varies |
+| Physical evidence | Previous private builds: wired and wireless picture, touch and audio confirmed on the development car with iPhone XS / iOS 18.7.10 |
+| Other cars | Mixed community reports across DiLink generations; not a certified model support list |
+| Current release | Automated and emulator checks, not a fresh physical-car validation of every change |
+| Wi-Fi | Prefer 5 GHz without an established station connection; align to a supported existing station channel; explicit 2.4 GHz fallback for firmware that rejects 5 GHz or automatic channel selection |
+| Video | Default H.264 / 30 fps; 60 fps and HEVC increase device-specific demands |
+
+## Known limitations
+
+- Some units stutter, particularly under higher video load. A 2.4 GHz link alone does not prove the cause: interference, firmware and decoder stalls can all contribute. Try Default icons, 30 fps and a lower resolution, then attach a report.
+- Some iOS/head-unit combinations do not visibly apply icon and text size. Reconnection is implemented; that does not guarantee the iPhone chooses the requested layout.
+- A radio that supports joining a 5 GHz network may still reject a 5 GHz Wi-Fi Direct group. The capability flag is diagnostic, not proof of group-owner support.
+- Automatic startup depends on the car's firmware and startup permissions.
+- USB requires a data port and correct host/device-role behavior.
+- Calls, Siri, background reconnection, long journeys and future iOS releases need broader testing.
+
+Reports record requested and actual frequencies, station association state, fallback failures and remembered-configuration events. Wi-Fi credentials and protocol payloads are excluded. A successful hotspot is not itself a successful CarPlay session.
+
+Android references: [SupplicantState](https://developer.android.com/reference/android/net/wifi/SupplicantState), [explicit P2P operating frequency](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pConfig.Builder#setGroupOperatingFrequency(int)).
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 309b801..a876b16 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -1,3 +1,36 @@
-# Distribution suspended
+# Install and connect
-The 0.1.0 APK has been withdrawn. Do not install or redistribute it. No replacement APK is available. See [SECURITY.md](../SECURITY.md) and [source-only build instructions](BUILD.md).
+1. Park the car. Download `DiPlay-0.1.0.apk` from the official GitHub release linked on the website.
+2. Install on the Android head unit using its supported APK installation method. Do not install on the iPhone. Update over an existing DiPlay beta to retain settings and pairing records; the signing key is unchanged.
+3. Open DiPlay. Grant the permissions requested for the features you use: Bluetooth/Nearby devices, Wi-Fi/Location on older Android, and microphone for Siri/calls. Allow notifications for connection controls.
+4. Close other phone-projection apps before connecting.
+
+## Wireless
+
+Android 10+ and functioning Wi-Fi Direct are required. Pair your iPhone through the car's Bluetooth settings, keep Bluetooth and Wi-Fi enabled, then choose **Connect phone** in DiPlay. Select your paired iPhone and allow CarPlay on the phone if prompted. **Choose iPhone** changes the selected paired device. No manual MAC address entry or ADB setup is needed.
+
+Your car's normal internet connection can remain enabled. DiPlay aligns channels only to a completed Wi-Fi association; otherwise it prefers 5 GHz, with fixed 2.4 GHz channels as fallback. Firmware makes the final radio decision. Do not change the car's country code or driver properties.
+
+## USB
+
+Connect the iPhone to a USB **data** port with a data-capable cable and choose **Connect with USB**. Approve USB access, Trust/CarPlay and the local VPN permission if requested. The local VPN carries the USB network link; it is not an internet VPN service. Charge-only ports/cables cannot work.
+
+## Settings
+
+Swipe down with three fingers in CarPlay to open DiPlay settings, or return to the home screen. Icon/text size, resolution and frame rate use **Apply and reconnect** during an active session. A selection alone does not apply; Cancel preserves the old setting. When disconnected, **Save** applies to the next connection. Other settings also apply on the next connection.
+
+Start with 30 fps, Efficient video (HEVC) off and Default icon/text size. Try 80% or 60% resolution for a slower head unit. Some iPhone/head-unit combinations still ignore icon/text scaling.
+
+## Connection recovery and reports
+
+If reinstalling left an old group, close other projection apps, then use **Settings → Wireless connection help → Reset CarPlay Wi-Fi**. DiPlay asks before removing an unrecognized Wi-Fi Direct group. Updating in place is preferable to uninstalling.
+
+Use **Settings → Save diagnostic report** after reproducing a problem. Android 10+ saves to **Downloads/DiPlay**; Android 9 uses a document picker. Review the file, then attach it to a GitHub issue with car model, DiLink/Android versions, iPhone/iOS, transport and reproduction steps. Nothing is uploaded automatically.
+
+APK installation restrictions are controlled by your car's firmware. ADB is optional if your car supports it, not an app runtime requirement:
+
+```sh
+adb install -r DiPlay-0.1.0.apk
+```
+
+Only use a trusted computer. A different signing certificate cannot update this build; do not uninstall until you have saved any reports you need.
diff --git a/docs/TESTING.md b/docs/TESTING.md
index 309b801..9753ab7 100644
--- a/docs/TESTING.md
+++ b/docs/TESTING.md
@@ -1,3 +1,7 @@
-# Distribution suspended
+# Test checklist
-The 0.1.0 APK has been withdrawn. Do not install or redistribute it. No replacement APK is available. See [SECURITY.md](../SECURITY.md) and [source-only build instructions](BUILD.md).
+Use the [installation guide](INSTALL.md). With the car parked, verify wired and wireless connection, picture, touch and music. Test disconnect/reconnect, then settings Apply/Cancel. Save a diagnostic report after reproducing an issue.
+
+For channel memory, connect until authenticated CarPlay renders, disconnect and reconnect without changing the car's Wi-Fi association. Look for `remembered saved` followed by `remembered first`. Report absent events; creating a hotspot alone is insufficient.
+
+Include head-unit model, DiLink/Android, iPhone/iOS, wired/wireless, app version and exact steps. Do not post credentials or unreviewed personal information. See [compatibility](COMPATIBILITY.md) for remaining limitations.
diff --git a/docs/THIRD_PARTY_NOTICES.md b/docs/THIRD_PARTY_NOTICES.md
index 6e9f1a5..89f1393 100644
--- a/docs/THIRD_PARTY_NOTICES.md
+++ b/docs/THIRD_PARTY_NOTICES.md
@@ -30,7 +30,7 @@ Gradle dependency declarations and version catalog accompany the source. License
## Experimental authentication data
-The withdrawn 0.1.0 preview APK included an accessory certificate/key pair recovered from public Carlinkit C2Air Allwinner V821 firmware during the owner's local investigation. These data are not newly generated Apple-issued credentials for DiPlay and are not relicensed as project source code. That distribution has been suspended. The credential must not be redistributed in new builds; the current source snapshot contains no accessory identity files. The source archive does not contain the private key, and the separate Android APK-signing key is never distributed.
+The public preview APK includes an accessory certificate/key pair recovered from public Carlinkit C2Air Allwinner V821 firmware during the owner's local investigation. These data are not newly generated Apple-issued credentials for DiPlay and are not relicensed as project source code. They are bundled in the preview APK to reproduce the offline experiment; continued acceptance and suitability for general distribution are unresolved. The source archive does not contain the private key, and the separate Android APK-signing key is never distributed.
## Download website
diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md
index fd56421..316f62f 100644
--- a/docs/VALIDATION.md
+++ b/docs/VALIDATION.md
@@ -1,10 +1,10 @@
-# Source snapshot validation — 2026-09-25
+# Restored 0.1.0 release — 2026-09-25
-- 172 JVM/Robolectric tests passed with freshly generated synthetic test identities.
-- Source-only debug APK build and debug lint passed.
-- The credential-asset guard rejected a synthetic `.pk8` probe and passed after it was removed.
-- APK inspection found no `offline-mfi` assets or credential-container files.
-- Static test private-key/certificate files have been removed from the source snapshot.
-- No new public APK or CarPlay compatibility claim is made. This development build lacks accessory authentication provisioning.
-
-The original release and incident records are preserved locally with restricted access. See SECURITY.md.
+- Built from the current public source with explicitly selected external authentication assets and the existing local Android signing key.
+- 172 JVM/Robolectric tests passed; zero failures/errors. Release lint and signed release build passed.
+- Public-tree credential scan passed. Source tests generate identities at runtime; no credential containers or private-key blocks are tracked.
+- Verified that the APK contains the intended runtime accessory identity and no Android signing keystore.
+- Signing certificate SHA-256: `87b38b12788dcb202a961215f2572e30ec2dc9d8ef4bc070d05f77e49291a363` (unchanged).
+- Package `com.shihab.diplay`, version `0.1.0`, version code `10`; restoration changes packaging and public documentation, not app behavior.
+- Existing USB-only TLS trust-manager warnings and unused-resource warning remain; this is not a completed security audit.
+- No fresh physical-car validation was performed for the restored artifact. Previous emulator and private-build testing do not establish universal compatibility.
diff --git a/mobile/build.gradle.kts b/mobile/build.gradle.kts
index d408d1c..ae2dcbf 100644
--- a/mobile/build.gradle.kts
+++ b/mobile/build.gradle.kts
@@ -3,6 +3,10 @@ plugins {
alias(libs.plugins.kotlin.compose)
}
+// Optional local-only input. CI and ordinary source builds contain no accessory identity.
+val localAuthenticationAssets = providers.environmentVariable("DIPLAY_AUTH_ASSETS_DIR")
+ .orNull?.let { file(it).canonicalFile }
+
android {
namespace = "com.shilapi.xcertplay"
compileSdk {
@@ -19,6 +23,8 @@ android {
}
+ localAuthenticationAssets?.let { sourceSets.getByName("main").assets.srcDir(it) }
+
signingConfigs {
create("release") {
storeFile = file(
@@ -63,7 +69,7 @@ dependencies {
debugImplementation(libs.androidx.compose.ui.tooling)
}
-// Source builds must never silently import a shared accessory private key.
+// No implicit import. Only the two explicitly selected local runtime assets are allowed.
val credentialAssets = files(android.sourceSets.flatMap { source ->
source.assets.directories.map { directory ->
fileTree(directory) {
@@ -74,14 +80,16 @@ val credentialAssets = files(android.sourceSets.flatMap { source ->
})
val rejectBundledCredentials by tasks.registering {
group = "verification"
- description = "Reject credential files in every APK asset source directory."
+ description = "Reject unexpected credential files in APK assets."
val filesToCheck = credentialAssets
+ val allowed = localAuthenticationAssets?.let { dir ->
+ listOf("identity.pk8", "certificate.p7b").map { dir.resolve("offline-mfi/$it").canonicalFile }.toSet()
+ } ?: emptySet()
inputs.files(filesToCheck)
doLast {
- check(filesToCheck.isEmpty) {
- "Credential assets are forbidden in distributable APKs: " +
- filesToCheck.files.joinToString { it.name }
- }
+ check(allowed.all { it.isFile }) { "Explicit local authentication assets are incomplete" }
+ val unexpected = filesToCheck.files.filter { it.canonicalFile !in allowed }
+ check(unexpected.isEmpty()) { "Unexpected credential files in APK assets" }
}
}
tasks.named("preBuild") { dependsOn(rejectBundledCredentials) }
diff --git a/scripts/build-beta.py b/scripts/build-beta.py
index 6109cb6..1ede7cd 100644
--- a/scripts/build-beta.py
+++ b/scripts/build-beta.py
@@ -1,6 +1,3 @@
#!/usr/bin/env python3
-"""The credential-bearing beta release path has been withdrawn."""
-raise SystemExit(
- "Release packaging is suspended. Do not bundle a recovered accessory identity. "
- "See docs/BUILD.md for source-only validation."
-)
+"""Legacy helper: releases now use explicit environment inputs."""
+raise SystemExit("Use the local release Gradle command and environment inputs documented in docs/BUILD.md.")
diff --git a/scripts/build_site.py b/scripts/build_site.py
index 523acaf..6541918 100644
--- a/scripts/build_site.py
+++ b/scripts/build_site.py
@@ -1,24 +1,36 @@
#!/usr/bin/env python3
-"""Build the public status pages. No APK download URL is published."""
+"""Generate the five static GitHub Pages editions; no runtime dependencies."""
from pathlib import Path
-from html import escape as e
import json
+from html import escape as e
ROOT = Path(__file__).resolve().parents[1]
SITE = ROOT / 'site'
+data = json.loads((SITE / 'content.json').read_text())
BASE = 'https://shihabal3amri.github.io/DiPlay/'
REPO = 'https://github.com/shihabal3amri/DiPlay'
-data = json.loads((SITE / 'content.json').read_text())
+RELEASE = REPO + '/releases/tag/v0.1.0'
+DOWNLOAD = REPO + '/releases/download/v0.1.0/DiPlay-0.1.0.apk'
for lang, d in data.items():
folder = SITE if lang == 'en' else SITE / lang
folder.mkdir(exist_ok=True)
prefix = './' if lang == 'en' else '../'
url = BASE + ('' if lang == 'en' else lang + '/')
nav = ''.join(f'{e(v["name"])}' for code,v in data.items())
+ alternates = ''.join(f'' for code in data)
+ pics = ''.join(f'
{e(d['body'])}
{e(d['detail'])}
{e(d['intro'])}
{e(d['promise'])}
{e(d['requires'])}
{e(d['bssid'])}
{e(d['adb'])} ↗{e(d['compatText'])}
{e(d['followText'])}
{e(d['updateText'])}