chore(frontend): shrink panel controls, configure Netlify deploy
- Shrink category cards and panel buttons for wider code view - Add netlify.toml, document backend URL/port setup for Netlify deploys
This commit is contained in:
parent
7a6df57ad0
commit
faeede3447
5 changed files with 75 additions and 13 deletions
23
README.md
23
README.md
|
|
@ -49,6 +49,29 @@ WebSocket server to it. Matchmaking and room/session logic are not
|
|||
implemented yet — see `backend/src/matchmaking/README.md` and
|
||||
`backend/src/rooms/README.md`.
|
||||
|
||||
## Deployment
|
||||
|
||||
The frontend (static Vite build) and backend (persistent Node
|
||||
HTTP+WebSocket process) deploy independently and to different kinds of
|
||||
host.
|
||||
|
||||
**Frontend on Netlify:** the root `netlify.toml` builds from
|
||||
`frontend/` (`npm run build`, publish `frontend/dist`). Point this site
|
||||
at your deployed backend by setting `VITE_WS_URL` under Site settings
|
||||
-> Environment variables (or `netlify env:set VITE_WS_URL
|
||||
wss://your-backend-host`) — it's read at build time by
|
||||
`frontend/src/net/client.ts`. Use `wss://`, not `ws://`: once the
|
||||
Netlify site is served over https, a plain `ws://` socket is blocked as
|
||||
mixed content (the client warns in the console if this is
|
||||
misconfigured). See `frontend/.env.example`.
|
||||
|
||||
**Backend:** Netlify doesn't run long-lived Node processes, so
|
||||
`backend/` needs a real host (Fly.io, Render, Railway, a VPS, ...) that
|
||||
can keep a WebSocket server alive. It listens on `process.env.PORT`
|
||||
(see `backend/src/index.js`), which most such hosts set automatically;
|
||||
override it manually if yours doesn't. Whatever host/port it ends up
|
||||
on, put that address into the frontend's `VITE_WS_URL` above.
|
||||
|
||||
## Status
|
||||
|
||||
Single-player game: playable. Multiplayer: backend is a bare HTTP+WS
|
||||
|
|
|
|||
|
|
@ -1 +1,13 @@
|
|||
# Multiplayer WebSocket backend URL, read at build time via
|
||||
# `import.meta.env.VITE_WS_URL` (see src/net/client.ts). Defaults to
|
||||
# ws://localhost:8080 for local dev when unset.
|
||||
#
|
||||
# For a Netlify deploy, set this in Site settings -> Environment
|
||||
# variables (or `netlify env:set VITE_WS_URL wss://your-backend-host`)
|
||||
# to the deployed backend's address. Use wss:// (not ws://) once the
|
||||
# Netlify site is served over https, or the browser blocks the
|
||||
# connection as mixed content. The backend's own listen port is
|
||||
# separately configurable via its host's PORT env var — see
|
||||
# backend/src/index.js — and is not set here; it only affects which
|
||||
# port the backend process binds to, not this URL.
|
||||
VITE_WS_URL=ws://localhost:8080
|
||||
|
|
|
|||
|
|
@ -10,6 +10,17 @@ const DEFAULT_WS_URL = 'ws://localhost:8080';
|
|||
* dev backend. */
|
||||
export const WS_URL = import.meta.env.VITE_WS_URL || DEFAULT_WS_URL;
|
||||
|
||||
// A page served over https can't open a plain ws:// socket (browsers
|
||||
// block it as mixed content) — this only bites once VITE_WS_URL is
|
||||
// left unset/misconfigured on an https deploy (e.g. Netlify), so warn
|
||||
// loudly instead of failing silently as a closed connection.
|
||||
if (typeof location !== 'undefined' && location.protocol === 'https:' && WS_URL.startsWith('ws://')) {
|
||||
console.warn(
|
||||
`[net] VITE_WS_URL is "${WS_URL}" but this page is served over https — ` +
|
||||
'the browser will block it as mixed content. Set VITE_WS_URL to a wss:// URL.',
|
||||
);
|
||||
}
|
||||
|
||||
/** Lifecycle of the underlying socket. `closed` covers both a clean
|
||||
* close and an error — reconnecting is out of scope here, callers that
|
||||
* care just need to know the connection is gone. */
|
||||
|
|
|
|||
|
|
@ -257,12 +257,12 @@ body {
|
|||
}
|
||||
|
||||
.panel-col {
|
||||
width: 330px;
|
||||
flex: 0 0 330px;
|
||||
width: 260px;
|
||||
flex: 0 0 260px;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
|
|
@ -271,7 +271,7 @@ body {
|
|||
overflow-y: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
align-content: start;
|
||||
padding: 2px 6px 2px 2px;
|
||||
}
|
||||
|
|
@ -280,9 +280,9 @@ body {
|
|||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
}
|
||||
.panel-actions .btn { width: 100%; }
|
||||
.panel-actions .btn { width: 100%; padding: 7px 10px; font-size: 9px; }
|
||||
/* `game/multiplayerMatch.ts`'s mutual reveal-vote status line, shown
|
||||
* below the Reveal button once the local player has voted to reveal
|
||||
* early and is waiting on the opponent to do the same (or vice versa). */
|
||||
|
|
@ -361,10 +361,10 @@ body {
|
|||
.cat-card {
|
||||
background: var(--panel-2);
|
||||
border: 3px solid var(--ink);
|
||||
padding: 8px;
|
||||
padding: 5px 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
box-shadow: 3px 3px 0 var(--ink);
|
||||
transition: transform .08s ease, box-shadow .08s ease;
|
||||
|
|
@ -386,7 +386,7 @@ body {
|
|||
}
|
||||
|
||||
.cat-swatch {
|
||||
width: 24px; height: 24px;
|
||||
width: 16px; height: 16px;
|
||||
border: 2px solid var(--ink);
|
||||
flex-shrink: 0;
|
||||
background: repeating-conic-gradient(#4b4540 0% 25%, #302f2a 0% 50%) 0 0/8px 8px;
|
||||
|
|
@ -401,15 +401,15 @@ body {
|
|||
|
||||
.cat-info { min-width: 0; }
|
||||
.cat-label {
|
||||
font-size: 8px;
|
||||
line-height: 1.5;
|
||||
font-size: 7px;
|
||||
line-height: 1.4;
|
||||
font-family: var(--pixel);
|
||||
color: var(--fg);
|
||||
white-space: normal;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.cat-count { font-size: 10px; color: var(--fg-dim); }
|
||||
.cat-count { font-size: 9px; color: var(--fg-dim); }
|
||||
|
||||
/* ---------- popover ---------- */
|
||||
|
||||
|
|
|
|||
16
netlify.toml
Normal file
16
netlify.toml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[build]
|
||||
base = "frontend"
|
||||
command = "npm run build"
|
||||
publish = "dist"
|
||||
|
||||
[build.environment]
|
||||
NODE_VERSION = "20"
|
||||
|
||||
# The multiplayer WebSocket backend (backend/) is a persistent Node
|
||||
# process — it does not run on Netlify. Deploy it separately (Fly.io,
|
||||
# Render, Railway, a VPS, ...) and point this site at it by setting
|
||||
# VITE_WS_URL in Site settings -> Environment variables (Netlify
|
||||
# dashboard) or via `netlify env:set VITE_WS_URL wss://your-backend-host`.
|
||||
# It must be `wss://` (not `ws://`) once this site is served over
|
||||
# https, or browsers block the connection as mixed content. See
|
||||
# frontend/.env.example and frontend/src/net/client.ts.
|
||||
Loading…
Reference in a new issue