# Three ways to build a portal

A front on hub-core, a front of your own on the public catalog and the handshake, or a backend with server keys. What each needs and how to pick.

The API does not care how your pages are made. Three shapes cover what portals do; mix them as you need.

|                   | A front on hub-core                                  | A front of your own                             | A backend with server keys                                       |
| ----------------- | ---------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------- |
| Reads the catalog | `fetchCatalog()`                                     | `GET /v1/catalog/{site}`                        | `GET /v1/server/catalog`                                         |
| Runs a game       | `GameFrame`                                          | an `iframe` and the handshake                   | the same, in the page                                            |
| Players           | `PlayerClient`, guests in `localStorage`             | `POST /v1/sdk/players` in the browser           | `POST /v1/server/players` by your own user id                    |
| Accounts          | magic link, code, password, built in                 | the same routes, your pages                     | your own accounts; a token per visit                             |
| Where it runs     | any JavaScript page                                  | any stack                                       | your servers plus a page                                         |
| Credential        | player token in the browser                          | player token in the browser                     | server key on the server, a token handed to the browser          |
| Guide             | [A front on hub-core](/docs/portals/hub-core-front/) | [A front of your own](/docs/portals/own-front/) | [A backend with server keys](/docs/portals/backend-server-keys/) |

## A front on hub-core

`@filudi/hub-core` is the package filudi.com runs on: the catalog client, the frame with the parent side of the
handshake, the player with its sign-in flows, the SEO helpers, an analytics client, a consent manager. It draws
nothing; you write the pages. Pick it when your front is JavaScript and you want the handshake, the token rules
and the retries done for you.

## A front of your own

The catalog is a public JSON document and the handshake is a few `postMessage` calls. Any stack can read the
catalog, create a guest in the browser, exchange its token for a game token and post `filudi:init` to the
frame. Pick it when your pages are not JavaScript, or when you want nothing from npm.

## A backend with server keys

Your service already knows its users. A server key lets it create a Filudi player per user, with your own user
id as `externalId`, and hand the browser a token for that player. The page then runs `GameFrame` or the plain
handshake as a front does. The key also reads leaderboards with nicknames and the site's statistics. Pick it
when players must be your users, or when a server needs the numbers.

## Mixing

A hub-core front with a backend is the common mix: the backend creates the player and the token; the page gives
the token to `PlayerClient` and lets hub-core do the rest. Nothing in the API ties a site to one shape.

## What every way shares

- The site must be approved and your domain approved before a page on it calls the API or frames a game
  ([Start here](/docs/portals/start-here/)).
- A game is untrusted. The player's own token never enters a frame; the frame gets a game token for one game and
  24 hours. Messages from a frame are claims, never facts.
- Bundles live on the play domain. Never copy one to your origin.
- A player belongs to one site. Players of filudi.com are other players.
