A React TypeScript website built with Vite for the OpenKotOR community.
- Node.js 22+ (use
.nvmrcif you use nvm) - npm
npm installnpm run devStarts the Vite development server at http://localhost:3000
npm run buildBuilds the project and outputs to the docs folder. Production base is controlled with VITE_BASE (see Deployment). Local npm run dev uses root / by default.
GitHub project Pages (subpath) test build (this GitHub repository is OpenKotOR/website → https://<org>.github.io/website/ if you do not use a custom domain):
Windows (Command Prompt):
set VITE_BASE=/website/
npm run buildmacOS / Linux (bash), with the same repo name the workflow uses:
VITE_BASE=/website/ npm run buildCI sets VITE_BASE to /<github-repo-name>/ in .github/workflows/deploy-site.yml — for this repo, /website/.
npm run serveBuilds the project and serves the docs folder using live-server at http://localhost:3000
npm run type-checkRuns TypeScript type checking without building.
Production is deployed from .github/workflows/deploy-site.yml on every push to main, on published GitHub Releases, and on manual workflow runs (workflow_dispatch).
The workflow runs two static builds: GitHub Pages with VITE_BASE=/<repo>/ (project-site subpath) and a Hugging Face Space build with VITE_BASE=/ at the Space root. That split keeps asset paths and react-router correct on each host.
- In the repository, open Settings → Pages.
- Under Build and deployment, set Source to GitHub Actions (not Deploy from a branch if you use the
deploy-github-pagesjob in this repo). - The Deploy site workflow publishes the
build_github_pagesartifact. The public URL is typicallyhttps://<org>.github.io/<repo>/.
GITHUB_TOKEN is enough; no extra secret is needed for Pages. The publish job uses id-token: write and pages: write as the official Pages actions require.
Hugging Face namespace for this site is OldRepublicDevs (the GitHub org for source remains OpenKotOR/website).
-
Create the Space once (Static HTML) using a token that can create repositories in the OldRepublicDevs namespace (token settings):
hf auth login hf repos create OldRepublicDevs/site --repo-type space --space-sdk static --public --exist-ok
CI runs the same
hf repos create … --exist-okbefore each upload. Override the Space id withHF_SPACE_REPOif needed. Runhf repos create --helpfor other options. -
In Settings → Secrets and variables → Actions, add a secret named either
HF_TOKENorHF_ACCESS_TOKEN(same value; the name matches a common local env). Use a user or fine-grained token with write access to the Space. Never commit the token, print it, or use it in client-side code. Rotate the token if it is leaked. -
The Sync Hugging Face Space job uploads to
OldRepublicDevs/site(Space idHF_SPACE_REPOin.github/workflows/deploy-site.yml). The canonical Hub mirror ishttps://oldrepublicdevs-site.static.hf.space/(see Spaces overview: the running host is derived from owner + Space name, e.g.SPACE_HOST/ embed URLs likehttps://<author>-<space>.hf.spacein Spaces embed; static builds use the*.static.hf.spacesuffix on the same subdomain string).https://openkotor.static.hf.space/is not something you can attach to a Space. That hostname is a single DNS label under the Public Suffix zonestatic.hf.space; Hub does not expose “pick any label” for it, and an unauthenticatedGETcurrently returns 401 (reserved / unassigned), not your app. The default Space URL for this org is the Space reposite→https://oldrepublicdevs-site.static.hf.space/. For a hostname you choose (e.g.preview.openkotor.com), use a custom domain (PRO/Team) with a CNAME tohf.spaceas documented there.
If the Space still shows the Gradio “Get started” tutorial (or “No application file”) even though index.html is on the Hub, the Space README.md is still sdk: gradio. A static Vite app must use root README.md with sdk: static — see scripts/hf-space-README.md. Fix it in either way:
- From GitHub (no local clone): push these changes, add
HF_TOKENin repo secrets, then run the workflow Fix HF Space (static README) under the Actions tab (Run workflow). - Locally (set
HF_TOKENorHF_ACCESS_TOKEN):
.\scripts\fix-hf-space-readme.ps1Full rebuild + upload to the same Space:
.\scripts\publish-hf.ps1Manual upload from your machine (optional): install the hf CLI (pip install "huggingface-hub[cli]"), set HF_TOKEN or HF_ACCESS_TOKEN, then from the repository root on Windows:
.\scripts\publish-hf.ps1The script runs VITE_BASE=/ build and hf upload to the Space. Override the destination with HF_SPACE_REPO=Owner/name if needed.
If the Space shows the Gradio “get started” page instead of the app: a Static HTML Space must have a root README.md with sdk: static (and app_file: index.html). This project copies scripts/hf-space-README.md into the deploy bundle for every Hub upload. After a successful run, the Space should load index.html as the app. (Gradio-specific dependency docs here do not apply to static sites.)
Troubleshooting
- Missing
HF_TOKEN/HF_ACCESS_TOKEN: the job errors; add one of them under Actions secrets and re-run. 403on upload: the token does not have write access to that Space, or the Space is under a different organization than the token is allowed to push to.404/ not found: create the Space first, or pointhf uploadat the correct repository id.- Space UI still like Gradio after push: in the Space Files tab, confirm
README.mdat the top containssdk: staticand thatindex.htmlis at the root; if needed, trigger a Factory reboot in Space settings.
The project is configured to work with VS Code Live Server extension:
-
VS Code Settings: The
.vscode/settings.jsonfile configures Live Server; point the root at thedocsfolder (update it if it still referencesdist).- Run on port 3000
- Auto-open the browser
- Ignore source files and development dependencies
-
Usage:
- Build the project:
npm run build - Right-click on
docs/index.htmlin VS Code - Select "Open with Live Server"
- Build the project:
├── .github/ # CI: deploy to GitHub Pages and Hugging Face
│ └── workflows/
│ └── deploy-site.yml
├── .nvmrc # Node version for local dev and Actions
├── docs/ # Vite build output (served by Live Server and deployed by CI)
│ ├── index.html
│ └── assets/
├── src/ # Source files
│ ├── App.tsx
│ ├── index.tsx
│ └── app.scss
├── .vscode/
│ └── settings.json
├── package.json
├── vite.config.ts
└── tsconfig.json
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run serve- Build and serve with live-servernpm run type-check- Type checking only