aboutsummaryrefslogtreecommitdiffstats
path: root/skills/ship-static/SKILL.md
diff options
context:
space:
mode:
Diffstat (limited to 'skills/ship-static/SKILL.md')
-rw-r--r--skills/ship-static/SKILL.md121
1 files changed, 121 insertions, 0 deletions
diff --git a/skills/ship-static/SKILL.md b/skills/ship-static/SKILL.md
new file mode 100644
index 0000000..1ef74d3
--- /dev/null
+++ b/skills/ship-static/SKILL.md
@@ -0,0 +1,121 @@
1---
2name: ship-static
3description: Deploy a static site to a ship VPS. Rsyncs a local dist folder to the server and configures Caddy to serve it. Use when deploying a built frontend, docs site, or any folder of static files.
4argument-hint: "<path-to-dist> <app-name> [host-nickname]"
5---
6
7# ship-static
8
9Deploy a static site by rsyncing a local directory to the server and configuring Caddy.
10
11## Read Config
12
13```bash
14python3 -c "
15import json, os
16cfg = json.load(open(os.path.expanduser('~/.config/ship/config.json')))
17nick = '<nickname-or-default>'
18h = cfg['hosts'].get(nick, cfg['hosts'][cfg['default']])
19print(h['host'])
20print(h['domain'])
21"
22```
23
24## Inputs
25
26- **Dist path** — local directory containing the built static files (e.g. `./dist`, `./out`)
27- **App name** — short lowercase name, becomes the subdomain (e.g. `mysite`)
28- **Domain** — defaults to `<app-name>.<base-domain>`, ask if different
29- **Host** — use default unless specified
30
31## Steps
32
33### 1. Validate local path
34
35Check that the dist directory exists and contains an `index.html`:
36
37```bash
38ls <dist-path>/index.html
39```
40
41If not found, tell the user — they may need to build first.
42
43### 2. Create remote directory
44
45```bash
46ssh <host> "sudo mkdir -p /var/www/<app-name> && sudo chown $USER:$USER /var/www/<app-name>"
47```
48
49### 3. Sync files
50
51```bash
52rsync -avz --delete <dist-path>/ <host>:/var/www/<app-name>/
53```
54
55The `--delete` flag removes files on the server that no longer exist locally, keeping
56the deployment clean. Tell the user how many files were transferred.
57
58### 4. Fix ownership
59
60After rsync, ensure Caddy can read the files:
61
62```bash
63ssh <host> "sudo chown -R www-data:www-data /var/www/<app-name>"
64```
65
66### 5. Write Caddy config
67
68Check if a config already exists:
69
70```bash
71ssh <host> "cat /etc/caddy/sites-enabled/<app-name>.caddy 2>/dev/null"
72```
73
74Write (or overwrite) the config:
75
76```bash
77ssh <host> "sudo tee /etc/caddy/sites-enabled/<app-name>.caddy > /dev/null << 'EOF'
78<domain> {
79 root * /var/www/<app-name>
80 file_server
81 encode gzip
82}
83EOF"
84```
85
86### 6. Validate and reload Caddy
87
88```bash
89ssh <host> "sudo caddy validate --config /etc/caddy/Caddyfile 2>&1"
90```
91
92If valid:
93```bash
94ssh <host> "sudo systemctl reload caddy"
95```
96
97If invalid, show the error and do not reload.
98
99### 7. Confirm
100
101Tell the user:
102- URL the site is live at
103- Number of files synced
104- Whether this was a new deployment or an update
105
106## Notes
107
108- Build before deploying — this skill does not run build commands
109- `--delete` in rsync means files removed locally will be removed from the server too
110- If the user wants a custom domain, use ship-caddy to update the config after deploying
111- For SPAs with client-side routing, the Caddy config may need a `try_files` directive:
112 ```
113 <domain> {
114 root * /var/www/<app-name>
115 try_files {path} /index.html
116 file_server
117 encode gzip
118 }
119 ```
120 Ask the user if their site uses client-side routing.
121- Use default host unless another is specified