Skip to content

Commit 566e8c5

Browse files
committed
updated README
1 parent 35dc653 commit 566e8c5

2 files changed

Lines changed: 73 additions & 208 deletions

File tree

.env.example

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ RATE_LIMIT_DOCS_MAX=120
1616

1717
# CORS
1818
# Comma-separated allowlist for browser requests. (curl/server-to-server are unaffected.)
19-
# Recommended:
20-
# - your website: https://wuwa.projektcode.com
21-
# - your GitHub Pages origin: https://projektcode.github.io
22-
CORS_ALLOWED_ORIGINS=https://wuwa.projektcode.com,https://projektcode.github.io
19+
# Example: https://example.com,https://mysite.github.io
20+
CORS_ALLOWED_ORIGINS=
2321

2422
# Demo (local only)
2523
ENABLE_DEMO=false

README.md

Lines changed: 71 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -1,246 +1,113 @@
11
# wuwa-api
22

3-
A Node.js (Fastify) REST API for **Wuthering Waves** data. It serves structured JSON (characters, weapons, metadata) and local images.
3+
A Node.js (Fastify) REST API for **Wuthering Waves** data serves structured JSON (characters, weapons) and optimized WebP images.
44

5-
Not affiliated with or endorsed by Kuro Games.
5+
> Not affiliated with or endorsed by Kuro Games.
66
7-
## Features
8-
9-
- REST API under `/v1/*`
10-
- Swagger UI at `/docs`
11-
- File-backed dataset:
12-
- `assets/data/**/en.json`
13-
- `assets/images/**` (normalized `.webp`)
14-
- Published dataset under `assets/` (generated privately from community sources and normalized):
15-
- character skills + scaling tables
16-
- character base stats at levels `20/50/90`
17-
- character images: `icon/card/splash/attribute`
18-
- weapon base ATK at `20/50/90` + passive effects + weapon icon
19-
- Data validation command (`npm run validate-data`)
20-
21-
## Requirements
22-
23-
- Node.js (recommend current LTS)
24-
25-
## Install
7+
## Quick Start
268

279
```bash
2810
npm install
11+
cp .env.example .env # optional
12+
npm run dev # http://127.0.0.1:3000/docs
2913
```
3014

31-
## Run
32-
33-
### Development
34-
35-
```bash
36-
# optional: copy and tweak env
37-
cp .env.example .env
38-
39-
npm run dev
40-
```
41-
42-
Open:
43-
- Swagger UI: `http://127.0.0.1:3000/docs`
44-
45-
### Build + start
46-
47-
```bash
48-
npm run build
49-
npm run start
50-
```
51-
52-
## Environment variables
53-
54-
- `PORT` (default `3000`)
55-
- `HOST` (default `0.0.0.0`)
56-
- `DATA_ROOT` (default `assets/data`)
57-
- `IMAGES_ROOT` (default `assets/images`)
58-
59-
Rate limit tiers (self-hosters can change these in `.env` or in `docker-compose.yml`):
60-
- `RATE_LIMIT_WINDOW` (default `1 minute`)
61-
- `RATE_LIMIT_LIST_MAX` (default `15`) — list endpoints (`/v1/characters`, `/v1/weapons`)
62-
- `RATE_LIMIT_DETAIL_MAX` (default `60`) — detail endpoints (`/v1/characters/:id`, `/v1/weapons/:id`)
63-
- `RATE_LIMIT_IMAGE_MAX` (default `60`) — character image routes
64-
- `RATE_LIMIT_DOCS_MAX` (default `120`) — docs routes (`/docs`, `/documentation/*`)
65-
66-
CORS:
67-
- `CORS_ALLOWED_ORIGINS` (comma-separated) — browser allowlist for cross-origin requests (curl/server-to-server clients are unaffected)
68-
69-
Demo:
70-
- `ENABLE_DEMO` (default `false`) — enables `/demo/*` (served from `.local/demo` and not intended for public deploys)
71-
72-
Example:
73-
74-
```bash
75-
# easiest way: use a .env file
76-
cp .env.example .env
77-
78-
# then edit .env and run
79-
npm run dev
80-
```
81-
82-
## API endpoints
83-
84-
### Health
85-
86-
- `GET /healthz`
87-
88-
```bash
89-
curl -s http://127.0.0.1:3000/healthz
90-
```
91-
92-
### Swagger docs
93-
94-
- `GET /docs`
95-
96-
### Meta
97-
98-
- `GET /v1/meta`
99-
100-
```bash
101-
curl -s http://127.0.0.1:3000/v1/meta
102-
```
103-
104-
### Characters
15+
**Production:** `npm run build && npm start`
10516

