AtlatestRepositorysigil-site
sigil-site / treepublish.sh
1
#!/usr/bin/env bash2
set -euo pipefail4
# Publish the Sigil website to Codeberg Pages5
#6
# Usage: ./publish.sh [OPTIONS]7
#8
# Options:9
# --local Build only, don't commit/push10
# --serve After building, serve locally (implies --local)11
# --port PORT Port for local server (default: 8000)12
# --skip-build Skip building libraries (use existing build artifacts)13
# --with-repl Force-build the WASM web REPL (on by default for a production14
# publish; use this to also build it under --local)15
# --skip-repl Skip the WASM web REPL build (explicit opt-out; NOT recommended16
# for a production publish — it ships a possibly-stale REPL)17
#18
# The REPL build needs zig (auto-detected from ~/.sigil/toolchain/zig) and19
# wasm-opt/Binaryen (on Guix: run under `guix shell binaryen`). A production20
# publish builds it by default so the live REPL never silently goes stale.21
#22
# Environment:23
# SIGIL Path to sigil binary (default: ~/.sigil/bin/sigil)24
# PARENT_DIR Parent directory where sibling repos live (default: ..)25
# CODEBERG_USER Codeberg username for HTTPS push auth (default: daviwil)26
# CODEBERG_TOKEN When set, uses HTTPS for git operations instead of SSH27
#28
# This script:29
# 1. Ensures the sigil monorepo is present and built30
# 2. Clones/fetches all extracted core library repos31
# 3. Builds each library so API doc JSON is generated32
# 4. Builds the WASM web REPL (default for a production publish; --skip-repl to opt out)33
# 5. Assembles a combined lib directory for with-api-docs34
# 6. Builds the site35
# 7. Optionally deploys to Codeberg Pages37
LOCAL_ONLY=false38
SERVE=false39
PORT=800040
SKIP_BUILD=false41
WITH_REPL="" # empty = decide after parsing: a production publish builds the REPL, --local skips it43
while [[ $# -gt 0 ]]; do44
case $1 in45
--local)46
LOCAL_ONLY=true47
shift48
;;49
--serve)50
LOCAL_ONLY=true51
SERVE=true52
shift53
;;54
--port)55
PORT="$2"56
shift 257
;;58
--skip-build)59
SKIP_BUILD=true60
shift61
;;62
--with-repl)63
WITH_REPL=true64
shift65
;;66
--skip-repl)67
WITH_REPL=false68
shift69
;;70
*)71
echo "Unknown option: $1"72
echo "Usage: $0 [--local] [--serve] [--port PORT] [--skip-build] [--with-repl] [--skip-repl]"73
exit 174
;;75
esac76
done78
# The web REPL is part of a PRODUCTION publish by default, so a real deploy can79
# never silently ship a stale REPL wasm. (It did: usesigil.org sat at 0.17.380
# while the rest of the site read 0.17.6, because --with-repl was an easy-to-81
# forget opt-in.) A production publish now BUILDS the REPL unless --skip-repl is82
# passed explicitly; local dev previews (--local) skip it by default for fast83
# iteration (opt in with --with-repl). Either way the choice is explicit.84
if [[ -z "$WITH_REPL" ]]; then85
if [[ "$LOCAL_ONLY" == "true" ]]; then WITH_REPL=false; else WITH_REPL=true; fi86
fi88
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"89
cd "$SCRIPT_DIR"91
SIGIL="${SIGIL:-$HOME/.sigil/bin/sigil}"92
PARENT_DIR="${PARENT_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"93
PUBLIC_DIR="$SCRIPT_DIR/public"94
COMBINED_LIB="$SCRIPT_DIR/build/combined-lib"96
# Pages deployment target (usesigil.org is hosted from sigil monorepo pages branch)97
# Use HTTPS with token auth when CODEBERG_TOKEN is set (e.g. in CI),98
# otherwise use SSH (local development)99
if [[ -n "${CODEBERG_TOKEN:-}" ]]; then100
CODEBERG_USER="${CODEBERG_USER:-daviwil}"101
PAGES_REPO_URL="https://${CODEBERG_USER}:${CODEBERG_TOKEN}@codeberg.org/sigil/sigil.git"102
else103
PAGES_REPO_URL="[email protected]:sigil/sigil.git"104
fi105
PAGES_BRANCH="pages"106
DOMAIN="usesigil.org"108
# ---------------------------------------------------------------------------109
# Core libraries whose API docs appear on usesigil.org110
# ---------------------------------------------------------------------------112
# Monorepo packages (built from ../sigil) that need a _pkg manifest113
# generated when their custom tasks: skip the default copy-package-docs114
# step. The browser/WASM bridge packages all stage JS assets through115
# custom tasks, so without this list their package pages never render116
# on the site even though their module .json docs generate fine.117
MONOREPO_PACKAGES=(118
# P2-reabsorbed packages. Keep these explicit so their package manifests119
# and any package-local docs/ trees come from the monorepo build rather120
# than a retired standalone checkout.121
sigil-args122
sigil-format123
sigil-git124
sigil-help125
sigil-repl126
sigil-stdlib127
sigil-cli128
sigil-run129
sigil-browser130
sigil-wasm-runtime131
sigil-wasm-dom132
sigil-wasm-net133
sigil-wasm-canvas2d134
sigil-wasm-gl135
)137
# Extracted repos (cloned as peer directories and built individually).138
# Multi-package repos: sigil-lang (sigil-lib + sigil-stdlib),139
# sigil-build (sigil-package + sigil-deps + sigil-build),140
# sigil-test (sigil-test + sigil-test-runner).141
EXTRACTED_REPOS=(142
# sigil-lang, sigil-build, sigil-store and sigil-test were re-integrated into the143
# monorepo (packages/); their standalone repos are archived. Building the stale144
# clones let their modules override the monorepo's (2026-09-18: unbound145
# reset-compiler-input-proofs! from a May sigil-build). Keep them out.147
sigil-log sigil-json sigil-http sigil-crypto sigil-tls sigil-sqlite148
sigil-lsp sigil-mcp sigil-nrepl sigil-ffi149
sigil-peg sigil-sxml sigil-markdown sigil-css150
sigil-r7rs sigil-transducers sigil-web sigil-web-client sigil-yaml sigil-later151
# Core, general-purpose libraries added by the 2026-07 completeness audit.152
# These are published sigil/* library packages that were missing from the153
# docs site. (SaaS/API-client packages: forgejo, caldav, jmap, discourse,154
# postmark, ses, lemonsqueezy, telegram, twitch, youtube, wise, plus the155
# graphics/audio/game stack, are intentionally excluded; see the audit note.)156
# sigil-rss was also identified but is NOT release-ready (no tags, its157
# package.sgl lacks the required `sigil:` field and fails to build), so it158
# is held back until it is fixed and released. sigil-ledger was evaluated159
# and intentionally left out as too specialized.160
sigil-websocket sigil-oauth sigil-jwt sigil-irc sigil-xmpp161
sigil-org sigil-tui162
)164
# ---------------------------------------------------------------------------165
# Helper functions166
# ---------------------------------------------------------------------------168
info() { echo "=== $* ==="; }169
warn() { echo "WARNING: $*"; }170
die() { echo "ERROR: $*" >&2; exit 1; }172
repo_url() {173
local name="$1"174
if [[ -n "${CODEBERG_TOKEN:-}" ]]; then175
echo "https://codeberg.org/sigil/${name}.git"176
else177
echo "[email protected]:sigil/${name}.git"178
fi179
}181
ensure_repo() {182
local name="$1"183
local dir="$PARENT_DIR/$name"185
if [[ -d "$dir" ]]; then186
echo " Fetching $name..."187
git -C "$dir" fetch --quiet --tags 2>/dev/null || true188
else189
echo " Cloning $name..."190
git clone --quiet "$(repo_url "$name")" "$dir"191
fi192
}194
build_extracted_repo() {195
local name="$1"196
local dir="$PARENT_DIR/$name"198
if [[ ! -d "$dir" ]]; then199
warn "$name directory not found, skipping"200
return201
fi203
echo " Building $name..."204
cd "$dir"206
# Ensure deps are installed207
if [[ ! -d ".sigil/deps" ]]; then208
$SIGIL deps install > /dev/null 2>&1 || true209
fi211
# Build with --force to ensure JSON docs are generated.212
# The build may error after compilation due to sigil-lib resolution;213
# that's OK since compilation (and JSON generation) still succeeds.214
$SIGIL build --force > /dev/null 2>&1 || true216
cd "$SCRIPT_DIR"217
}219
# Merge a lib directory into the combined lib.220
# Copies .sgb, .json, and _pkg files. First source wins on conflicts.221
merge_lib() {222
local src="$1"223
local label="$2"225
if [[ ! -d "$src" ]]; then226
warn "$label lib dir not found: $src"227
return228
fi230
# Copy .sgb and .json files, preserving directory structure231
find "$src" -type f \( -name "*.sgb" -o -name "*.json" \) | while read -r file; do232
local rel="${file#$src/}"233
local dest="$COMBINED_LIB/$rel"234
if [[ ! -f "$dest" ]]; then235
mkdir -p "$(dirname "$dest")"236
cp "$file" "$dest"237
fi238
done240
# Copy _pkg directories (package metadata + docs)241
if [[ -d "$src/_pkg" ]]; then242
find "$src/_pkg" -type f | while read -r file; do243
local rel="${file#$src/}"244
local dest="$COMBINED_LIB/$rel"245
if [[ ! -f "$dest" ]]; then246
mkdir -p "$(dirname "$dest")"247
cp "$file" "$dest"248
fi249
done250
fi251
}253
# Fix package attribution for extracted repos.254
# When a module exists in both the monorepo (as part of sigil-stdlib) and an255
# extracted repo (as its own package), the monorepo .json says package: "sigil-stdlib"256
# but the extracted repo .json says package: "<repo-name>". We want the extracted257
# repo's attribution so the module appears under the correct package on the site.258
fix_extracted_json() {259
local name="$1"260
local src="$PARENT_DIR/$name/build/dev/lib"262
if [[ ! -d "$src" ]]; then263
return264
fi266
# Overwrite .json files in combined-lib where the extracted repo's version267
# has the correct package attribution (package matches the repo name)268
find "$src" -name "*.json" ! -path "*/_pkg/*" | while read -r file; do269
if grep -q "\"package\": \"$name\"" "$file"; then270
local rel="${file#$src/}"271
local dest="$COMBINED_LIB/$rel"272
mkdir -p "$(dirname "$dest")"273
cp "$file" "$dest"274
fi275
done276
}278
# Ensure a _pkg manifest exists for a monorepo package.279
# Some packages have custom tasks: that skip the default copy-package-docs step,280
# so their _pkg manifest is never created. We generate one from package.sgl.281
ensure_pkg_manifest() {282
local name="$1"283
local pkg_dir="$PARENT_DIR/sigil/packages/$name"284
local manifest_dir="$COMBINED_LIB/_pkg/$name"285
local manifest_path="$manifest_dir/manifest.json"287
# Skip if manifest already exists288
if [[ -f "$manifest_path" ]]; then289
return290
fi292
if [[ ! -f "$pkg_dir/package.sgl" ]]; then293
warn "No package.sgl for $name, cannot generate manifest"294
return295
fi297
# Extract version and description from package.sgl298
# Packages may omit version: (inherited from workspace), fall back to workspace version299
local version description300
version=$(grep 'version:' "$pkg_dir/package.sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)301
if [[ -z "$version" ]]; then302
version=$(grep 'version:' "$PARENT_DIR/sigil/package.sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)303
fi304
description=$(grep 'description:' "$pkg_dir/package.sgl" | head -1 | sed 's/.*description: *"\(.*\)".*/\1/' || true)306
mkdir -p "$manifest_dir"307
cat > "$manifest_path" <<MANIFEST308
{309
"name": "$name",310
"version": "$version",311
"description": "$description"312
}313
MANIFEST314
echo " Generated manifest for $name"315
}317
# Ensure a _pkg manifest exists for an EXTRACTED repo package.318
# Extracted repos whose package.sgl defines a custom tasks: build task override319
# the default build (which runs copy-package-docs), and if they also ship no320
# docs/ dir they never emit their own _pkg/<name>/manifest.json. Without that321
# manifest, Press's scan-library-docs skips the package entirely: no Libraries322
# sidebar entry and the /docs/lib/<name>/ page 404s (as happened to323
# sigil-crypto, sigil-tls, and sigil-nrepl). This is the same failure mode324
# ensure_pkg_manifest handles for MONOREPO_PACKAGES; generate the manifest from325
# the repo's own package.sgl. The package name is the repo name (matches the326
# convention fix_extracted_json relies on for single-package repos).327
ensure_extracted_pkg_manifest() {328
local name="$1"329
local repo_dir="$PARENT_DIR/$name"330
local pkg_sgl="$repo_dir/package.sgl"331
local build_lib="$repo_dir/build/dev/lib"333
if [[ ! -f "$pkg_sgl" ]]; then334
return335
fi337
local manifest_dir="$COMBINED_LIB/_pkg/$name"338
local manifest_path="$manifest_dir/manifest.json"340
# Skip if a manifest was already merged from the repo's own build output341
if [[ -f "$manifest_path" ]]; then342
return343
fi345
# Only synthesize a manifest when the repo actually built modules attributed346
# to this package. This guards against workspace/multi-package repos (e.g.347
# sigil-lang, whose package.sgl name is the workspace name "sigil-lang" but348
# which ships sigil-stdlib/sigil-lib) and against unbuilt/empty repos --349
# either would otherwise produce a bogus empty package in the sidebar.350
if [[ ! -d "$build_lib" ]]; then351
return352
fi353
if ! grep -rls "\"package\": \"$name\"" "$build_lib" --include='*.json' >/dev/null 2>&1; then354
return355
fi357
local version description358
version=$(grep 'version:' "$pkg_sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)359
description=$(grep 'description:' "$pkg_sgl" | head -1 | sed 's/.*description: *"\(.*\)".*/\1/' || true)361
mkdir -p "$manifest_dir"362
cat > "$manifest_path" <<MANIFEST363
{364
"name": "$name",365
"version": "$version",366
"description": "$description"367
}368
MANIFEST369
echo " Generated manifest for extracted package $name"370
}372
# ---------------------------------------------------------------------------373
# Step 1: Ensure sigil monorepo is present and built374
# ---------------------------------------------------------------------------376
info "Checking sigil monorepo"378
if [[ ! -d "$PARENT_DIR/sigil" ]]; then379
die "../sigil not found. Clone the sigil monorepo as a peer directory."380
fi382
if [[ "$SKIP_BUILD" != "true" ]]; then383
if [[ ! -d "$PARENT_DIR/sigil/build/dev/lib" ]]; then384
echo " Building monorepo..."385
cd "$PARENT_DIR/sigil"386
$SIGIL build387
cd "$SCRIPT_DIR"388
else389
echo " Monorepo build found."390
fi391
fi393
# ---------------------------------------------------------------------------394
# Step 2: Clone/fetch extracted library repos395
# ---------------------------------------------------------------------------397
info "Ensuring extracted library repos"399
for repo in "${EXTRACTED_REPOS[@]}"; do400
ensure_repo "$repo"401
done403
# ---------------------------------------------------------------------------404
# Step 3: Build extracted libraries405
# ---------------------------------------------------------------------------407
if [[ "$SKIP_BUILD" != "true" ]]; then408
info "Building extracted libraries"410
for repo in "${EXTRACTED_REPOS[@]}"; do411
build_extracted_repo "$repo"412
done413
fi415
# ---------------------------------------------------------------------------416
# Step 3.5: Build web REPL WASM (default for production publishes; --skip-repl to opt out)417
# ---------------------------------------------------------------------------419
if [[ "$WITH_REPL" == "true" ]]; then420
# Auto-detect the sigil-bundled zig so the REPL build works without a manual421
# PATH setup. sigil's pinned zig is cached under the monorepo's tools/zig422
# (populated by scripts/with-zig) and symlinked at ~/.sigil/toolchain/zig —423
# the same toolchain the release build uses. Only look if zig isn't already424
# on PATH.425
if ! command -v zig >/dev/null 2>&1; then426
for zdir in "$HOME/.sigil/toolchain/zig" "${PARENT_DIR:-}/sigil/tools/zig"; do427
if [[ -n "$zdir" && -x "$zdir/zig" ]]; then428
info "Using bundled zig at $zdir"429
export PATH="$zdir:$PATH"430
break431
fi432
done433
fi434
if ! command -v zig >/dev/null 2>&1; then435
die "REPL build requires zig: not on PATH and no bundled zig found at ~/.sigil/toolchain/zig or \$PARENT_DIR/sigil/tools/zig. Install zig, or run the monorepo's scripts/with-zig once to populate the bundled toolchain."436
fi438
# wasm-opt (Binaryen) is required for the --asyncify post-link pass that the439
# monorepo's --config web build runs. Without it that pass is silently440
# skipped and the REPL wasm ships unresolved asyncify.* imports, so it fails441
# to instantiate in the browser ("Import asyncify: module is not an object442
# or function") and the REPL hangs. Fail loudly instead of shipping a broken443
# REPL. On Guix, wasm-opt is not on PATH by default: re-run inside a guix444
# shell (zig is auto-detected, so binaryen is the only thing to add):445
# guix shell binaryen -- ./publish.sh446
if ! command -v wasm-opt >/dev/null 2>&1; then447
die "REPL build requires wasm-opt (Binaryen) for the --asyncify pass, not on PATH. On Guix: guix shell binaryen -- ./publish.sh (zig is auto-detected). To publish WITHOUT the REPL, pass --skip-repl explicitly — but that ships whatever REPL wasm is currently staged, which may be stale."448
fi450
info "Building web REPL (WASM)"452
ensure_repo "sigil-web-repl"453
REPL_SRC="$PARENT_DIR/sigil-web-repl"454
cd "$REPL_SRC"456
# Clean build: the bundle step globs everything under build/web/lib,457
# so orphaned modules from older builds survive incremental rebuilds458
# and ship stale bytecode (March-era v7 match/sxml modules rode along459
# this way and broke those REPL examples on the live site).460
rm -rf build/web462
# Install deps or use redirects to local monorepo463
if [[ -d "$PARENT_DIR/sigil" ]]; then464
REDIR_FILE=$(mktemp)465
cat > "$REDIR_FILE" << 'REDIR_EOF'466
(redirects467
repos: (list468
(for-repo469
url: "codeberg:sigil/sigil"470
use: (from-path dir: "../sigil"))))471
REDIR_EOF472
$SIGIL build --redirects "$REDIR_FILE" --config web473
rm -f "$REDIR_FILE"474
else475
$SIGIL deps install476
$SIGIL build --config web477
fi478
cd "$SCRIPT_DIR"480
# Copy WASM artifacts into site assets481
REPL_BUILD="$REPL_SRC/build/web"482
if [[ -f "$REPL_BUILD/sigil-web-repl.wasm" ]]; then483
echo " Copying WASM artifacts..."484
cp "$REPL_BUILD/sigil-web-repl.wasm" "$SCRIPT_DIR/assets/repl/"485
# The page JS and the wasm are a matched pair: a stale page driving486
# a fresh wasm hung evaluation on the live site (the eval/input ABI487
# plumbing had moved on). Always ship the page from the same build.488
cp "$REPL_BUILD/index.html" "$SCRIPT_DIR/assets/repl/index.html"490
# Generate merged lib.bundle (web-repl modules + extras for REPL examples).491
# generate-web-bundle lets LATER dirs override earlier ones, so the492
# REPL's own lib goes last: it is the coherent, freshly built set,493
# and a stale peer build must never override its core/stdlib494
# bytecode (a v7 sigil/core.sgb from an old sigil-sxml build once495
# shipped over the fresh v9 one and broke the live REPL).496
BUNDLE_DIRS=""497
for peer in sigil-sxml sigil-match; do498
if [[ -d "$PARENT_DIR/$peer/build/dev/lib" ]]; then499
echo " Adding modules from $peer..."500
BUNDLE_DIRS="$BUNDLE_DIRS \"$PARENT_DIR/$peer/build/dev/lib\""501
fi502
done503
BUNDLE_DIRS="$BUNDLE_DIRS \"$REPL_BUILD/lib\""505
echo " Generating lib.bundle..."506
$SIGIL eval "(import (sigil build))507
(let ((n (generate-web-bundle508
output: \"assets/repl/lib.bundle\"509
dirs: (list $BUNDLE_DIRS))))510
(display n)511
(display \" files bundled\n\"))"512
else513
warn "WASM build did not produce sigil-web-repl.wasm"514
fi515
fi517
# ---------------------------------------------------------------------------518
# Step 4: Assemble combined lib directory519
# ---------------------------------------------------------------------------521
info "Assembling combined API docs"523
rm -rf "$COMBINED_LIB"524
mkdir -p "$COMBINED_LIB"526
# Monorepo libs first (primary source)527
merge_lib "$PARENT_DIR/sigil/build/dev/lib" "monorepo"529
# Then extracted repos (only adds modules not already present)530
for repo in "${EXTRACTED_REPOS[@]}"; do531
merge_lib "$PARENT_DIR/$repo/build/dev/lib" "$repo"532
done534
# Fix package attribution for extracted repos whose modules overlap with monorepo535
for repo in "${EXTRACTED_REPOS[@]}"; do536
fix_extracted_json "$repo"537
done539
# Generate _pkg manifests for monorepo packages that lack them540
for pkg in "${MONOREPO_PACKAGES[@]}"; do541
ensure_pkg_manifest "$pkg"542
done544
# Generate _pkg manifests for extracted repos whose custom build tasks skip545
# copy-package-docs (e.g. sigil-crypto, sigil-tls, sigil-nrepl). Without this546
# they never appear in the Libraries sidebar and their pages 404.547
for repo in "${EXTRACTED_REPOS[@]}"; do548
ensure_extracted_pkg_manifest "$repo"549
done551
echo " Combined lib ready."553
# ---------------------------------------------------------------------------554
# Step 5: Build the site555
# ---------------------------------------------------------------------------557
info "Building site"559
# Ensure press and other deps are installed560
if [[ ! -d ".sigil/deps" ]]; then561
echo " Installing site dependencies..."562
$SIGIL deps install563
fi565
# Compile the site explicitly before run. `sigil run`'s auto-compile-hook566
# can produce sub-threshold .sgb stubs in some cases (see sigil-papercut t-2fa9);567
# an explicit `sigil build` produces real bytecode and avoids the failure mode568
# where `(import (sigil-site main))` finds the module but its exports are empty.569
echo " Compiling site sources..."570
$SIGIL build572
# Clear stale output before regenerating. The site build writes pages into573
# public/ but never removes ones that no longer exist, so pages for packages574
# dropped from the arrays (or any renamed/removed content) linger as stale575
# files. Because the deploy step copies public/ verbatim into the fresh pages576
# branch, those stale pages would ship to production on every republish, not577
# just locally. Starting from an empty output tree guarantees public/ reflects578
# exactly the current build.579
rm -rf "$PUBLIC_DIR"581
# Build and run the site582
# -L adds combined-lib to module search paths so Press's load-module-details583
# can find .json doc files for packages not in the site's dependency tree584
$SIGIL -L "$COMBINED_LIB" run -- build586
# Verify587
if [[ ! -d "$PUBLIC_DIR" ]] || [[ ! -f "$PUBLIC_DIR/index.html" ]]; then588
die "Site build failed - public directory missing or incomplete"589
fi591
# ---------------------------------------------------------------------------592
# Step 6: Deploy or serve593
# ---------------------------------------------------------------------------595
if [[ "$LOCAL_ONLY" == "true" ]]; then596
echo ""597
echo "Local build complete! Site is in: $PUBLIC_DIR"599
if [[ "$SERVE" == "true" ]]; then600
echo "Starting local server at http://localhost:$PORT"601
echo "Press Ctrl+C to stop."602
cd "$PUBLIC_DIR"603
python3 -m http.server "$PORT"604
fi605
else606
info "Publishing site to $DOMAIN"608
TEMP_DIR=$(mktemp -d)610
# Initialize a fresh repo with orphan branch611
cd "$TEMP_DIR"612
git init --quiet613
git config user.email "[email protected]"614
git config user.name "Sigil Pages"615
git checkout --orphan "$PAGES_BRANCH"617
# Copy public content618
cp -r "$PUBLIC_DIR"/* "$TEMP_DIR/"620
# Create .domains file for Codeberg Pages621
echo "$DOMAIN" > "$TEMP_DIR/.domains"623
# Commit and force push624
git add -A625
git commit --quiet -m "Update site"626
git remote add origin "$PAGES_REPO_URL"627
echo " Force pushing to $PAGES_BRANCH branch..."628
git push --force origin "$PAGES_BRANCH"630
echo ""631
echo "Done! Site will be available at:"632
echo " https://$DOMAIN/"633
echo " https://$DOMAIN/docs/"635
# Cleanup636
cd "$SCRIPT_DIR"637
rm -rf "$TEMP_DIR"638
fi