Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
177 commits
Select commit Hold shift + click to select a range
642e81c
ci(ci): move mutation to a release gate on main
systemfsoftware-maker Oct 5, 2026
4924650
ci(ci): run the release gate on github-hosted runners
systemfsoftware-maker Oct 6, 2026
2948df3
fix(ci): refuse a mutation shard whose mutate globs match no files
systemfsoftware-maker Oct 6, 2026
78d23d0
ci(ci): pass the release gate with a notice when there are no decisio…
systemfsoftware-maker Oct 6, 2026
445caba
deps(deps): move to effect 4 stable at exact pins
systemfsoftware-maker Oct 5, 2026
2c50fc8
build(repo): move lint, test and mutation settings to the root
systemfsoftware-maker Oct 5, 2026
330df81
build(repo): declare the effect/http unstable-api opt-in once at the …
systemfsoftware-maker Oct 5, 2026
0f0e072
feat(repo): serve the starter site from one worker
systemfsoftware-maker Oct 6, 2026
94943b0
ci(ci): run the e2e journeys against pnpm dev on linux and macos
systemfsoftware-maker Oct 6, 2026
d40d55f
feat(repo): serve an effect httpapi and its openapi document from the…
systemfsoftware-maker Oct 6, 2026
4b89a65
feat(repo): preview every pull request and deploy production after th…
systemfsoftware-maker Oct 6, 2026
907bdac
feat(repo): call the site worker through effect rpc instead of httpapi
systemfsoftware-maker Oct 7, 2026
ee05623
refactor(repo): delete the hello seed package
systemfsoftware-maker Oct 5, 2026
1531046
feat(repo): enforce a strict nonce csp with trusted types
systemfsoftware-maker Oct 6, 2026
79189b5
build(repo): run all dependency code in the sandbox, systemfsoftware …
systemfsoftware-maker Oct 6, 2026
ba6231b
feat(repo): deploy the site from one command
systemfsoftware-maker Oct 6, 2026
d7244df
ci(ci): deploy production after a passing or skipped mutation job
systemfsoftware-maker Oct 6, 2026
d7daabb
refactor(repo): name the site's procedure health
systemfsoftware-maker Oct 7, 2026
9c2cf14
ci(ci): pin the shared release tooling to main, as main does
systemfsoftware-maker Oct 7, 2026
4e03afd
chore(repo): merge lake1/release-gate into lake1/effect4-pins
systemfsoftware-maker Oct 7, 2026
d2df28a
chore(repo): merge lake1/effect4-pins into lake1/shared-configs
systemfsoftware-maker Oct 7, 2026
57771ea
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
da12fe2
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
5c50136
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
a79a498
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
52f9ee2
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
f16479b
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
90add22
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
d030769
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
9ab2c67
build(repo): take systemfsoftware from main and pnpm-release-manageme…
systemfsoftware-maker Oct 7, 2026
91a262e
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
f686d9c
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
84267bb
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
bc134b6
build(repo): build the sandbox's pnpm store with pnpm-release-managem…
systemfsoftware-maker Oct 7, 2026
64e7664
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
0f81815
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
e4bbb6a
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
6b3c059
ci(ci): run the release gate only on pushes to main
systemfsoftware-maker Oct 7, 2026
3f3a504
chore(repo): refuse to run the journeys when port 1337 is already taken
systemfsoftware-maker Oct 7, 2026
7d78fde
test(repo): drop the plain-fetch tests from the journeys suite
systemfsoftware-maker Oct 7, 2026
6f42d31
chore(repo): restore commitlint.config.ts as main has it
systemfsoftware-maker Oct 7, 2026
93b958c
ci(ci): stop running the journeys against deployed sites
systemfsoftware-maker Oct 7, 2026
e6b6e5e
fix(repo): send every rpc call to the served path in one round trip
systemfsoftware-maker Oct 7, 2026
0bf9f2f
chore(repo): merge lake1/release-gate into lake1/effect4-pins
systemfsoftware-maker Oct 7, 2026
0c6d6d4
chore(repo): merge lake1/effect4-pins into lake1/shared-configs
systemfsoftware-maker Oct 7, 2026
8592598
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
26d34e4
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
2e785c9
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
b97aea8
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
23df623
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
e7a62a1
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
e1631b1
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
e623a94
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
b9854fe
chore(repo): fail commitlint closed when git cannot read the index
systemfsoftware-maker Oct 7, 2026
a88a620
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
f23159b
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
8f0bd08
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
b161b40
ci(ci): let the macos chromium download follow the chrome for testing…
systemfsoftware-maker Oct 7, 2026
a8f0f5e
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
546a80a
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
efa443f
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
95bbb06
chore(repo): merge main into lake1/release-gate
systemfsoftware-maker Oct 7, 2026
42bcefb
chore(repo): merge lake1/release-gate into lake1/effect4-pins
systemfsoftware-maker Oct 7, 2026
7b82915
chore(repo): merge lake1/effect4-pins into lake1/shared-configs
systemfsoftware-maker Oct 7, 2026
cd73a2b
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
98f813e
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
c2283e9
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
5d6c9ff
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
e49e82c
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
fec437a
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
2e139fb
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
ac95465
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
29d1b80
build(repo): drop darwin from the flake and the toolchain
systemfsoftware-maker Oct 7, 2026
9bb82c7
ci(ci): run the journeys on linux only
systemfsoftware-maker Oct 7, 2026
bf35eae
chore(repo): merge lake1/release-gate into lake1/effect4-pins
systemfsoftware-maker Oct 7, 2026
c60d671
chore(repo): merge lake1/effect4-pins into lake1/shared-configs
systemfsoftware-maker Oct 7, 2026
4c03d51
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
71841ad
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
a7cd561
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
49313fc
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
475eb3a
ci(ci): drop the macos chromium install step
systemfsoftware-maker Oct 7, 2026
6f28356
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
770abef
build(repo): drop darwin from the sandbox patch and supported archite…
systemfsoftware-maker Oct 7, 2026
5d97489
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
c7b0037
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
df02b35
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
7767212
chore(repo): drop the journeys busy-port guard
systemfsoftware-maker Oct 7, 2026
4e8a46c
build(repo): show which tests ran in the turbo test logs
systemfsoftware-maker Oct 7, 2026
a1752d1
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
052419b
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
abcce37
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
fbcd048
ci(ci): install for the changeset check through the dev shell's boots…
systemfsoftware-maker Oct 7, 2026
ffd6832
build(repo): drop the root mutation script no workflow calls
systemfsoftware-maker Oct 7, 2026
de168f5
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
4bd4508
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
709fe0b
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
b23a8e2
chore(repo): merge main into lake1/release-gate
systemfsoftware-maker Oct 7, 2026
7793d48
chore(repo): merge lake1/release-gate into lake1/effect4-pins
systemfsoftware-maker Oct 7, 2026
06da6d7
deps(deps): move @effect/tsgo to 0.50.0
systemfsoftware-maker Oct 7, 2026
63786d6
chore(repo): merge lake1/effect4-pins into lake1/shared-configs
systemfsoftware-maker Oct 7, 2026
a919416
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
b223966
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
5a49da0
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
11e7bcb
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
57d57e6
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
15dc522
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
54d6757
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
b1095be
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
b3eef8f
build(repo): take systemfsoftware main 8a4b543
systemfsoftware-maker Oct 7, 2026
69eadec
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
acd1311
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
78d4f58
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
72a10ef
chore(repo): merge main (#35/#36 squashed) into shared-configs
systemfsoftware-maker Oct 7, 2026
b3108ee
chore(repo): merge lake1/shared-configs into lake1/site
systemfsoftware-maker Oct 7, 2026
06bf2ac
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
245828b
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
70b6927
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
f0e18f6
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
d71d019
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
b5fc341
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
4590e7d
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
ca40e7f
chore(repo): merge main (#37 squashed) into site
systemfsoftware-maker Oct 7, 2026
cf82071
chore(repo): merge lake1/site into lake1/stack-ci
systemfsoftware-maker Oct 7, 2026
6f0b766
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
5b6f92a
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
92cd547
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
38d569a
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
2c48bac
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
bd699f3
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
958410c
chore(repo): merge main (#41 squashed) into stack-ci
systemfsoftware-maker Oct 7, 2026
50fb46a
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
933eca2
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
d889287
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
8f75bfb
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
9e4eba2
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
f12dbf1
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
a1aee1d
build(repo): name the changesets versioning strategy, move @effect/ts…
systemfsoftware-maker Oct 7, 2026
380bde4
chore(repo): merge lake1/stack-ci into lake1/delete-hello
systemfsoftware-maker Oct 7, 2026
0bdadbf
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
c854ed4
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
4d82eac
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
14bbe45
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
7fd5b58
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
91b3707
chore(repo): merge main (#42 squashed) into delete-hello
systemfsoftware-maker Oct 7, 2026
fbeabde
chore(repo): merge lake1/delete-hello into lake1/csp
systemfsoftware-maker Oct 7, 2026
83ec64f
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
6ce8253
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
b552fea
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
fc11838
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
cf501f1
chore(repo): merge main (#43 squashed) into csp
systemfsoftware-maker Oct 7, 2026
25385d4
chore(repo): merge lake1/csp into lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
96345ee
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
c8642c9
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
aa61fa9
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
2213fb6
chore(repo): merge main (#49 squashed) into nix-sandbox
systemfsoftware-maker Oct 7, 2026
db08cc5
build(repo): give the dev shell release-tools from the pnpm-release-m…
systemfsoftware-maker Oct 7, 2026
761e5b3
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
7ecec11
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
c686d64
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
2542024
build(repo): take the sandbox from pnpm-release-management unpatched
systemfsoftware-maker Oct 7, 2026
e4614c4
test(repo): drop every sandbox launcher from PATH in the hooks proof
systemfsoftware-maker Oct 7, 2026
942b206
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
0f3702c
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
bfb4d41
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
fb4f8a1
build(repo): take the stryker packages from the stryker-js-effect flake
systemfsoftware-maker Oct 7, 2026
7857171
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
8a7c790
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
da6c43d
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
6dca2fa
revert(repo): take lake1/deploy's merge back off lake1/nix-sandbox
systemfsoftware-maker Oct 7, 2026
8e9e7c6
chore(repo): merge lake1/nix-sandbox into lake1/deploy
systemfsoftware-maker Oct 7, 2026
2a15ef0
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
a9eac20
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
de3319f
chore(repo): merge main (#52 squashed) into deploy
systemfsoftware-maker Oct 7, 2026
8eb7986
chore(repo): merge lake1/deploy into lake1/previews
systemfsoftware-maker Oct 7, 2026
da833eb
chore(repo): merge main (#69 squashed) into previews
systemfsoftware-maker Oct 7, 2026
9b67796
chore(repo): merge lake1/previews into lake1/http-api
systemfsoftware-maker Oct 7, 2026
4b4daf9
chore(repo): merge main (#51 squashed) into http-api
systemfsoftware-maker Oct 7, 2026
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The repository is structured into two workspace roots defined in `pnpm-workspace
└── docs/ # Solutions, tooling decisions, and plans
```

- [`apps/site`](apps/site) — The one Cloudflare Worker: a TanStack Start site defined and deployed with Alchemy.
- [`apps/site`](apps/site) — The one Cloudflare Worker: a TanStack Start site that calls its Worker through effect/rpc (one RpcGroup served at `/api/rpc`, a typed RpcClient in the page), defined and deployed with Alchemy.
- [`apps/site-e2e`](apps/site-e2e) — The end-to-end journeys that run against `pnpm dev` (`pnpm journeys`).

---
Expand Down
19 changes: 19 additions & 0 deletions apps/site-e2e/tests/__fixtures__/browser.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,22 @@ export const visitHomePage = (scenario: string): Effect.Effect<HomePageVisit, ne
(context) => Effect.promise(() => context.close()),
)
})

const healthChecked = (): boolean => document.querySelector('[role=status]')?.textContent.endsWith('checking') === false

export const readWorkerHealth: Effect.Effect<string, never, Chromium> = Effect.gen(function*() {
const origin = yield* siteUrl
const browser = yield* Chromium
return yield* Effect.acquireUseRelease(
Effect.promise(() => browser.newContext()),
(context) =>
Effect.gen(function*() {
const page = yield* Effect.promise(() => context.newPage())
yield* Effect.promise(() => page.goto(`${origin}/`))
yield* Effect.promise(() => page.waitForFunction(healthChecked))
const status = yield* Effect.promise(() => page.getByRole('status').textContent())
return status ?? ''
}),
(context) => Effect.promise(() => context.close()),
)
})
20 changes: 20 additions & 0 deletions apps/site-e2e/tests/health.integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Gherkin, it, makeFeature, Then, When } from '@systemfsoftware/effect-gherkin-spec'

import { ChromiumLive, readWorkerHealth } from './__fixtures__/browser.fixture'

const Feature = makeFeature({ it })

const CHROMIUM_TIMEOUT_MS = 30_000

Feature('Seeing that the Worker is healthy', { timeout: CHROMIUM_TIMEOUT_MS })
.withLayer(ChromiumLive)
.live('a real Chromium loads the page the running Worker serves')
.body(({ scenario }) => {
scenario(
'The home page reports a healthy Worker',
Gherkin.Do.pipe(
When('a visitor opens the home page')('health', () => readWorkerHealth),
Then('the page says the Worker is healthy')((s, expect) => expect(s.health).toBe('Worker health: ok')),
),
)
})
4 changes: 4 additions & 0 deletions apps/site/src/api/health.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as S from 'effect/Schema'

export const Health = S.Struct({ status: S.Literal('ok') })
export type Health = S.Schema.Type<typeof Health>
18 changes: 18 additions & 0 deletions apps/site/src/api/site-rpc-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as Effect from 'effect/Effect'
import { FetchHttpClient, HttpClient, HttpClientRequest } from 'effect/http'
import * as Layer from 'effect/Layer'
import { RpcClient, RpcSerialization } from 'effect/rpc'

import { SITE_RPC_PATH, SiteRpcs } from './site-rpcs'

export const siteClient = RpcClient.make(SiteRpcs)

export const SiteClientProtocol = Layer.effect(RpcClient.Protocol)(
Effect.flatMap(
HttpClient.HttpClient,
(client) => RpcClient.makeProtocolHttp(HttpClient.mapRequest(client, HttpClientRequest.setUrl(SITE_RPC_PATH))),
),
).pipe(
Layer.provide(RpcSerialization.layerJson),
Layer.provide(FetchHttpClient.layer),
)
17 changes: 17 additions & 0 deletions apps/site/src/api/site-rpc-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as Effect from 'effect/Effect'
import { HttpServer } from 'effect/http'
import * as Layer from 'effect/Layer'
import { RpcSerialization, RpcServer } from 'effect/rpc'

import type { Health } from './health.schema'
import { SITE_RPC_PATH, SiteRpcs } from './site-rpcs'

const healthy: Health = { status: 'ok' }

const HealthHandlers = SiteRpcs.toLayer({ health: () => Effect.succeed(healthy) })

export const SiteRpcLive = RpcServer.layerHttp({ group: SiteRpcs, path: SITE_RPC_PATH, protocol: 'http' }).pipe(
Layer.provide(HealthHandlers),
Layer.provide(RpcSerialization.layerJson),
Layer.provide(HttpServer.layerServices),
)
7 changes: 7 additions & 0 deletions apps/site/src/api/site-rpcs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Rpc, RpcGroup } from 'effect/rpc'

import { Health } from './health.schema'

export const SITE_RPC_PATH = '/api/rpc'

export const SiteRpcs = RpcGroup.make(Rpc.make('health', { success: Health }))
17 changes: 17 additions & 0 deletions apps/site/src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import { createFileRoute } from '@tanstack/react-router'
import * as Effect from 'effect/Effect'
import { useEffect, useState } from 'react'

import { siteClient, SiteClientProtocol } from '../api/site-rpc-client'

export const Route = createFileRoute('/')({ component: Home })

const workerHealth = Effect.scoped(Effect.flatMap(siteClient, (client) => client.health())).pipe(
Effect.map((health) => health.status),
Effect.orElseSucceed(() => 'unreachable'),
Effect.provide(SiteClientProtocol),
)

function Home() {
const [health, setHealth] = useState('checking')

useEffect(() => {
void Effect.runPromise(workerHealth).then(setHealth)
}, [])

return (
<main>
<h1>Endgame Starter</h1>
<p>One Cloudflare Worker, built the systemfsoftware way.</p>
<p role='status'>Worker health: {health}</p>
</main>
)
}
10 changes: 9 additions & 1 deletion apps/site/src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import startHandler from '@tanstack/react-start/server-entry'
import * as Effect from 'effect/Effect'
import { HttpRouter } from 'effect/http'
import * as S from 'effect/Schema'

import { SiteRpcLive } from './api/site-rpc-server'
import { SITE_RPC_PATH } from './api/site-rpcs'
import { contentSecurityPolicyOf, CspNonce } from './csp/content-security-policy.schema'

const siteRpc = HttpRouter.toWebHandler(SiteRpcLive)

const isRpcRequest = (request: Request): boolean => new URL(request.url).pathname === SITE_RPC_PATH

const drawNonce = (random: Crypto) =>
S.decodeEffect(CspNonce)(btoa(String.fromCharCode(...random.getRandomValues(new Uint8Array(16)))))

Expand All @@ -21,5 +28,6 @@ const serve = (request: Request, random: Crypto) =>
})

export default {
fetch: (request: Request): Promise<Response> => Effect.runPromise(serve(request, globalThis.crypto)),
fetch: (request: Request): Promise<Response> =>
isRpcRequest(request) ? siteRpc.handler(request) : Effect.runPromise(serve(request, globalThis.crypto)),
}
5 changes: 3 additions & 2 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
// The one repo-wide unstable-API opt-in, exactly `effect/http` (Kiro ruling, 2026-10-05).
// The one repo-wide unstable-API opt-in, exactly `effect/http` (Kiro ruling, 2026-10-05) and
// `effect/rpc` (2026-10-07: the site calls its Worker through effect/rpc, shipped only there).
// Effect 4.0.1 ships HTTP only under the unstable marker; effecttsgo/unstable-api-usage
// (new in @effect/tsgo 0.48.1) errors on it, and global-fetch-in-effect bans the fetch
// alternative. Drop this when @systemfsoftware/tsconfig carries the same opt-in.
"extends": "@systemfsoftware/tsconfig/bundler/dom",
"compilerOptions": {
"plugins": [{ "name": "@effect/language-service", "allowedUnstableApis": ["effect/http"] }]
"plugins": [{ "name": "@effect/language-service", "allowedUnstableApis": ["effect/http", "effect/rpc"] }]
}
}
Loading