aboutsummaryrefslogtreecommitdiffstats
path: root/skills/ship-static/SKILL.md
blob: 1ef74d30a8a1cd6c6603abfcda0895d57e17b039 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
---
name: ship-static
description: 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.
argument-hint: "<path-to-dist> <app-name> [host-nickname]"
---

# ship-static

Deploy a static site by rsyncing a local directory to the server and configuring Caddy.

## Read Config

```bash
python3 -c "
import json, os
cfg = json.load(open(os.path.expanduser('~/.config/ship/config.json')))
nick = '<nickname-or-default>'
h = cfg['hosts'].get(nick, cfg['hosts'][cfg['default']])
print(h['host'])
print(h['domain'])
"
```

## Inputs

- **Dist path** — local directory containing the built static files (e.g. `./dist`, `./out`)
- **App name** — short lowercase name, becomes the subdomain (e.g. `mysite`)
- **Domain** — defaults to `<app-name>.<base-domain>`, ask if different
- **Host** — use default unless specified

## Steps

### 1. Validate local path

Check that the dist directory exists and contains an `index.html`:

```bash
ls <dist-path>/index.html
```

If not found, tell the user — they may need to build first.

### 2. Create remote directory

```bash
ssh <host> "sudo mkdir -p /var/www/<app-name> && sudo chown $USER:$USER /var/www/<app-name>"
```

### 3. Sync files

```bash
rsync -avz --delete <dist-path>/ <host>:/var/www/<app-name>/
```

The `--delete` flag removes files on the server that no longer exist locally, keeping
the deployment clean. Tell the user how many files were transferred.

### 4. Fix ownership

After rsync, ensure Caddy can read the files:

```bash
ssh <host> "sudo chown -R www-data:www-data /var/www/<app-name>"
```

### 5. Write Caddy config

Check if a config already exists:

```bash
ssh <host> "cat /etc/caddy/sites-enabled/<app-name>.caddy 2>/dev/null"
```

Write (or overwrite) the config:

```bash
ssh <host> "sudo tee /etc/caddy/sites-enabled/<app-name>.caddy > /dev/null << 'EOF'
<domain> {
    root * /var/www/<app-name>
    file_server
    encode gzip
}
EOF"
```

### 6. Validate and reload Caddy

```bash
ssh <host> "sudo caddy validate --config /etc/caddy/Caddyfile 2>&1"
```

If valid:
```bash
ssh <host> "sudo systemctl reload caddy"
```

If invalid, show the error and do not reload.

### 7. Confirm

Tell the user:
- URL the site is live at
- Number of files synced
- Whether this was a new deployment or an update

## Notes

- Build before deploying — this skill does not run build commands
- `--delete` in rsync means files removed locally will be removed from the server too
- If the user wants a custom domain, use ship-caddy to update the config after deploying
- For SPAs with client-side routing, the Caddy config may need a `try_files` directive:
  ```
  <domain> {
      root * /var/www/<app-name>
      try_files {path} /index.html
      file_server
      encode gzip
  }
  ```
  Ask the user if their site uses client-side routing.
- Use default host unless another is specified