npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hexah/create-skin

v0.1.7

Published

Scaffolder skórki Hexah (zdalny kontener Module Federation, harness dev z HMR).

Readme

@hexah/create-skin

Scaffolder skórki Hexah — generuje projekt zdalnej skórki Module Federation (rspack + @hexah/skin-sdk) z gotowym workflowem dev (HMR) i podłączeniem do hosta na środowisku testowym.

Kontrakt skórki (hooki danych, UI, sloty) dostarcza paczka @hexah/skin-sdk — wygenerowany projekt ma ją już w zależnościach (npm install @hexah/skin-sdk, by dodać do istniejącego).

Użycie

npm create @hexah/skin moja-skorka     # albo: npx @hexah/create-skin moja-skorka
cd moja-skorka
npm install
npm run dev        # rspack serve z HMR

Podłączenie do test.kf2.pl

Skórkę ładuje aplikacja działająca pod publicznym adresem (HTTPS), a przeglądarka nie pozwala takiej stronie pobrać zasobu z localhost. Wystaw więc dev server pod publicznym URL przez tunel:

npx cloudflared tunnel --url http://localhost:3001   # → https://<rand>.trycloudflare.com

<rand>.trycloudflare.com to adres, który cloudflared wypisze w terminalu — skopiuj go (zmienia się po każdym restarcie tunelu). Następnie otwórz https://test.kf2.pl, zaloguj się i w konsoli przeglądarki (F12 → Console) wklej:

localStorage.setItem('hexah.skinRemoteAllowedOrigins', JSON.stringify(['https://<rand>.trycloudflare.com']))
localStorage.setItem('hexah.skinRemote', JSON.stringify({
  name: 'moja_skorka',                                  // = nazwa kontenera (uniqueName w rspack.config.js)
  entry: 'https://<rand>.trycloudflare.com/remoteEntry.js',
  template: 'sdkremote',
  screens: { report: './ReportScreen' },
  apiVersion: '0.11.0',
}))

Odśwież stronę, w Ustawieniach Gry wybierz motyw „SDK Remote (zdalna skórka)" i wejdź na ekran zgłoszeń — zobaczysz swój ReportScreen na realnych danych. Po każdej zmianie w src/ odśwież stronę (remote przebuduje się przez HMR).

Budowanie motywu — co masz do dyspozycji

