Polyglot repository layout (Python + web viewer)¶
This repository is Python-first: the package, CLI, tests, and Makefile live at the repo
root. The GI/KG viewer (RFC-062) is a separate
Node project under web/gi-kg-viewer/.
Treat them as two toolchains that share one git tree, not one unified npm workspace (by design).
Quick comparison¶
| Area | Location | Install / run |
|---|---|---|
| Python app (CLI, pipeline, FastAPI server) | Repo root (pyproject.toml, src/) |
python3 -m venv .venv, source .venv/bin/activate, make init or pip install -e ".[…]" |
| Viewer UI (Vue 3 + Vite + TypeScript) | web/gi-kg-viewer/ (package.json) |
cd web/gi-kg-viewer && npm install; npm run dev / npm run build / npm run test:* |
End-to-end viewer (API + built SPA in one process): install [dev], build dist/ under
web/gi-kg-viewer, then python -m podcast_scraper.cli serve --output-dir …. See
Server Guide and web/gi-kg-viewer/README.md.
Environment files (two purposes)¶
| File | Purpose |
|---|---|
config/examples/.env.example |
Copy to repo root .env for Python: API keys, CACHE_DIR, logging, optional PODCAST_SCRAPER_*, etc. (CONFIGURATION.md; twelve-factor config). |
web/gi-kg-viewer/.env.example |
Copy to web/gi-kg-viewer/.env for Vite only: VITE_DEFAULT_CORPUS_PATH (pre-fills the shell corpus path for Graph tab auto-load — API corpus path only; offline file-picker loads skip topic_clusters.json fetch and sibling merge), VITE_CLUSTER_SIBLING_EPISODE_CAP (Graph tab topic-cluster sibling auto-load), VITE_DEFAULT_GRAPH_LENS_DAYS (Graph time-lens lower bound on first auto-load: positive integer = "last N days" — production default 7; 0 or empty = "all time", used by the stack-test viewer build so static fixture publish dates aren't filtered out). Vite loads .env* next to the app by default. |
Root .gitignore already ignores .env, .env.local, and similar patterns so secrets are not
committed from either location.
Git ignores (viewer)¶
Node / Vite / Playwright artifacts for the viewer (node_modules/, dist/, Playwright
reports, log files, etc.) are listed under web/gi-kg-viewer/ in the repository root
.gitignore. There is no
separate web/gi-kg-viewer/.gitignore.
Makefile targets (run from repo root)¶
All of these assume an activated Python venv when Python is involved.
The viewer directory is WEB_VIEWER_DIR in the root Makefile
(default web/gi-kg-viewer). You can override it for a one-off command, e.g.
make serve-ui WEB_VIEWER_DIR=path/to/viewer.
| Target | What it does |
|---|---|
make serve SERVE_OUTPUT_DIR=… |
Parallel: FastAPI (serve-api) + Vite dev (serve-ui); UI usually on 5173, API on 8000. |
make serve-api SERVE_OUTPUT_DIR=… |
FastAPI only. |
make serve-ui |
Vite only in web/gi-kg-viewer (proxies /api → 8000). |
make serve-e2e-mock |
E2E fixture HTTP server (RSS + mock API paths) on 127.0.0.1; default port 18765 (E2E_MOCK_PORT). Use --feeds-spec with fixture URLs on that host/port (primary p01–p05 + long-form p07–p09; skips p06 edge cases) (E2E Testing Guide). |
make test-ui |
Vitest unit tests for TS utils under web/gi-kg-viewer (no browser). |
make test-ui-e2e |
Playwright E2E (Firefox); installs npm deps and browsers as needed. |
make verify-gil-offsets-strict |
Validates GIL Quote offsets against FAISS transcript chunk spans on disk (GIL_OFFSET_VERIFY_DIR). See Semantic Search Guide. |
CI runs the same web/gi-kg-viewer paths; see .github/workflows/python-app.yml.
Invoking viewer tools — npm / ./node_modules/.bin/ (not npx)¶
The Node analog of Python's .venv is web/gi-kg-viewer/node_modules/ —
a per-project, gitignored dependency folder. Use it the same way you'd
use .venv/bin/<tool> for Python: invoke project-pinned binaries, not
ambient ones.
| Python | Node (viewer) |
|---|---|
.venv/bin/python |
node_modules/.bin/<tool> |
pyproject.toml / requirements.txt |
package.json (deps + lockfile) |
source .venv/bin/activate |
npm run <script> (auto-prepends node_modules/.bin to PATH for that script) |
Use these:
cd web/gi-kg-viewer
npm install # creates / updates node_modules
npm run test:e2e # Playwright via project-pinned CLI
npm run test:unit # Vitest
npm run dev # Vite dev server
./node_modules/.bin/playwright test some.spec.ts -g "..." # equivalent direct invocation
Avoid npx <tool> for viewer tooling. The viewer pins
@playwright/test (which exposes its CLI as
node_modules/.bin/playwright) but not a separate package literally
named playwright. npx playwright doesn't find a playwright package
in node_modules, silently fetches a fresh copy from the npm registry
into a temp dir, and runs that. The freshly-fetched runner then loads
spec files whose import { test } from '@playwright/test' resolves to
the project's node_modules/@playwright/test — two module instances
at the same version, no shared internal state. The runner's internal
test registry rejects test.describe() calls from the spec with:
Error: Playwright Test did not expect test.describe() to be called here. … You have two different versions of @playwright/test.
The worker process crashes; the parent shell sees exit code 137
(SIGKILL). Easy to misread as "user canceled" or OOM. The smoking gun
is npm warn exec The following package was not found and will be
installed: playwright@… near the top of the output.
npx is not the Node equivalent of python -m. python -m only
loads from the current interpreter; npx falls back to fetching from
the registry if the literal name isn't in node_modules. Reach for
npm run … or ./node_modules/.bin/… instead.
Where to read next¶
- First pipeline run (profile + operator YAML + feeds): README.md, Installation Guide, CLI.md — Quick Start
- Contributor setup: CONTRIBUTING.md
- Daily dev patterns: Development Guide — GI / KG browser viewer
- FastAPI routes and
serve: Server Guide —/api/*overview; OpenAPI UI at/docswhen the API is up - Vitest + Playwright: Testing Guide
- One-page commands: Quick Reference