mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-11 08:20:53 +00:00
## Summary Embed the HubSpot-hosted contact sales form on `/contact` and `/zh-CN/contact` so HubSpot owns submission handling, validation, anti-spam/security updates, tracking context, and form configuration. ## Changes - **What**: Replaces the custom local contact form stub with a HubSpot embed component using the HubSpot-hosted developer/raw HTML script and `hs-form-html` container. - **Localization**: Uses the existing English form ID by default and switches to the zh-CN form ID for `/zh-CN/contact`. - **Styling**: Applies HubSpot form CSS custom properties to match the Comfy contact page colors and `PP Formula` font more closely. - **Docs**: Updates the website README with the developer embed snippet and the zh-CN form ID. - **Dependencies**: None. ## Why Embedded Form - HubSpot docs say forms should be loaded with the HubSpot-hosted JavaScript file, and that security, anti-spam, accessibility, and performance improvements will not propagate if the embed runtime is copied or self-hosted: https://developers.hubspot.com/docs/cms/start-building/building-blocks/modules/forms - The direct form submission endpoint is documented under `v3 legacy`: https://developers.hubspot.com/docs/api-reference/legacy/marketing/forms/v3-legacy/submit-data-unauthenticated - HubSpot’s legacy API overview says numeric-versioned APIs are legacy and will be deprecated in a future release: https://developers.hubspot.com/docs/api-reference/legacy/overview ## Review Focus - Confirm the portal ID and form IDs are correct: - `en`: `94e05eab-1373-47f7-ab5e-d84f9e6aa262` - `zh-CN`: `6885750c-02ef-4aa2-ba0d-213be9cccf93` - Check visual fit on `/contact` and `/zh-CN/contact`, especially font, background, inputs, radio controls, and submit button. - Confirm the developer/raw HTML embed remains the preferred integration over a custom Forms API POST. ## Local Checks - `pnpm exec oxfmt --check apps/website/src/components/contact/HubspotFormEmbed.vue apps/website/README.md` - `pnpm exec eslint apps/website/src/components/contact/HubspotFormEmbed.vue` - `pnpm --filter @comfyorg/website typecheck` - `pnpm --filter @comfyorg/website test:unit` - `pnpm --filter @comfyorg/website build` - Commit hooks: stylelint, oxfmt, oxlint, eslint, `pnpm typecheck`, `pnpm typecheck:website` - Push hook: `pnpm knip --cache` Build completed with existing non-fatal environment warnings: Node `v25.8.1` vs requested `24.x`, unresolved website font paths deferred to runtime, `transformWithEsbuild` deprecation, and missing Ashby env falling back to the committed snapshot. Incredibly, during the taking of these screenshots, I discovered a bug in macos, where despite the snapshot/record bar not existing, from me esc'ing out, some of the tooltips persist. Closing and reopening the lid did not fix this. I didn't see the process in activity monitor. <img width="1512" height="862" alt="Screenshot 2026-04-29 at 7 09 55 PM" src="https://github.com/user-attachments/assets/92518795-6845-4b34-8da3-54048b440eb1" /> <img width="1512" height="862" alt="Screenshot 2026-04-29 at 7 13 18 PM" src="https://github.com/user-attachments/assets/f7609e58-898d-413c-975c-b02b70b84e73" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11723-fix-embed-HubSpot-contact-form-3506d73d365081528bfbe4b024c2a21f) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
149 lines
5.3 KiB
Markdown
149 lines
5.3 KiB
Markdown
# @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
|
|
<script
|
|
src="https://js-na2.hsforms.net/forms/embed/developer/244637579.js"
|
|
defer
|
|
></script>
|
|
<div
|
|
class="hs-form-html"
|
|
data-region="na2"
|
|
data-form-id="94e05eab-1373-47f7-ab5e-d84f9e6aa262"
|
|
data-portal-id="244637579"
|
|
></div>
|
|
```
|
|
|
|
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
|