Importuj wyłącznie z @hexah/skin-sdk (+ react i @mui/* jako współdzielone singletony hosta). Nie masz dostępu do kodu gry — host dostarcza w runtime read-modele danych, usługi platformy, prymitywy UI i ciężkie sloty. Kontrakt jest wersjonowany (SKIN_API_VERSION, obecnie 0.11.0); deklarowane apiVersion musi mieć ten sam major i minor ≤ host.

Trzy sposoby na skórkę

  1. Pojedynczy ekran — komponent zarejestrowany pod kluczem z SCREEN_KEYS. W rspack.config.js wystawiasz go (exposes), w configu localStorage mapujesz na klucz (screens: { report: './ReportScreen' }). Host renderuje go w miejscu danej podstrony.
  2. Rama całej strony (layout/chrome) — komponent dostaje children (aktywny ekran) i owija go własnym paskiem/nawigacją/stopką. Wystawiasz np. ./SkinFrame i podajesz w configu layout: './SkinFrame'. Możesz dać samą ramę, same ekrany, albo jedno i drugie. Tutorial: docs/skin-sdk/tutorial-frame.md.
  3. Rozmieszczanie slotów — ciężkie fragmenty z logiką/danymi (np. mapa świata, statystyki zgłoszeń) renderuje host; Ty pobierasz je gotowe przez useSlots() i tylko ustawiasz w layoutcie.

Konwencja read-modeli

Każdy read-model to hook zwracający obiekt metod. Metoda przyjmuje jeden obiekt opcji z polem callback (odbiera odpowiedź socketu) — pozostałe pola lecą do hosta jako data:

const reports = useReports()
reports.list({ page: 1, pageSize: 10, callback: (ret) => {
  if (ret?.error) return
  setIssues(ret.issues) // kształt zwrotki zależy od metody
}})

Hooki danych (jeden na podstronę menu)

| Hook | Podstrona | Metody | | --- | --- | --- | | useArticles | Terminal / Aktualności / Kurier | list, getBySlug, recordView, markKurierRead, listComments, createComment, toggleReaction | | useGptThreads | Harold (GPT) | list, get, create, remove, sendMessage | | useTales | Operacje (opowieści) | list, search, get, getFavorites, getPreferences, togglePreference, join, leave, toggleSubscribe, checkSubscribe | | useInn | Mesa (karczma) | listTales, getMembersCount | | useTown | Metropolia (budynki) | bankSend, innRest, innBuyTravelerKit, healerPlantsList, healerHeal, voltarToolsList, voltarBuy, hallTypes, hallPriceList, hallBuy, workshopPlansList, workshopPlanGet, workshopCraftItem, forgePlansList, forgePlanGet, forgeCraftMaterial, workPerform | | useGuild | Frakcje (gildie) | create, join, list, search, get, sendCrabs, headquartersRestInfo, headquartersRest, leave, getPermissions, specialActions, getProperties, hexmapPopulationTotal, hexmapMappingActivityMonth, provinceInfo, publicStats, hexmapPopulations, hexmapPopulationsByMember, warehouseGet, warehouseDeposit, warehouseYardWithdraw, materialsGet, materialsDonate, materialsDistribute | | useFamily | Dynastie (rody) | create, list, get, getProperties, choseName, invite, acceptInvitation, removeMember, editMember, editSpouse, transferOwner, setPermission, changeDescription, npcAccessGrant, npcAccessRevoke, npcAccessList, depositCrabs, depositInfluencePoints | | useVillages | Kolonie (osady) | found, takeAbandoned, get, list, buildCreate, buildCost, buildUpgrade, buildDemolish, buildMove, buildResetAll, depositCrabs, withdrawCrabs, sendResourcesToGuild, abandon, rebellionResolve, taxesSet, governorAssign, techniqueList, techniqueUpgrade, hexDecorationsUpdate, nameUpdate | | useShop | Zaopatrzenie (sklep) | getOffers, getItems, buyItem, startPayment | | useRanking | Notowania (rankingi) | ranking, rankingExplorer | | useAccountProfile | Profil (konto) | getAccountInfo, getBlockedList, blockUser, unblockUser, linkDiscord, getGlobalStats | | useSettings | Konfiguracja | updateSetting, setInvisibleOnline, updateNewsletterSubscription | | useReports | Zgłoszenia (bugtracker) | list, markAllRead, setIssueNotification |

Read-modele stanu (czytają aktywny stan, bez argumentów)

useShard() · useShardUser() · useCharacter() · useAccount() · usePageData() · useOnlineCharacters() — zwracają bieżące dane świata/postaci/konta (lub null, gdy brak).

Usługi platformy

  • useSnackbar(){ notify }notify([{ severity, message }]) pokazuje powiadomienie hosta.
  • useDialog(){ open, close } — modal hosta (open(config) / close()).
  • useGamePageShell({ title }) — ustawia tytuł/powłokę strony (wołaj w useMemo, jak w przykładzie).

Prymitywy UI (motywowalne komponenty MUI hosta)

PageBox (kontener strony, pełna wysokość) · HexahCharacterSection · AngularPanel · StandardButton (tekst ≤ 16 znaków) · RoundAvatar · DataList (lista wierszy z opisem/akcją) · HexahChip · HexahPagination + HexahPaginationItem. Poza nimi używaj zwykłego @mui/material (Box, Typography, …) — to też instancja hosta. Importuj z barrela (import { Box, Typography } from '@mui/material'), nie z subpath (@mui/material/Box) — host współdzieli jako singleton tylko barrel, więc subpath nie zbuduje się w skórce.

Sloty (host renderuje, skórka rozmieszcza)

import { useSlots, SLOT_KEYS } from '@hexah/skin-sdk'
const slots = useSlots()
const WorldMap = slots[SLOT_KEYS.WORLD_MAP]
return WorldMap ? <WorldMap /> : null   // łagodna degradacja, gdy host nie dostarcza slotu

Zarejestrowane: WORLD_MAP (Mapa Sektora — mapa świata + ruiny), ISSUE_STATS (statystyki zgłoszeń). Zarezerwowane (jeszcze bez komponentu): GAME_PAGE, ISSUE_RICH_CONTENT, ARTICLE_COMMENTS, ARTICLE_ISSUE_GRID.

Stałe i utile

  • SCREEN_KEYS — klucze ekranów: ARTICLE, KURIER, KURIER_REDAKCJA, KURIER_SKRZYNKA, GPT_LIST, GPT_THREAD, REPORT, REPORT_DETAIL, ARTICLE_DETAIL.
  • SLOT_KEYS — klucze slotów (jak wyżej). DEFAULT_TEMPLATE · SKIN_API_VERSION.
  • Utile nawigacji ekranu zgłoszeń (czyste funkcje): buildReportListHref, buildReportDetailHref, buildReportBackHref, parseReportListPage, parseReportStateFilter, parseReportTypeFilter, parseReportMineFilter, parseReportPlannedFilter; style chipów: getStateChipSx, getIssueTypeChipSx.

Pełna mapa „podstrona menu → hook/slot" i decyzje projektowe: docs/skin-sdk/data-hooks.md.

Co generuje

Gotowy projekt skórki:

  • rspack.config.jsModuleFederationPlugin wystawiający ramę i ekrany, paczki współdzielone z hostem (import: false), dev server na :3001 (CORS + allowedHosts).
  • src/SkinFrame.jsx, src/ReportScreen.jsx, src/ArticleScreen.jsx, src/GptListScreen.jsx — gotowe wzorce (rama całej strony + ekrany) na @hexah/skin-sdk.
  • src/examples/ — referencja: wywołania pozostałych read-modeli danych i slotów (do kopiowania).
  • AGENTS.md + CLAUDE.md — zasady i granice dla asystentów AI (import tylko z SDK, brak dostępu do kodu/backendu gry, współdzielone singletony). AI czyta je automatycznie.
  • package.json, .gitignore, README.md z instrukcją podłączenia do środowiska testowego.

Nazwa kontenera Module Federation jest automatycznie sanityzowana z nazwy katalogu do poprawnego identyfikatora.

Licencja

MIT.