Skip to content

Commit 32521a2

Browse files
committed
Make landing make SKaiNET themed
1 parent 22e89e3 commit 32521a2

5 files changed

Lines changed: 2064 additions & 144 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 1 addition & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -69,150 +69,7 @@ jobs:
6969
- name: Prepare static site folder (scan apps & generate index)
7070
run: |
7171
set -e
72-
73-
SITE_DIR="site"
74-
mkdir -p "$SITE_DIR"
75-
76-
python << 'PYTHON_EOF'
77-
import json, os, shutil, html
78-
79-
ROOT = os.getcwd()
80-
SITE_DIR = os.path.join(ROOT, "site")
81-
os.makedirs(SITE_DIR, exist_ok=True)
82-
83-
release_tag = os.environ.get("GITHUB_REF_NAME", "")
84-
85-
apps = []
86-
87-
# Walk repo and look for webapp.json
88-
for dirpath, dirnames, filenames in os.walk(ROOT):
89-
if "webapp.json" not in filenames:
90-
continue
91-
92-
meta_path = os.path.join(dirpath, "webapp.json")
93-
with open(meta_path, "r", encoding="utf-8") as f:
94-
try:
95-
meta = json.load(f)
96-
except Exception as e:
97-
print(f"[WARN] Cannot parse {meta_path}: {e}")
98-
continue
99-
100-
app_id = meta.get("id")
101-
name = meta.get("name", app_id)
102-
description = meta.get("description", "")
103-
screenshot_rel = meta.get("screenshot")
104-
105-
# Only support multi dist directories; ignore legacy single distDir
106-
dist_dirs_rel = meta.get("distDirs", []) if isinstance(meta.get("distDirs"), list) else []
107-
108-
if not app_id:
109-
print(f"[WARN] {meta_path} missing 'id', skipping.")
110-
continue
111-
112-
# If no distDirs provided, just register app for index but skip copy
113-
if not dist_dirs_rel:
114-
print(f"[INFO] {meta_path} has no 'distDirs'; will only list app on index (no files copied).")
115-
116-
project_root = dirpath
117-
118-
# Helper: merge-copy contents of src into dst (overwrite on conflicts)
119-
def merge_copy(src: str, dst: str):
120-
if not os.path.exists(src):
121-
return
122-
os.makedirs(dst, exist_ok=True)
123-
for name in os.listdir(src):
124-
s = os.path.join(src, name)
125-
d = os.path.join(dst, name)
126-
if os.path.isdir(s):
127-
merge_copy(s, d)
128-
else:
129-
os.makedirs(os.path.dirname(d), exist_ok=True)
130-
try:
131-
shutil.copy2(s, d)
132-
except Exception as e:
133-
print(f"[WARN] Failed to copy {s} -> {d}: {e}")
134-
135-
# Copy contents of every configured distDir into site/<id>/ (no validation)
136-
target_app_dir = os.path.join(SITE_DIR, app_id)
137-
if os.path.exists(target_app_dir):
138-
shutil.rmtree(target_app_dir)
139-
os.makedirs(target_app_dir, exist_ok=True)
140-
141-
for rel in dist_dirs_rel:
142-
src_dir = os.path.join(project_root, rel)
143-
if not os.path.exists(src_dir):
144-
print(f"[INFO] distDir does not exist (skipped): {src_dir}")
145-
continue
146-
print(f"[OK] Merging distDir for {app_id}: {src_dir} -> {target_app_dir}")
147-
merge_copy(src_dir, target_app_dir)
148-
149-
screenshot_target = None
150-
if screenshot_rel:
151-
screenshot_src = os.path.join(project_root, screenshot_rel)
152-
if os.path.exists(screenshot_src):
153-
screenshot_name = os.path.basename(screenshot_src)
154-
screenshot_target = f"{app_id}/{screenshot_name}"
155-
shutil.copy2(screenshot_src, os.path.join(target_app_dir, screenshot_name))
156-
else:
157-
print(f"[WARN] Screenshot configured but not found: {screenshot_src}")
158-
159-
apps.append({
160-
"id": app_id,
161-
"name": name or app_id,
162-
"description": description,
163-
"screenshot": screenshot_target
164-
})
165-
166-
# Generate root index.html
167-
apps.sort(key=lambda a: a["id"])
168-
index_html_path = os.path.join(SITE_DIR, "index.html")
169-
170-
with open(index_html_path, "w", encoding="utf-8") as f:
171-
f.write("<!DOCTYPE html>\n<html lang='en'>\n<head>\n")
172-
f.write(" <meta charset='UTF-8'>\n")
173-
f.write(" <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n")
174-
f.write(" <title>KMP Web Apps</title>\n")
175-
f.write(" <style>\n")
176-
f.write(" body { font-family: system-ui, sans-serif; max-width: 960px; margin: 2rem auto; padding: 0 1rem; }\n")
177-
f.write(" h1 { margin-bottom: 0.25rem; }\n")
178-
f.write(" .tag { color: #666; font-size: 0.9rem; margin-bottom: 1.5rem; }\n")
179-
f.write(" .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; }\n")
180-
f.write(" .card { border: 1px solid #ddd; border-radius: 0.75rem; padding: 1rem; text-decoration: none; color: inherit; background: #fafafa; transition: box-shadow 0.15s, transform 0.15s; }\n")
181-
f.write(" .card:hover { box-shadow: 0 6px 18px rgba(0,0,0,0.08); transform: translateY(-2px); }\n")
182-
f.write(" .card h2 { margin-top: 0; margin-bottom: 0.25rem; font-size: 1.1rem; }\n")
183-
f.write(" .card p { margin: 0.25rem 0 0.5rem 0; font-size: 0.9rem; color: #555; }\n")
184-
f.write(" .badge { display: inline-block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: #555; background: #eaeaea; padding: 0.1rem 0.45rem; border-radius: 999px; margin-bottom: 0.3rem; }\n")
185-
f.write(" .screenshot { width: 100%; border-radius: 0.5rem; margin-top: 0.5rem; border: 1px solid #e0e0e0; object-fit: cover; max-height: 180px; }\n")
186-
f.write(" .empty { color: #777; font-style: italic; }\n")
187-
f.write(" </style>\n")
188-
f.write("</head>\n<body>\n")
189-
190-
f.write(" <h1>KMP Web Apps</h1>\n")
191-
if release_tag:
192-
f.write(f" <div class='tag'>Deployed from release <strong>{html.escape(release_tag)}</strong></div>\n")
193-
194-
if not apps:
195-
f.write(" <p class='empty'>No web apps detected for this release (no valid <code>webapp.json</code> with a working <code>index.html</code>).</p>\n")
196-
else:
197-
f.write(" <div class='grid'>\n")
198-
for app in apps:
199-
href = f"./{app['id']}/"
200-
name = html.escape(app["name"])
201-
desc = html.escape(app["description"] or "")
202-
f.write(f" <a class='card' href='{href}'>\n")
203-
f.write(f" <div class='badge'>/{html.escape(app['id'])}</div>\n")
204-
f.write(f" <h2>{name}</h2>\n")
205-
if desc:
206-
f.write(f" <p>{desc}</p>\n")
207-
if app["screenshot"]:
208-
f.write(f" <img class='screenshot' src='{html.escape(app['screenshot'])}' alt='Screenshot of {name}' />\n")
209-
f.write(" </a>\n")
210-
f.write(" </div>\n")
211-
212-
f.write("</body>\n</html>\n")
213-
214-
print(f"[OK] Root index generated at {index_html_path}")
215-
PYTHON_EOF
72+
python3 scripts/generate-samples-page.py --build --output site
21673
21774
- name: Upload artifact for GitHub Pages
21875
uses: actions/upload-pages-artifact@v3

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ replay_pid*
2929
.idea
3030
.kotlin
3131

32+
# Generated site directories
33+
site/
34+
preview-site/

0 commit comments

Comments
 (0)