Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7f4d786
Port app to Cloudflare Workers
bebraw Apr 3, 2026
24c8662
Document Cloudflare deploy and remove legacy deployment files
bebraw Apr 3, 2026
021ec19
Pin npm dependency versions
bebraw Apr 3, 2026
2ed3c81
Remove redundant generate scripts
bebraw Apr 3, 2026
8d8b89d
Remove dead template and utility code
bebraw Apr 3, 2026
90ed34b
Remove unused utility generators
bebraw Apr 3, 2026
4e1e603
Restore startup rebuild hooks
bebraw Apr 3, 2026
ad5f892
Update safe dependency versions
bebraw Apr 3, 2026
4940091
Add API end-to-end tests
bebraw Apr 3, 2026
f78ca01
Upgrade utility dependencies
bebraw Apr 3, 2026
0d0956b
Upgrade Express runtime dependencies
bebraw Apr 3, 2026
1a286bf
Upgrade GraphQL dependencies
bebraw Apr 3, 2026
0f95e6d
Remove lodash dependency
bebraw Apr 3, 2026
3bb215f
Remove Express runtime
bebraw Apr 3, 2026
857d2ca
Trim maintenance scripts
bebraw Apr 3, 2026
3af7b9b
Fix TypeScript project config
bebraw Apr 3, 2026
b1c131e
Protect API routes with token header
bebraw Apr 3, 2026
e9b4a2f
Add quality gate script
bebraw Apr 3, 2026
e2ce28e
Tighten media access and worker token config
bebraw Apr 3, 2026
27208b0
Upgrade to TypeScript 6
bebraw Apr 3, 2026
0ba9fd1
Remove redundant helper dependencies
bebraw Apr 3, 2026
c8da9bd
Harden Cloudflare asset and worker handling
bebraw Apr 3, 2026
b75371c
Bump project to Node 24
bebraw Apr 3, 2026
5f179c0
Remove stale package main entry
bebraw Apr 3, 2026
3d2df76
Update local development documentation
bebraw Apr 3, 2026
2a98c3c
Upgrade ical-generator
bebraw Apr 3, 2026
228031a
Remove Node runtime fallback
bebraw Apr 3, 2026
7414bac
Trim redundant README notes
bebraw Apr 3, 2026
be50972
Port index generator to TypeScript
bebraw Apr 3, 2026
0e145df
Align logging with Cloudflare Workers
bebraw Apr 3, 2026
09176b3
Replace generated barrels with content registry
bebraw Apr 3, 2026
6dda863
Remove attendee CSV support
bebraw Apr 3, 2026
5a20766
Pin Wrangler as a local dev dependency
bebraw Apr 3, 2026
4abc28b
Remove stale Tito configuration mentions
bebraw Apr 3, 2026
6cbaf4a
Drop legacy calendar route and stale config docs
bebraw Apr 3, 2026
b446f38
Harden Worker validation and local CI
bebraw Apr 3, 2026
f0436f4
Replace type-graphql runtime schema
bebraw Apr 3, 2026
1ae53db
Remove type-graphql and reflection stack
bebraw Apr 3, 2026
0cebbec
Move conference series data out of resolver path
bebraw Apr 3, 2026
376e60b
Rename local API test and drop stale schema path
bebraw Apr 3, 2026
3b0c3da
Inline schema entrypoint
bebraw Apr 3, 2026
41d17d0
chore: Allow access to calendar
bebraw Apr 3, 2026
765cebd
chore: Split up docs
bebraw Apr 3, 2026
6acdd7e
fix: Fix worker name
bebraw Apr 3, 2026
9fe68b4
chore: Add a note
bebraw Apr 3, 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
8 changes: 8 additions & 0 deletions .assetsignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*
!media/
!media/**/
!media/**/*.ico
!media/**/*.jpeg
!media/**/*.jpg
!media/**/*.png
!media/**/*.svg
3 changes: 2 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
TITO_TOKEN=<get from https://api.tito.io/>
# Required API token for all non-media routes. Send it in the `TOKEN` header.
TOKEN=
34 changes: 34 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI

on:
pull_request:
push:
branches:
- main

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
quality-fast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: package.json
cache: npm

- name: Install dependencies
shell: bash
run: npm ci

