Skip to content

fix(add): smooth the rough edges found while documenting add - #274

Merged
Bccorb merged 1 commit into
mainfrom
fix/add-rough-edges
Oct 13, 2026
Merged

Bccorb merged 1 commit into
mainfrom
fix/add-rough-edges

Conversation

@Bccorb

@Bccorb Bccorb commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Closes #271

Branched from main, separate from #273 (the Compose project name for #270). The two touch nearby lines in add.ts, helpTopics.ts, add.test.ts and the README, but they merge cleanly in either order. I checked by merging both locally: 1324 tests passed and tsc was clean.

The six items

  1. --api-url defaults by ecosystem. When the backend's .env has no PORT, add reads the port from the entry file's listen call: app.listen(4000), http.ListenAndServe(":8081", ...), r.Run(":9000"), e.Start(":1323"), Addr: "...:7070", TcpListener::bind("0.0.0.0:3000"), SocketAddr::from(([..], 4001)), or uvicorn.run(..., port=8001). If there is none, it falls back to DEFAULT_BACKEND_PORTS: 3000 for Node, 8000 for FastAPI and Django (the uvicorn and runserver defaults), and 8080 for Go and Rust.
    • Go and Rust use 8080 because the snippets follow the seamless-auth-go and seamless-auth-rust READMEs, and both listen on :8080. Gin's Run() with no address also defaults to 8080.
    • The api starters in seamless-templates use PORT 3000, but they are scaffolded by init, not add, and they set PORT in .env, which still wins.
    • seamless help add and the README document the order.
  2. One list of searched folders. searchedDirsText() in detect.ts builds its text from CANDIDATE_DIRS and WORKSPACE_PARENTS, the same arrays detection walks. The "Found no backend" error and the add help both use it, so app/ (plus web/, client/ and frontend/ in the error) now appear. The README is static, so a test checks that the README contains the generated list in backticks, and another checks that each listed folder is where detection actually finds a backend.
  3. Credentialed CORS for Go, Axum and Django. The code is based on templates/api/gin and templates/api/axum in seamless-templates main:
    • net/http and chi: a withCORS net/http middleware. It reflects an allowed Origin, sets Allow-Credentials, and answers preflight with 204. net/http serves withCORS(mux), and chi uses r.Use(withCORS) ahead of the routes.
    • Gin: the starter's Gin middleware, inline.
    • Echo: Echo's own middleware.CORSWithConfig with AllowCredentials. It is in the echo module, so nothing new to install.
    • Axum: a tower-http CorsLayer (AllowOrigin::list, allow_credentials(true), mirrored headers). It is layered before the console is merged, so the same-origin console stays outside CORS, as in the starter. The install now also runs cargo add tower-http --features cors.
    • Django: django-cors-headers (INSTALLED_APPS += ["corsheaders"], CorsMiddleware first, CORS_ALLOWED_ORIGINS from UI_ORIGINS, CORS_ALLOW_CREDENTIALS = True), and django-cors-headers is installed with the adapter.
    • Origins come from UI_ORIGINS, falling back to the detected web origin, the same as Express, Fastify and FastAPI.
  4. FastAPI .env. I did what the FastAPI starter does: install python-dotenv and call load_dotenv(). FastAPI and Django now install python-dotenv, and the printed code calls load_dotenv() before reading os.environ. The hint says so and no longer mentions uvicorn --env-file. The pip note now says "them" for the extra packages.
  5. React sign-in screens. React now gets two steps, following templates/web/react-vite/src/App.tsx and the @seamless-auth/react README:
    • Step 1 wraps <App /> in BrowserRouter and AuthProvider at the entry.
    • Step 2 mounts AuthRoutes from @seamless-auth/react/routes behind a SignIn guest guard on path="*", plus a RequireAuth guard for signed-in pages. It goes in src/App.tsx|jsx|js when that file exists, otherwise the entry. JavaScript apps get the same code without the ReactNode type.
    • react-router-dom (an optional peer of the binding that the routes need) is installed when the app does not have it.
  6. Em dashes. The seamless <command> --help header is now seamless add (seamless v0.23.0). Other user-facing em dashes in src are fixed too: the top-level help tagline, the verify summary lines, and the admin dashboard prompt labels in init. So are two code comments and the test describe titles. A test now fails if any file under src contains an em dash.