106-
- `GET /v1/characters` (supports `search`, `element`, `weaponType`, `rarity`, `limit`, `offset`)
107-
- `GET /v1/characters/:id`
17+
## Features
10818

19+
- REST API at `/v1/*` with Swagger UI at `/docs`
20+
- File-backed dataset (`assets/data`, `assets/images`)
21+
- Characters: skills, scaling tables, stats at 20/50/90, images (icon/card/splash/attribute)
22+
- Weapons: base ATK at 20/50/90, passive effects, icons
23+
- Rate limiting by route tier
24+
- Data validation: `npm run validate-data`
25+
26+
---
27+
28+
<details>
29+
<summary><strong>API Endpoints</strong></summary>
30+
31+
| Endpoint | Description |
32+
|----------|-------------|
33+
| `GET /healthz` | Health check |
34+
| `GET /docs` | Swagger UI |
35+
| `GET /v1/meta` | API & dataset metadata |
36+
| `GET /v1/characters` | List characters (`search`, `element`, `weaponType`, `rarity`, `limit`, `offset`) |
37+
| `GET /v1/characters/:id` | Character details |
38+
| `GET /v1/characters/:id/images` | List available images |
39+
| `GET /v1/characters/:id/images/:file` | Get image file |
40+
| `GET /v1/weapons` | List weapons (`search`, `type`, `rarity`, `limit`, `offset`) |
41+
| `GET /v1/weapons/:id` | Weapon details |
42+
| `GET /v1/images/...` | Static image files (legacy) |
43+
44+
**Examples:**
10945
```bash
11046
curl -s "http://127.0.0.1:3000/v1/characters?search=augusta" | jq
11147
curl -s http://127.0.0.1:3000/v1/characters/augusta | jq
112-
```
113-
114-
### Character images
115-
116-
- `GET /v1/characters/:id/images` (lists available `.webp` files)
117-
- `GET /v1/characters/:id/images/:file`
118-
119-
```bash
120-
curl -s http://127.0.0.1:3000/v1/characters/augusta/images | jq
121-
curl -L http://127.0.0.1:3000/v1/characters/augusta/images/splash.webp --output splash.webp
122-
```
123-
124-
### Weapons
125-
126-
- `GET /v1/weapons` (supports `search`, `type`, `rarity`, `limit`, `offset`)
127-
- `GET /v1/weapons/:id`
128-
129-
```bash
130-
curl -s "http://127.0.0.1:3000/v1/weapons?search=harvest" | jq
13148
curl -s http://127.0.0.1:3000/v1/weapons/ages-of-harvest | jq
13249
```
13350

134-
### Static image root (legacy/compat)
135-
136-
- `GET /v1/images/...` serves static files rooted at `IMAGES_ROOT`.
137-
138-
Example:
139-
140-
```bash
141-
curl -I http://127.0.0.1:3000/v1/images/characters/augusta/splash.webp
142-
```
143-
144-
## Rate limiting
145-
146-
Rate limiting is enforced by `@fastify/rate-limit` using **route-level tiers**.
147-
148-
- List endpoints (`/v1/characters`, `/v1/weapons`): `RATE_LIMIT_LIST_MAX` per `RATE_LIMIT_WINDOW`
149-
- Detail endpoints (`/v1/characters/:id`, `/v1/weapons/:id`): `RATE_LIMIT_DETAIL_MAX` per `RATE_LIMIT_WINDOW`
150-
- Character image endpoints (`/v1/characters/:id/images*`): `RATE_LIMIT_IMAGE_MAX` per `RATE_LIMIT_WINDOW`
151-
- Docs endpoints (`/docs`, `/documentation/*`): `RATE_LIMIT_DOCS_MAX` per `RATE_LIMIT_WINDOW`
152-
153-
This API is designed to be public but discourage heavy usage (encourage self-hosting).
154-
155-
## Validate data
156-
157-
After updating `assets/` (or after manual edits):
158-
159-
```bash
160-
npm run validate-data
161-
```
162-
163-
## Temporary demo page
51+
</details>
16452

165-
A temporary demo page exists at:
166-
- `/demo/augusta.html`
53+
<details>
54+
<summary><strong>Environment Variables</strong></summary>
16755