- name: Run fast quality gate
shell: bash
run: npm run quality:gate:fast
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ node_modules/
logs/
attendees/
build/
.wrangler/
.wrangler-dry-run/
.npm/
server/types/
media/scripts/
utils/*.csv
Expand All @@ -13,4 +16,3 @@ utils/diversity-*
.env
.fusebox
.scripts

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-exact=true
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v22
v24.14.1
41 changes: 41 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Development

## Local development

Use the Worker runtime for local development:

1. Use Node.js 24, for example with `nvm use`.
2. Install dependencies with `npm install`.
3. Authenticate Wrangler with `npx wrangler login`.
4. Start the Worker locally with `npm run cf:dev`.

Wrangler uses [wrangler.jsonc](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/wrangler.jsonc) and serves public image assets from the repository through the static-assets configuration in [.assetsignore](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/.assetsignore).

Useful local endpoints:

- `http://localhost:8787/calendar-2026.ics`
- `http://localhost:8787/media/people/kenw.jpg`

## Quality checks

Before deploying or after larger refactors, run:

```sh
npm run quality:gate
```

That executes the checked-in CI workflow locally through `agent-ci`.

If you only want the direct checks without the local CI wrapper, run:

```sh
npm run quality:gate:fast
```

## Environment variables

The application requires a `TOKEN` value at runtime for protected Worker-handled routes. `/calendar-2026.ics` and `/media/*` are public.

For local Wrangler development, provide the values in `.dev.vars` or `.env`. The example in [.env.template](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/.env.template) is:

- `TOKEN` for authenticating protected Worker-handled routes through a `TOKEN` request header
1 change: 0 additions & 1 deletion Procfile

This file was deleted.

57 changes: 42 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
# GraphQL API for TOSKA conferences

Simple GraphQL API for our conferences:
This repository serves conference data over GraphQL and exposes a small set of supporting routes:

To see the query API:
- `/graphql`
- `/ping`
- `/calendar-2026.ics`
- `/media/*`

1. `NODE_ENV="development" npm start`
2. `http://localhost:3000/graphql` or `http://localhost:3000/calendar-2022.ics` (calendar)
Development setup lives in [DEVELOPMENT.md](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/DEVELOPMENT.md).

## Asset Designer
## Deploying to Cloudflare

You can access the asset designer through `http://localhost:3000/asset-designer`.
### Prerequisites

## Image Processing
- A Cloudflare account with Workers enabled
- Node.js 24 and npm installed
- Dependencies installed with `npm install`
- Wrangler authenticated with `npx wrangler login`
- A `TOKEN` secret configured for the Worker

There's no special image processing in place at the moment.
### Configure the Worker

> You can access images through `http://localhost:3000/media`. Example: `http://localhost:3000/media/people/kenw.jpg`.
The project already includes a Worker entrypoint at [worker/index.ts](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/worker/index.ts) and a Wrangler configuration at [wrangler.jsonc](/Users/juhovepsalainen/Projects/future-frontend/graphql-api/wrangler.jsonc).

## Webhooks
The current configuration:

See the webhooks below.
- runs a fetch-native request handler in Cloudflare Workers
- routes `/graphql`, `/ping`, and `/calendar-2026.ics` through the Worker
- serves only image files under `/media/*` from static assets in the repository
- reuses a cached Worker handler per isolate instead of rebuilding the schema on each request
- emits structured console logs with Cloudflare Workers observability enabled

### Heroku to Netlify
If you want a different Worker name, change the `name` field in `wrangler.jsonc`.
Set the runtime token before deploy with `npx wrangler secret put TOKEN`.
For local Worker development, provide the same value in `.dev.vars` or `.env` so Wrangler can load it into the Worker `env` bindings.

The API has been connected to the site using a webhook so that it builds whenever the API changes:
### Deploy

- `heroku config:set REBUILD_SITES=<Netlify urls separate by comma go here> -a react-finland-api`
Run:

> Remember to run the server in production mode. That will enable site rebuilding hook!
```sh
npm run cf:deploy
```

That executes `npx wrangler deploy` using the checked-in configuration.

### Verify after deploy

Check these endpoints on the deployed domain:

- `/graphql`
- `/ping`
- `/calendar-2026.ics`
- `/media/people/kenw.jpg`

Note that the first two require a `TOKEN` header.
6 changes: 0 additions & 6 deletions add-compiled-to-git.sh

This file was deleted.

3 changes: 0 additions & 3 deletions app.json

This file was deleted.

6 changes: 3 additions & 3 deletions content/freezing-edge-2020/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Conference } from "../../server/schema/Conference";
import * as locations from "../locations";
import * as people from "../people";
import * as allSponsors from "../sponsors";
import { locations } from "../generated";
import { people } from "../generated";
import { sponsors as allSponsors } from "../generated";
import schedules from "./schedules";

const partners = [allSponsors.reactFinland, allSponsors.survivejs];
Expand Down
5 changes: 2 additions & 3 deletions content/freezing-edge-2020/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Schedule } from "../../server/schema/Schedule";
import { SessionType } from "../../server/schema/Session";
import * as locations from "../locations";
// import * as people from "../people";
import * as talks from "./talks";
import { freezingEdge2020Talks as talks, locations } from "../generated";
// import { people } from "../generated";

const presentationDay: Schedule = {
day: "2020-06-01",
Expand Down
Empty file.
7 changes: 0 additions & 7 deletions content/freezing-edge-2020/talks/index.ts

This file was deleted.

6 changes: 3 additions & 3 deletions content/future-frontend-2023/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Conference } from "../../server/schema/Conference";
import * as locations from "../locations";
import * as people from "../people";
import * as allSponsors from "../sponsors";
import { locations } from "../generated";
import { people } from "../generated";
import { sponsors as allSponsors } from "../generated";
import schedules from "./schedules";

const partners = [
Expand Down
4 changes: 2 additions & 2 deletions content/future-frontend-2023/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Schedule } from "../../server/schema/Schedule";
import { Level, SessionType } from "../../server/schema/Session";
import * as locations from "../locations";
import * as people from "../people";
import { locations } from "../generated";
import { people } from "../generated";

const monday: Schedule = {
day: "2023-06-05",
Expand Down
6 changes: 3 additions & 3 deletions content/future-frontend-2024/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Conference } from "../../server/schema/Conference";
import * as locations from "../locations";
import * as people from "../people";
import * as allSponsors from "../sponsors";
import { locations } from "../generated";
import { people } from "../generated";
import { sponsors as allSponsors } from "../generated";
import schedules from "./schedules";

const partners = [
Expand Down
4 changes: 2 additions & 2 deletions content/future-frontend-2024/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Schedule } from "../../server/schema/Schedule";
import Keyword from "../../server/schema/keywords";
import { Level, SessionType } from "../../server/schema/Session";
import * as locations from "../locations";
import * as people from "../people";
import { locations } from "../generated";
import { people } from "../generated";

/*
const monday: Schedule = {
Expand Down
6 changes: 3 additions & 3 deletions content/future-frontend-2025/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Conference } from "../../server/schema/Conference";
import * as locations from "../locations";
import * as people from "../people";
import * as allSponsors from "../sponsors";
import { locations } from "../generated";
import { people } from "../generated";
import { sponsors as allSponsors } from "../generated";
import schedules from "./schedules";

const partners = [
Expand Down
4 changes: 2 additions & 2 deletions content/future-frontend-2025/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Schedule } from "../../server/schema/Schedule";
import Keyword from "../../server/schema/keywords";
import { Level, SessionType } from "../../server/schema/Session";
import * as locations from "../locations";
import * as people from "../people";
import { locations } from "../generated";
import { people } from "../generated";

// All times are given in GMT+0 (adjusted to GMT+3 at the frontend)
const monday: Schedule = {
Expand Down
6 changes: 3 additions & 3 deletions content/future-frontend-2026/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Conference } from "../../server/schema/Conference";
import { Contact } from "../../server/schema/Contact";
import * as locations from "../locations";
import * as people from "../people";
import * as allSponsors from "../sponsors";
import { locations } from "../generated";
import { people } from "../generated";
import { sponsors as allSponsors } from "../generated";
import schedules from "./schedules";

const partners: Contact[] = [
Expand Down
4 changes: 2 additions & 2 deletions content/future-frontend-2026/schedules.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Schedule } from "../../server/schema/Schedule";
import Keyword from "../../server/schema/keywords";
import { Level, SessionType } from "../../server/schema/Session";
import * as locations from "../locations";
import * as people from "../people";
import { locations } from "../generated";
import { people } from "../generated";

// All times are given in GMT+0 (adjusted to GMT+3 at the frontend)
const monday: Schedule = {
Expand Down
Loading
Loading