efits
A server-rendered site for EVE fits and skillplans. Each fit carries pyfa's simulation of it, and every number on a fit's page is coloured by where it ranks among the other fits on the same hull. A fit without a skillplan of its own borrows the newest plan on its hull. The fleet page adds fits up into wings and a fleet, and keeps the whole fleet in its link.
The browser gets HTML, the small scripts for the editors, the searches and the
fleet page, and the fitter's components. Every list searches as the term is
typed: fits in Typesense straight from the browser with a search-only key, and
skillplans by the names already on the page. The fit lists also narrow by
facets, either the hull's class, race, tech, meta and faction (joined from
eve's eve-types) or the fit's own cap stability and sensors. They filter by
ranges typed under the stat columns and sort on any of those columns, and the
link holds all of it. The fitter also prices its
shopping list from the browser with a select-only ClickHouse user. Everything
else reaches ClickHouse and Typesense from the server.
Pages
/ newest fits, or a search: ?q=, a facet (?group_name=Frigate),
a range (?targeting_misc_speed=2000..), ?sort=-defense_ehp_total
/ship/<hull> every fit on a hull, searched the same way
/ship/<hull>/fit/<id> a fit
/ship/<hull>/fit/<id>/fit the fit as EFT text
/ship/<hull>/fit/<id>/skillplan the plan it shows, as text
/fit/<id> redirects to the fit under its hull; /fit and /skillplan work here too
/skillplans every plan, or a search with ?q=
/skillplan/<id> a plan; /skillplan/<id>/skillplan is its text
/fleet?s=<base64 JSON> a fleet
/fitter opens the first fitter workspace
/fitter/<id> a fitter workspace: fits and a hangar, and the shopping list between them
The fitter is the one page rendered from Svelte components, since it
recomputes as it is edited. Its workspaces are shared, and every edit saves to
/api/fitter/workspaces/<id>, where the server splits charges out of their
modules and cuts pasted contracts into items. The browser prices the shopping
list itself, off eve's market_orders as the select-only eve_market user,
and finds the fits it adds in the efits-fits Typesense collection with the
read-only efits_search key.
Every page also answers under /admin, where the fit list shows every fit and
the fit and skillplan pages carry editors. Edits save as a field loses focus.
Code
src/middleware.ts picks the site a request is in and rewrites /admin reads
to the public page. It also turns a thrown HttpError into its status and
anything else into a 500. Pages load all their data in their own frontmatter,
since a component that fails mid-render can no longer change the status.
src/lib holds everything that is not markup: the ClickHouse and Typesense
clients, the stat definitions the fit page draws (stats.ts), ranking
(compare.ts), skillplan parsing, and reading and totalling fleets. The
browser scripts are in src/scripts, and admin writes go to the endpoints in
src/pages/admin/api.
Data
realdb.toml declares the efits project on the shared ClickHouse: fits,
skillplans and the fitter's workspaces. Each replaces on updated, so an
edit or a delete is a new row.
src/lib/realdb.ts is generated from it with realdb gen .ts. Skill ranks come
from the EVE static data in Typesense.
typesense.toml is this repo's copy of the efits project on the shared
Typesense: the fits collection the pyfa sync fills, and the keys that read it.
Commands
bun run dev dev server on :4321
./vet.sh tests, build and nag; done means it exits 0
task tag, build and push the docker image, then deploy it with cooler
task publish tag, build and push the docker image, tagged with the commit, latest and any tag on it