Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .changeset/auth-cookie-prefix.md

This file was deleted.

41 changes: 0 additions & 41 deletions .changeset/cinematic-views.md

This file was deleted.

36 changes: 0 additions & 36 deletions .changeset/react-app-shell-and-ui-kit.md

This file was deleted.

20 changes: 0 additions & 20 deletions .changeset/sequelize-declare-attributes.md

This file was deleted.

121 changes: 121 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,126 @@
# seamless-templates

## 0.10.0

### Minor Changes

- 43239a8: feat(templates): name auth cookies per application

Both API starters (`express` and `fastify`) now read `AUTH_COOKIE_PREFIX` and
derive `accessCookieName`, `refreshCookieName`, `registrationCookieName` and
`preAuthCookieName` from it, passing all four to the auth server and the matching
`cookieName` to `requireAuth`.

Cookies are scoped by host and ignore the port, so two Seamless applications
served from the same host share one cookie jar and overwrite each other's
session. Signing into one signs you out of the other. That is invisible in
production, where each application has its own domain, and unavoidable in
development, where they are all on localhost.

The guard has to be told the name as well as the server. Left on its default it
looks for `seamless-access` while the server has issued something else, and every
request 401s while holding a valid session.

The default prefix is `seamless-`, which reproduces the names
`@seamless-auth/express` already uses, so an existing project upgrades without
logging anyone out. `.env.example` and the README table in both starters document
the variable.

Note for anyone scaffolding several applications on one host: the variable is
read but not yet set by `template.json`, so a project created by the CLI still
gets the default names and still shares a cookie jar with its neighbours. Set
`AUTH_COOKIE_PREFIX` in the generated `.env` to separate them.

- 1dca3d9: feat(templates): give each style its own voice, and replace generated artwork

The shared React kit gains a font token per role (`--app-font-display`,
`--app-font-body`, `--app-font-label`), a `Vista` backdrop component, and
full-viewport views with scroll-driven transitions. Nothing is downloaded: the
tokens name system stacks only, so the lever is which of the faces an OS already
ships each style reaches for.

`Vista` is a fixed stack of four layers behind the page: two concentrated light
sources, concentric rings, a slow conic sweep, and a ruled grid. Every layer is a
gradient built from the application's own two colours, so one component still
comes out looking like that application, and a style that wants no backdrop sets
each layer to `none`. It also carries the page background, which is why the shell
mounts it once and content above it needs `above-vista`.

Each region a `Screen` renders is now a view. A style decides whether that means a
block of an ordinary scrolling page or a full height of the window that the page
settles on, so the same markup is a working tool or an experience without being
written twice. The reveal animation is ranged over `cover` rather than `entry`,
because a view as tall as the window never finishes entering and an entry range
strands it part-way through with its content invisible. Both scroll-driven
behaviours sit behind `@supports` and `prefers-reduced-motion`, and degrade to
visible.

This replaced the per-application SVG motif. A drawing had to be invented on every
run, came out differently each time, and was reliably the least convincing thing
on the screen. `Screen`, `AuthFrame` and `EmptyState` no longer accept a `motif`
prop, and the prop is gone from `types.ts`.

Also in this change: the `board` archetype now renders a banded header, like every
archetype except `feed`.

Breaking for anyone consuming the kit directly: passing `motif` to `Screen`,
`AuthFrame` or `EmptyState` is now a type error, and the `--app-motif-*` tokens no
longer exist. Generators that write a `Motif` component alongside a screen need
updating in step, since the backdrop now belongs to the theme rather than to the
subject.

- a723535: feat(templates): give both React starters a design token layer, an app shell, and a shared UI kit

Both React starters (`react-vite` and `react-oauth`) now take every colour, radius,
shadow, duration and type size from custom properties declared in `src/index.css`.
No component carries a literal colour, so the whole application rethemes from one
block, and the tokens respond to the OS colour scheme without any `dark:` variants
in markup.

On top of that:

- `layouts/Layout.tsx` and `components/Navbar.tsx` are a persistent sidebar shell
with full-width content, replacing the centered navbar over a centered column.
The sidebar reads its own `shell` token family, so a theme can put a deep
sidebar against light content.
- `src/components/kit` is a set of composable, token-styled pieces: `Screen`
(which arranges a page by named archetype), `AuthFrame`, `StatRow`,
`InlineCreateForm`, `RecordList`, `RecordCard`, `DataTable`, `RankedTable`,
`ActionCard`, `EmptyState`, `Field`, `Toggle`, `PrimaryButton`, and a
`useCollection` hook that loads a collection and creates optimistically.
`kit/Example.tsx` is a worked screen built from them.
- Each starter's own pages are composed from the kit and use the tokens
throughout. The OAuth starter keeps its provider-driven sign-in, its callback
route and its own nav entries.

The tokens, the shell layout and the kit are identical in both starters and are
kept that way mechanically: they are edited in `shared/react-app` and copied into
each template by `npm run sync:shared`, and `npm run validate` fails when a copy
has drifted. This repository is not published to npm and the CLI copies exactly one
template directory into a new project, so each template has to carry its own copy
rather than importing a package.

Existing projects are unaffected until they scaffold again.

### Patch Changes

- 7b278e5: fix(templates): declare Sequelize model attributes instead of using public class fields

The `User` model in both API starters (`express` and `fastify`) declared its
attributes as `public id!: string`. Sequelize installs its attribute getters and
setters on the prototype, and a public class field is emitted as an own property
initialised to undefined, which shadows them: `user.id` reads undefined while
`user.get("id")` returns the row's value. Sequelize warns about this at model
init. `declare` emits no field at all, so the accessors survive.

Whether the field is emitted depends on `useDefineForClassFields`, which follows
`target`. Both starters compile at `target: ES2020`, where the field is erased
and the shadowing does not occur, so this is a guard rather than a repair of
behaviour anyone is seeing today. It matters because the guard is what keeps a
later `target` bump from silently breaking every model: at ES2022 the same code
returns undefined for every attribute, and the first symptom is a query built
with an undefined parameter on a handler that filters by `req.appUser.id`.

## 0.9.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "seamless-templates",
"version": "0.9.0",
"version": "0.10.0",
"private": true,
"description": "Frontend and API starter templates for Seamless Auth, consumed by the Seamless CLI",
"homepage": "https://github.com/fells-code/seamless-templates#readme",
Expand Down