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
64 changes: 64 additions & 0 deletions .github/workflows/deploy-mindmap-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Deploy mindmap to GitHub Pages

on:
pull_request:
paths:
- "prototype-mindmap/**"
- ".github/workflows/deploy-mindmap-pages.yml"
workflow_dispatch:

permissions:
contents: read

jobs:
build:
name: Build Pages artifact
runs-on: ubuntu-latest
defaults:
run:
working-directory: prototype-mindmap
steps:
- name: Require main for a deployment
if: ${{ github.event_name == 'workflow_dispatch' && github.ref != 'refs/heads/main' }}
working-directory: .
run: |
echo "Mindmap Pages deployments must run from main." >&2
exit 1
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
cache-dependency-path: prototype-mindmap/package-lock.json
- run: npm ci
- name: Production build
run: npm run build:pages
- name: Verify Pages artifact
run: npm run verify:pages
- name: Configure Pages
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
uses: actions/configure-pages@v5
- name: Upload Pages artifact
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
uses: actions/upload-pages-artifact@v4
with:
path: prototype-mindmap/dist

deploy:
name: Deploy Pages artifact
if: ${{ github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
needs: build
runs-on: ubuntu-latest
concurrency:
group: mindmap-pages
cancel-in-progress: false
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
17 changes: 11 additions & 6 deletions .github/workflows/mindmap-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ on:
- "backend/src/__tests__/openaiProxy.test.ts"
- "scripts/get_env.py"
- "scripts/test_get_env.py"
- ".github/workflows/deploy-mindmap-pages.yml"
- ".github/workflows/mindmap-tests.yml"
push:
branches: [main, mindmap-main]
Expand All @@ -27,6 +28,7 @@ on:
- "backend/src/openaiProxy.ts"
- "backend/src/toolGrants.ts"
- "scripts/get_env.py"
- ".github/workflows/deploy-mindmap-pages.yml"
- ".github/workflows/mindmap-tests.yml"

permissions:
Expand Down Expand Up @@ -79,19 +81,22 @@ jobs:
- name: Eval typecheck
run: npm run eval:typecheck
- name: Production build
env:
VITE_BACKEND_URL: https://ci.invalid/api
VITE_REQUIRE_LAUNCH: "true"
run: npm run build
run: npm run build:pages
- name: Verify Pages artifact
run: npm run verify:pages
- name: Install Chromium
run: npx playwright install --with-deps chromium
- name: Playwright mocked smoke
- name: Playwright development smoke
run: npm run test:e2e
- name: Playwright production artifact smoke
run: npm run test:e2e:pages:built
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@v6
with:
name: mindmap-playwright-report
path: prototype-mindmap/playwright-report
path: |
prototype-mindmap/playwright-report
prototype-mindmap/playwright-report-pages
if-no-files-found: ignore
retention-days: 7
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ MANIFEST

# Environments
.env*
!prototype-mindmap/.env.production
.venv
env/
venv/
Expand Down
2 changes: 2 additions & 0 deletions prototype-mindmap/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_BACKEND_URL=https://app.thoughtful-ai.com/api
VITE_REQUIRE_LAUNCH=true
2 changes: 2 additions & 0 deletions prototype-mindmap/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules/
dist/
playwright-report-pages/
test-results/
*.log
tsconfig.tsbuildinfo
eval/runs/
76 changes: 73 additions & 3 deletions prototype-mindmap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,86 @@ is ignored when `PROD` is set, so a misconfigured deploy environment cannot ship
ungated bundle. A grant present in the URL is processed in every mode.

`VITE_BACKEND_URL` is **required** for production builds and throws at startup if
missing. Development and test builds fall back to `http://localhost:8000/api`; a
production bundle carrying that fallback would point every user's browser at their
own machine.
missing. The committed `.env.production` contains the public Pages backend and
launch requirement; Vite loads it automatically on production builds.
Development and test builds fall back to `http://localhost:8000/api`; a production
bundle carrying that fallback would point every user's browser at their own machine.

The Writing Tools registry uses `VITE_MINDMAP_TOOL_URL`. Its development default
is `http://localhost:5181/`; its production default is
`https://mindmap.thoughtful-ai.com/`. The existing Playwright smoke suite
continues to use Vite's development server at port 4173, so production-gate
verification remains a separate build check.

## GitHub Pages production build

GitHub Pages hosts only the compiled browser files. Authentication, launch
grants, document snapshots, OpenAI proxying, and token persistence remain on
the Writing Tools backend. The Pages build receives public configuration only;
never provide an OpenAI key, Better Auth secret, database credential, or
`wtk_` token to this build.

Build and verify the exact production artifact with:

```sh
npm run build:pages
npm run verify:pages
npm run test:e2e:pages
```

The normal `test:e2e:pages` command rebuilds and verifies first, so it cannot
silently exercise a stale `dist`; CI uses `test:e2e:pages:built` after its
existing production build. `verify:pages` requires an HTTPS backend, checks that
`dist/index.html` and the configured backend are present, and refuses published
`.env` files. The source
retains its intentional development fallback string, so the production
Playwright suite—not a raw string scan—proves that the built app actually sends
exchange and provider requests to the configured HTTPS backend. It serves that
same `dist` directory with `vite preview`; the normal `test:e2e` command
continues to exercise the development server.

Every supported entry point is the site root with launch state in the URL
fragment. Fragments are handled entirely in the browser and are not sent to
GitHub Pages, so this build has no path-based SPA route and needs no `404.html`
fallback.

The workflow at `.github/workflows/deploy-mindmap-pages.yml` builds on relevant
pull requests but cannot publish them. A deployment is a manual workflow run
from `main`; selecting any other ref fails without uploading an artifact.
Running the workflow does not configure the repository's Pages settings, DNS,
the production backend, or the Writing Tools tile.

Before the first deployment:

1. Merge and deploy the grant-origin work from
[#579](https://github.com/AIToolsLab/writing-tools/pull/579), refresh the
Pages branch from `main`, and unskip the `wt_api` production smoke. It must
prove that exchange and provider requests use the launching platform's API,
not the build-time fallback.
2. Land the tool/device-client split and confirm production allowlists contain
the exact compiled taskpane client plus `mindmap`.
3. Configure this repository's Pages source as **GitHub Actions** and claim
`mindmap.thoughtful-ai.com`.
4. Ask the DNS owner to create exactly:

```text
CNAME mindmap.thoughtful-ai.com → aitoolslab.github.io
```

Do not append `/writing-tools` or any repository name. DNS cannot carry a
URL path; GitHub selects the repository from the claimed custom domain and
the request host.
5. Wait for DNS and TLS provisioning, then enable **Enforce HTTPS**. GitHub
documents that DNS propagation and availability of HTTPS enforcement can
each take up to 24 hours, so an initially unavailable HTTPS launch is not
by itself an application failure.
6. Run the real Word and Google Docs off-origin checks before exposing the
tile.

Tile rollout belongs to the separate Writing Tools add-in build.
`VITE_ENABLE_MINDMAP_TOOL` is read by
`frontend/src/pages/tools/index.tsx`; it is not part of this Pages build.

## Design principle: typed proposals with deterministic consequences

- **Enforcement (code, not configurable):** a mirror must pass validation before
Expand Down
21 changes: 21 additions & 0 deletions prototype-mindmap/e2e-pages/global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { fileURLToPath } from "node:url";
import { preview } from "vite";

export default async function startPagesPreview(): Promise<(() => Promise<void>) | undefined> {
if (process.env.PLAYWRIGHT_SKIP_SERVER) return undefined;

const port = Number(process.env.PLAYWRIGHT_PAGES_PORT ?? 4174);
const root = fileURLToPath(new URL("..", import.meta.url));
const server = await preview({
root,
preview: {
host: "127.0.0.1",
port,
strictPort: true,
},
});

return async () => {
await server.close();
};
}
Loading