Courtside MVP: engine, web app, Docker + Cloudflare Tunnel deploy, docs
Tournament engine (pools, single/double elimination, standings with proper tiebreaks, withdrawals, two-court queue with ETAs and alerts), a single-process Node server with SQLite via node:sqlite and a WebSocket live board, organizer desk, QR landing page that follows the tournament phase, Dockerfile and compose with cloudflared, and documentation for deploying and running a day. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01MB7nCCAscYsb3zzkT6LHZi
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { esc } from '../http.js';
|
||||
|
||||
export function layout({ title, body, state = null, script = null, bodyClass = '', admin = null, nav = '' }) {
|
||||
return `<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="theme-color" content="#0F1418">
|
||||
<title>${esc(title)} · Courtside</title>
|
||||
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
|
||||
<link rel="manifest" href="/static/manifest.webmanifest">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;600;700&family=Source+Sans+3:wght@400;600&family=JetBrains+Mono:wght@500&display=swap">
|
||||
<link rel="stylesheet" href="/static/app.css">
|
||||
</head>
|
||||
<body class="${esc(bodyClass)}">
|
||||
<header class="top">
|
||||
<a class="brand" href="/">Courtside</a>
|
||||
<nav>${nav}${admin ? `<a href="/admin">Desk</a><a href="/admin/logout">Sign out</a>` : ''}</nav>
|
||||
</header>
|
||||
<main>
|
||||
${body}
|
||||
</main>
|
||||
<footer class="foot">Courtside · self-hosted tournament desk · <a href="https://gitea.cloudfreeiot.com/bkvargyas/courtside">source</a></footer>
|
||||
${state ? `<script id="state" type="application/json">${JSON.stringify(state).replace(/</g, '\\u003c')}</script>` : ''}
|
||||
${script ? `<script src="${esc(script)}" defer></script>` : ''}
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
export const flash = (msg, kind = 'ok') => msg ? `<div class="flash ${kind}">${esc(msg)}</div>` : '';
|
||||
Reference in New Issue
Block a user