Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .env.1password
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 1Password-backed development environment. Contains REFERENCES, not secrets,
# so this file is committed. Run the app through `op run` to expand them:
#
# npm run dev:op # = op run --env-file=.env.1password -- next dev
#
# Requires 1Password CLI 2.x, unlocked (desktop-app integration or `op signin`).
# Values here are injected into the shell environment, and Next.js does NOT let
# .env.local override an already-set shell variable (see @next/env processEnv),
# so this reference wins over any stale key sitting in .env.local.
TYPESAFE_API_KEY="op://Development/Jev API Key/password"

# Optional: override the Jev model id (defaults to jev-latest).
# JEV_MODEL=jev-latest
83 changes: 83 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Runs the checks listed in CONTRIBUTING.md on every pull request and on main.
#
# Node: the manifest pins neither Node nor a package manager, so CI uses the
# version this project is developed against. Next 16 requires >= 20.9.
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

# A new push to the same branch supersedes an in-flight run.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: "24"

jobs:
checks:
name: unit, types, lint, build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v7
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm

- run: npm ci

- name: Unit tests
run: npm test

- name: Types
run: npm run typecheck

- name: Lint
run: npm run lint

- name: Production build
run: npm run build

e2e:
name: end-to-end (Playwright)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: actions/setup-node@v7
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm

- run: npm ci

# Keyed on the lockfile, so the cache is rebuilt when Playwright's version moves.
- name: Cache Playwright browsers
uses: actions/cache@v6
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}

- name: Install Chromium
run: npx playwright install --with-deps chromium

# playwright.config.ts builds the app and serves it with the key unset, so
# the suite runs in demo mode and needs no credentials.
- name: End-to-end tests
run: npm run e2e

- name: Upload report
if: failure()
uses: actions/upload-artifact@v7
with:
name: playwright-report
path: playwright-report/
Comment on lines +77 to +82
retention-days: 7
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ web_modules/
.env.*
!.env.example
!.env.local.example
!.env.1password

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ npm run build
npm run e2e # Playwright, builds and serves the app in demo mode
```

GitHub Actions runs all of these on every pull request and on `main` (`.github/workflows/ci.yml`): one job for the unit tests, types, lint and build, and one for the end-to-end suite. The end-to-end job needs no credentials, since the suite serves the app with the key unset and routes through the simulator. A failing run uploads its Playwright report as an artifact.

Automated tests should not need a real API key. For UI changes, exercise model/tool modes, option validation, threshold changes, fallback visibility, key removal, storage/export behavior, keyboard controls, themes, and narrow screens.

Open a pull request explaining the intended behavior, why it preserves the execution boundary, which tests ran, and any unverified behavior. Include a before/after example or screenshot when useful. A proposed GitHub topic change in `repository-metadata.json` still needs a separate authorized repository-settings update.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,31 @@ cp .env.local.example .env.local
# Edit .env.local and set TYPESAFE_API_KEY, then restart the dev server.
```

### 1Password-backed key (recommended)

Keep the key in 1Password and run the app through `op run`, so no secret ever
lands in a file:

```bash
npm run dev:op
```

`.env.1password` is committed and holds a **reference**, not a secret:
`TYPESAFE_API_KEY="op://Development/Jev API Key/password"`. `op run` expands it
into the process environment at launch. Requires 1Password CLI 2.x, unlocked
(desktop-app integration or `op signin`).

Verify it took effect — `live` reports whether the SERVER has a key:

```bash
curl -s http://localhost:3000/api/route
# {"live":true} ({"live":false} means demo mode)
```

A shell-provided variable is not overridden by `.env.local` (`@next/env`'s
`processEnv` only fills keys absent from the initial environment), so this path
wins over any stale key left in `.env.local`.

The browser calls this app's `/api/route` endpoint. The server forwards live evaluations to `POST https://api.typesafe.ai/v1/systemone` using `jev-latest`. Jev answers typed questions; it does not generate the code that executes a route.

### Bring your own key and privacy
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
"name": "typesafe-router",
"version": "0.1.0",
"private": true,
"description": "Jev Tool & Model Router — Jev decides, your code executes.",
"description": "Jev Tool & Model Router \u2014 Jev decides, your code executes.",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint",
"test": "vitest run",
"e2e": "playwright test",
"typecheck": "next typegen && tsc --noEmit"
"typecheck": "next typegen && tsc --noEmit",
"dev:op": "op run --env-file=.env.1password -- next dev",
"start:op": "op run --env-file=.env.1password -- next start"
},
"dependencies": {
"next": "16.3.5",
Expand Down
Loading