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
24 changes: 13 additions & 11 deletions docs/api-versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

The primary "API surface" of this site is the `/open` URL scheme bridge. External consumers (GitHub Action comments, CI scripts, integrations) construct `/open?...` URLs. Breaking changes to accepted parameters must not invalidate old links.

## Current version: v1 (unversioned)
## Current version: v1

All existing `/open` URLs are treated as **v1**. The `v` query parameter is optional and defaults to `1`.
The current URL scheme lives at `/open`. It is treated as v1.

### v1 parameter sets

Expand All @@ -27,21 +27,23 @@ All existing `/open` URLs are treated as **v1**. The `v` query parameter is opti

## Versioning convention

| Version | Path | Status |
| ------- | ---------------- | ------- |
| v1 | `/open` | Current |
| v2+ | `/open?v=2&...` | Future |
New versions live at a new path prefix — not as a query parameter.

| Version | Path | Status |
| ------- | ----------- | ------- |
| v1 | `/open` | Current |
| v2+ | `/v2/open` | Future |

### Rules

1. **Never remove or rename params from an existing version.** Old links must keep working.
2. **Introduce a new version for breaking changes.** Add `v=2` (or higher) when dropping, renaming, or reinterpreting existing params.
2. **Introduce a new path for breaking changes.** Use `/v2/open` (or `/v3/open`, etc.) when dropping, renaming, or reinterpreting existing params.
3. **New optional params are non-breaking.** They may be added to an existing version without a version bump.
4. **The `v` param must be a positive integer string.** Unknown values return an error state with a clear message.
4. **Old version routes stay alive indefinitely.** Do not delete `/open` when `/v2/open` ships.

## Adding a new version

1. Extend the `resolveParams` function in `src/app/open/page.tsx` with a branch for the new version.
1. Create `src/app/v2/open/` with its own `page.tsx` that implements the new param set.
2. Add the new param set to this document under a new `## v<N> parameter sets` section.
3. Keep the old version branch intact — do not delete it.
4. Update the version table above.
3. Update the version table above.
4. Keep the old route untouched — do not modify it.
23 changes: 5 additions & 18 deletions src/app/open/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
import { useEffect, useRef, useState } from "react";
import { type IssueParams, buildWorktreeUrl } from "./issue-card";
import { NoParamsView } from "./no-params-view";
import { UnknownVersionView } from "./unknown-version-view";
import { OpeningView } from "./opening-view";
import { InstallView } from "./install-view";
import { OpenNav, OpenFooter } from "./open-layout";

type Phase =
| "loading" // reading URL params
| "opening" // scheme triggered, awaiting user confirmation
| "success" // user confirmed it opened
| "install" // user says it didn't open → show install guide
| "no-params" // no valid params in URL
| "unknown-version"; // unrecognized v= param
| "loading" // reading URL params
| "opening" // scheme triggered, awaiting user confirmation
| "success" // user confirmed it opened
| "install" // user says it didn't open → show install guide
| "no-params"; // no valid params in URL

function get(sp: URLSearchParams, key: string): string {
const val = sp.get(key);
Expand Down Expand Up @@ -44,23 +42,13 @@ function resolveParams(sp: URLSearchParams): IssueParams | null {
return { kind: "github", owner, repo, issue };
}

const SUPPORTED_VERSIONS: string[] = ["1"];

export default function OpenPage() {
const [phase, setPhase] = useState<Phase>("loading");
const [params, setParams] = useState<IssueParams | null>(null);
const [urlVersion, setUrlVersion] = useState<string>("1");
const schemeTriggered = useRef(false);

useEffect(() => {
const sp = new URLSearchParams(window.location.search);
const raw = sp.get("v");
const v = raw !== null ? raw : "1";
setUrlVersion(v);
if (!SUPPORTED_VERSIONS.includes(v)) {
setPhase("unknown-version");
return;
}
const p = resolveParams(sp);
if (!p) { setPhase("no-params"); return; }
setParams(p);
Expand All @@ -83,7 +71,6 @@ export default function OpenPage() {
<main className="open-main">
<div className="open-content">
{phase === "no-params" && <NoParamsView />}
{phase === "unknown-version" && <UnknownVersionView version={urlVersion} />}
{phase === "loading" && (
<div className="loading-center">
<div className="spinner-lg anim-spin" />
Expand Down
23 changes: 0 additions & 23 deletions src/app/open/unknown-version-view.tsx

This file was deleted.

Loading