Tests

  • detect.test.ts: searchedDirsText matches the folders detection searches; backendListenPort defaults per ecosystem and reads each listen pattern; React router file and the react-router-dom peer.
  • snippets.test.ts: CORS per Go router, Axum (layer before the console), Django; load_dotenv() before the first env read; new install lines for Rust, FastAPI, Django.
  • webSnippets.test.ts: React steps, files, TS vs JS, router peer.
  • add.test.ts: API URL default for FastAPI, Django, Go, Axum; listen-call port and PORT precedence; the no-backend error names every searched folder; React install and AuthRoutes output.
  • help.test.ts: help names the folders and ports, generated lines stay within the help width, README matches the folder list, no em dash in src.

Verification

npm run build, npm test (63 files, 1309 passed, 4 skipped), npm run check:types-current, npm run check:templates-pin, and the pre-commit coverage run (lines 99.23%) all pass.

I ran the built CLI (add --local --yes --email=you@example.com </dev/null, installs run for real) against these scratch projects. For each one I pasted the printed code into the app and compiled or ran it:

Project API URL written Install run Printed code checked with Live CORS check
Express (TS) + React (Vite, TS) :3000 npm install @seamless-auth/react react-router-dom tsc --noEmit on api and web, vite build not run
FastAPI with uv :8000 uv add "seamless-auth[fastapi]>=0.2" python-dotenv python -c "import main" with an empty environment (so load_dotenv() supplied every value) uvicorn main:app: preflight from localhost:5173 got allow-origin and allow-credentials
Go net/http module :8080 go get seamless-auth-go (v0.2.0) go vet, go build preflight 204 with the CORS headers; an unknown origin got none
Gin, chi, Echo modules (snippet only) go vet not run
Axum crate :3001, read from TcpListener::bind cargo add seamless-auth, cargo add tower-http --features cors cargo check, cargo build preflight 200 with the CORS headers; /console/ served without them
Django with uv :8000 uv add "seamless-auth[django]>=0.2" python-dotenv django-cors-headers manage.py check (no issues) runserver: preflight got allow-origin and allow-credentials; GET /api/me returned 401

Not run: Express CORS at runtime (its snippet is unchanged), and Fastify (unchanged).

Docs to update after release (fells-code/seamless-auth-docs)

src/content/docs/operate/add-to-existing-app.mdx:

  • L31 (Python row of the backend table): also python-dotenv, plus django-cors-headers for Django. L30 (Rust row): also tower-http with the cors feature.
  • L36 (React row of the web table): plus react-router-dom if missing.
  • L78-85: --api-url defaults. Drop the "FastAPI and Django usually listen on 8000, so pass --api-url" workaround, and describe the new order (PORT, the listen call, then 3000 for Node, 8000 for Python, 8080 for Go and Rust).
  • L108: sample output becomes $ cd web && npm install @seamless-auth/react react-router-dom.
  • L158-160: the router-peer sentence should add react-router-dom for React.
  • L212-213 (Go "By hand"): CORS is now printed; only loading .env stays by hand.
  • L223-224 (Rust "By hand"): same; the CorsLayer is printed and tower-http is installed.
  • L228: FastAPI install adds python-dotenv.
  • L235-237 (FastAPI "By hand"): the printed code calls load_dotenv() and python-dotenv is installed. Drop the --env-file and "pass --api-url if uvicorn is not on port 3000" text; keep the requirements.txt note for pip.
  • L241: Django install adds python-dotenv and django-cors-headers.
  • L246-248 (Django "By hand"): CORS (django-cors-headers) and load_dotenv() are now printed.
  • L254-257 (React bullet): React now gets two steps, BrowserRouter plus AuthProvider at the entry, then AuthRoutes with signed-in and signed-out guards in src/App.

src/content/docs/reference/cli-commands.mdx:

  • L231 (Axum row): installs cargo add seamless-auth and cargo add tower-http --features cors.
  • L232 (FastAPI, Django row): plus python-dotenv, and django-cors-headers for Django.
  • L240 (React row): @seamless-auth/react, plus react-router-dom if missing.
  • L270 (--api-url row): default is PORT from .env, else the entry's listen port, else 3000 (Node), 8000 (FastAPI, Django), 8080 (Go, Rust).

Default --api-url by ecosystem (and the entry's listen call), list the searched folders from the detector's own list, print working credentialed CORS for Go, Axum and Django, install python-dotenv for FastAPI and Django and load it in the printed code, give React the AuthRoutes sign-in step, and remove the em dashes from user-facing text.

Closes #271
@Bccorb
Bccorb merged commit fe553f5 into main Oct 13, 2026
5 checks passed
@Bccorb
Bccorb deleted the fix/add-rough-edges branch October 15, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

seamless add: rough edges found while documenting it

1 participant