168-
It is **disabled by default**. Enable it only for local testing:
56+
| Variable | Default | Description |
57+
|----------|---------|-------------|
58+
| `PORT` | `3000` | Server port |
59+
| `HOST` | `0.0.0.0` | Server host |
60+
| `DATA_ROOT` | `assets/data` | JSON data directory |
61+
| `IMAGES_ROOT` | `assets/images` | Image directory |
62+
| `RATE_LIMIT_WINDOW` | `1 minute` | Rate limit window |
63+
| `RATE_LIMIT_LIST_MAX` | `15` | List endpoints limit |
64+
| `RATE_LIMIT_DETAIL_MAX` | `60` | Detail endpoints limit |
65+
| `RATE_LIMIT_IMAGE_MAX` | `60` | Image endpoints limit |
66+
| `RATE_LIMIT_DOCS_MAX` | `120` | Docs endpoints limit |
67+
| `CORS_ALLOWED_ORIGINS` || Comma-separated browser allowlist |
68+
| `ENABLE_DEMO` | `false` | Enable `/demo/*` (local testing only) |
16969

170-
```bash
171-
ENABLE_DEMO=true npm run dev
172-
```
70+
See `.env.example` for a complete template.
17371

174-
The demo HTML is loaded from `.local/demo` (gitignored) so it won’t be published with the repo.
72+
</details>
17573

176-
## Data sources
74+
<details>
75+
<summary><strong>Docker & Deployment</strong></summary>
17776

178-
The dataset in `assets/` is sourced from community resources (e.g. Prydwen and Fandom).
179-
180-
181-
## Docker + deployment notes
182-
183-
This repo can be deployed anywhere that runs Docker.
184-
185-
### Build + run locally
77+
### Local Docker
18678

18779
```bash
18880
docker build -t wuwa-api .
18981
docker run --rm -p 3000:3000 wuwa-api
19082
```
19183

192-
The API is then available at:
193-
- `http://127.0.0.1:3000/docs`
194-
195-
### Deploy with Nginx Proxy Manager (recommended for home server)
84+
### With Nginx Proxy Manager
19685

197-
Use `docker-compose.yml` and connect the container to the same external Docker network as Nginx Proxy Manager. (GHCR image names must be lowercase; this repo uses `ghcr.io/projektcode/wuwa-api`.)
198-
199-
Key points:
200-
- Do **not** publish the API container port to the internet (no `ports:` section).
201-
- Use `expose: 3000` and attach to the NPM network (this repo’s compose uses the external network name `nginx_proxy`).
202-
203-
Run:
86+
Use `docker-compose.yml` on the same Docker network as NPM:
20487

20588
```bash
206-
# first start
207-
docker compose up -d
208-
209-
# updates (pull new image)
210-
docker compose pull
211-
docker compose up -d
89+
docker compose up -d # first start
90+
docker compose pull && docker compose up -d # updates
21291
```
21392

214-
#### NPM UI setup
215-
216-
In Nginx Proxy Manager → **Proxy Hosts****Add Proxy Host**:
217-
- **Domain Names**: `api.custom.domain`
218-
- **Scheme**: `http`
219-
- **Forward Hostname / IP**: `wuwa-api`
220-
- **Forward Port**: `3000`
93+
**NPM setup:** Add proxy host → Forward `wuwa-api:3000` → Enable SSL.
22194

222-
Then under **SSL**:
223-
- request/choose a cert for `api.custom.domain`
224-
- enable **Force SSL**
95+
### Hosting Options
22596

226-
After that, your API should be reachable at:
227-
- `https://api.custom.domain/v1/characters/augusta`
97+
| Platform | Notes |
98+
|----------|-------|
99+
| Fly.io / Render / Railway | Simple deploy; free tier limits apply |
100+
| Google Cloud Run | Usage-based; scales to zero |
101+
| Small VPS / Oracle Free VM | Best for always-on self-host |
228102

229-
### Hosting recommendations
103+
### Scaling Images
230104

231-
Because this API serves a lot of image bytes, free tiers are often limited by bandwidth.
105+
Start with images in `assets/images`. If bandwidth becomes an issue, move to object storage + CDN (S3/R2) and update image URLs.
232106

233-
Good fits:
234-
- Fly.io / Render / Railway / Koyeb (simple deploy; expect cold starts/limits on free tiers)
235-
- Google Cloud Run (good free usage-based tier; container-based; scales to zero)
236-
- A small VPS / Oracle Cloud Always Free VM (best for always-on self-host)
107+
</details>
237108

238-
### Images: cache vs object storage
109+
---
239110

240-
Start simple:
241-
- keep images in `assets/images`
242-
- run with `NODE_ENV=production` so image responses can be cached aggressively
111+
## Data Sources
243112

244-
If bandwidth becomes a problem:
245-
- move images to object storage + CDN (e.g., S3/R2 + a CDN)
246-
- keep the JSON API here, but change image URLs to point at the CDN
113+
Dataset in `assets/` is sourced from community resources (Prydwen, Fandom).

0 commit comments

Comments
 (0)