# @comfyorg/website Marketing/brand website built with Astro + Vue. ## Ashby careers integration `/careers` and `/zh-CN/careers` are rendered from Ashby's public job board API at build time. Data flow: 1. `src/pages/careers.astro` awaits `fetchRolesForBuild()` during the Astro build. 2. `src/utils/ashby.ts` calls `GET https://api.ashbyhq.com/posting-api/job-board/{board}?includeCompensation=false`, validates the envelope and each posting with Zod (`src/utils/ashby.schema.ts`), and maps to the domain type in `src/data/roles.ts`. 3. On any failure (network, HTTP 4xx/5xx, envelope schema drift), the fetcher falls back to the committed JSON snapshot at `src/data/ashby-roles.snapshot.json`. 4. `src/utils/ashby.ci.ts` emits GitHub Actions annotations and a `$GITHUB_STEP_SUMMARY` block so stale fetches are visible on green builds. ### Required environment variables Both are build-time only. Never prefix with `PUBLIC_` (Astro would inline that into the client bundle). | Name | Purpose | Default (when unset) | | ------------------------------ | --------------------------- | --------------------------------- | | `WEBSITE_ASHBY_API_KEY` | Ashby API key (Basic auth) | Build uses the committed snapshot | | `WEBSITE_ASHBY_JOB_BOARD_NAME` | Ashby public job board slug | Build uses the committed snapshot | ### CI wiring (manual step — required) This repo's `.github/workflows/*.yaml` changes cannot be pushed by a GitHub App. A maintainer must apply the following edits **once**: **`.github/workflows/ci-website-build.yaml`** — pass the env into the build step and run the unit tests before it: ```yaml jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Setup frontend uses: ./.github/actions/setup-frontend - name: Run website unit tests run: pnpm --filter @comfyorg/website test:unit - name: Build website env: WEBSITE_ASHBY_API_KEY: ${{ secrets.WEBSITE_ASHBY_API_KEY }} WEBSITE_ASHBY_JOB_BOARD_NAME: ${{ vars.WEBSITE_ASHBY_JOB_BOARD_NAME || 'comfy-org' }} run: pnpm --filter @comfyorg/website build - name: Verify API key is not leaked into build output env: WEBSITE_ASHBY_API_KEY: ${{ secrets.WEBSITE_ASHBY_API_KEY }} run: | set +x if [ -z "${WEBSITE_ASHBY_API_KEY:-}" ]; then echo "Secret not available in this run; skipping leak check." exit 0 fi # grep -rlF prints only file paths (never match content). MATCHES=$(grep -rlF --exclude-dir=node_modules --null \ -e "$WEBSITE_ASHBY_API_KEY" apps/website/dist/ 2>/dev/null \ | tr '\0' '\n' || true) if [ -n "$MATCHES" ]; then echo "::error title=Ashby API key leaked into build output::$MATCHES" exit 1 fi ``` **`.github/workflows/ci-vercel-website-preview.yaml`** — add the two env vars to the top-level `env:` block so `vercel build` (both `deploy-preview` and `deploy-production` jobs) sees them: ```yaml env: VERCEL_ORG_ID: ${{ secrets.VERCEL_WEBSITE_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_WEBSITE_PROJECT_ID }} VERCEL_TOKEN: ${{ secrets.VERCEL_WEBSITE_TOKEN }} VERCEL_SCOPE: comfyui WEBSITE_ASHBY_API_KEY: ${{ secrets.WEBSITE_ASHBY_API_KEY }} WEBSITE_ASHBY_JOB_BOARD_NAME: ${{ vars.WEBSITE_ASHBY_JOB_BOARD_NAME || 'comfy-org' }} ``` The secret must also be added to the Vercel project environment (`vercel env add WEBSITE_ASHBY_API_KEY …` or via the Vercel UI) so that `vercel build` in the preview job has access to it. Fork PRs do not exercise this path: `ci-vercel-website-preview.yaml` receives an empty `VERCEL_TOKEN` for forks and fails at `vercel pull` before the build runs. Fork-safe PR interactions (the preview-URL comment) are handled by `pr-vercel-website-preview.yaml`. ### Refreshing the snapshot When a maintainer wants to update the committed snapshot (e.g. after onboarding/offboarding roles): ```bash WEBSITE_ASHBY_API_KEY=… WEBSITE_ASHBY_JOB_BOARD_NAME=comfy-org \ pnpm --filter @comfyorg/website ashby:refresh-snapshot git commit apps/website/src/data/ashby-roles.snapshot.json ``` The script exits non-zero on any non-fresh outcome so stale/empty snapshots can't be accidentally committed. ## HubSpot contact form The contact page uses HubSpot's hosted form embed for the interest form: ```html
``` The localized `/zh-CN/contact` page uses the same portal and script with form ID `6885750c-02ef-4aa2-ba0d-213be9cccf93`. This keeps submission handling, validation, anti-spam updates, and field configuration in HubSpot. The local implementation in `src/components/contact/HubspotFormEmbed.vue` only loads the hosted script and renders the documented embed container. ## Scripts - `pnpm dev` — Astro dev server - `pnpm build` — production build to `dist/` - `pnpm typecheck` — `astro check` - `pnpm test:unit` — Vitest unit tests - `pnpm test:e2e` — Playwright E2E tests (requires `pnpm build` first) - `pnpm ashby:refresh-snapshot` — refresh the committed careers snapshot