Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
55 lines
3.4 KiB
Bash
Executable File
55 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Stamp out a new game from the template.
|
|
# ./new-game.sh <slug> "<Name>" [port] [domain]
|
|
# e.g. ./new-game.sh tumbleweed "Tumbleweed" 8789 tumbleweed.kestrelsnest.social
|
|
# Ports so far: wizwar 8787, waving-hands 8788. Each game is its own droplet,
|
|
# so the port only has to be unique on your machine for running two locally.
|
|
set -euo pipefail
|
|
SLUG="${1:?usage: new-game.sh <slug> \"<Name>\" [port] [domain]}"
|
|
NAME="${2:?usage: new-game.sh <slug> \"<Name>\" [port] [domain]}"
|
|
PORT="${3:-8789}"
|
|
DOMAIN="${4:-$SLUG.kestrelsnest.social}"
|
|
case "$SLUG" in *[!a-z0-9-]*) echo "slug: lowercase letters, digits and hyphens" >&2; exit 1;; esac
|
|
DEST="$(cd "$(dirname "$0")/.." && pwd)/$SLUG"
|
|
[ -e "$DEST" ] && { echo "$DEST already exists" >&2; exit 1; }
|
|
KIT="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
rsync -a --exclude node_modules --exclude .svelte-kit --exclude build --exclude data "$KIT/template/" "$DEST/"
|
|
# File names carry the slug (unit, cron, backup, rollup, skills).
|
|
find "$DEST" -depth -name '*__SLUG__*' | while read -r f; do
|
|
mv "$f" "$(dirname "$f")/$(basename "$f" | sed "s/__SLUG__/$SLUG/g")"
|
|
done
|
|
# Then the placeholders inside. __IP__ and the Sentry ids stay until they exist.
|
|
find "$DEST" -type f \( -name '*.ts' -o -name '*.svelte' -o -name '*.json' -o -name '*.md' -o -name '*.sh' -o -name '*.tmpl' -o -name '*.service' -o -name '*.cron' -o -name '*.html' -o -name '*.css' -o -name '.gitignore' \) -print0 \
|
|
| xargs -0 sed -i '' -e "s/__SLUG__/$SLUG/g" -e "s/__NAME__/$NAME/g" -e "s/__PORT__/$PORT/g" -e "s/__DOMAIN__/$DOMAIN/g"
|
|
cp "$KIT/CONVENTIONS.md" "$DEST/docs-conventions.md" 2>/dev/null || true
|
|
mkdir -p "$DEST/docs" && mv "$DEST/docs-conventions.md" "$DEST/docs/conventions.md"
|
|
|
|
cd "$DEST"
|
|
git init -q && git add -A && git commit -q -m "Begin $NAME from the game kit"
|
|
npm install --no-audit --no-fund >/dev/null 2>&1 && (cd server && npm install --no-audit --no-fund >/dev/null 2>&1) && echo "dependencies installed" || echo "npm install failed; run it by hand (root and server/)"
|
|
cat <<MSG
|
|
|
|
$NAME is at $DEST (port $PORT, $DOMAIN).
|
|
|
|
Next:
|
|
1. Replace src/lib/game/index.ts with your game, keeping the GameSpec shape,
|
|
and src/lib/components/Board.svelte with its board. Keep the tests green.
|
|
2. Fill in the hall's pitch, tag and about panel (src/lib/components/Hall.svelte),
|
|
the rules page, the guide, src/app.html's description, and the palette in src/app.css.
|
|
Add static/og.png (1200 by 630) and static/apple-touch-icon.png (180 by 180):
|
|
app.html already points at them, and the static fallback serves the hall's
|
|
HTML for a missing file, so a share card without the image breaks quietly.
|
|
3. Create the droplet (deploy/README.md), then replace __IP__ everywhere:
|
|
grep -rl __IP__ . --exclude-dir=node_modules | xargs sed -i '' 's/__IP__/<ip>/g'
|
|
4. Create a Sentry project (the Sentry MCP can) and put its DSN and project id
|
|
in deploy/$SLUG.service and deploy/sentry-slack-alert.sh.
|
|
5. deploy/deploy.sh <ip>
|
|
6. Put the game in the family: add it to the kit's family.json (every game's
|
|
about panel lists the others from that file at its next deploy), then give
|
|
it a card on the family's landing page, Kestrel's Hall, hand-written HTML in
|
|
the blog repo at ~/Sites/blog/static/gamehall/index.html, and deploy the blog.
|
|
Card art is the game's own drawing; never a publisher's logo or scan.
|
|
CONVENTIONS.md in the kit is the house style every game follows.
|
|
MSG
|