{"_id":"@athon-labs/help-widget-core","name":"@athon-labs/help-widget-core","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@athon-labs/help-widget-core","version":"0.0.1","private":false,"type":"module","description":"Shared helpers for Athon help widgets: issue FormData, screen capture, and submit.","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/styles.css"},"publishConfig":{"access":"public"},"sideEffects":["./dist/styles.css"],"devDependencies":{"tsup":"^8.5.0","typescript":"^5.8.3","vitest":"^3.2.4"},"scripts":{"build":"tsup && cp src/styles.css dist/styles.css","typecheck":"tsc --noEmit","test":"vitest run"},"_id":"@athon-labs/help-widget-core@0.0.1","_integrity":"sha512-IpfmfLtpCF4P77TAl2+XD0iaW8dY46KzzpqHHfMrypKlq5sWZqI/isaVhxZln/Er7fpazXYuCH0QD4edhcbscg==","_resolved":"/private/var/folders/29/mc0szw4x6370qzrffd0xbg_w0000gn/T/5e831ed5547e10fa94aef0fcdc1557ae/athon-labs-help-widget-core-0.0.1.tgz","_from":"file:athon-labs-help-widget-core-0.0.1.tgz","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-IpfmfLtpCF4P77TAl2+XD0iaW8dY46KzzpqHHfMrypKlq5sWZqI/isaVhxZln/Er7fpazXYuCH0QD4edhcbscg==","shasum":"77a10965d3c0ddb5974fd841ba9927e83ea07aef","tarball":"https://registry.npmjs.org/@athon-labs/help-widget-core/-/help-widget-core-0.0.1.tgz","fileCount":6,"unpackedSize":68897,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDOSUogKwcjXfVwS1tahSwyj52Sc6wN1Ign7Xh/foUgUAIhALzeq6JM+X6fjeZJLRzFyBizlmatO0cUDXFglSj0aLl3"}]},"_npmUser":{"name":"thethind","email":"harminder@thind.dev"},"directories":{},"maintainers":[{"name":"thethind","email":"harminder@thind.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/help-widget-core_0.0.1_1787332115549_0.9706738859955006"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-21T17:08:35.380Z","0.0.1":"2026-08-21T17:08:35.683Z","modified":"2026-08-21T17:08:35.927Z"},"maintainers":[{"name":"thethind","email":"harminder@thind.dev"}],"description":"Shared helpers for Athon help widgets: issue FormData, screen capture, and submit.","readme":"# @athon-labs/help-widget-core\n\nShared helpers for the Athon help widgets. Host apps should use `@athon-labs/help-widget-react` or `@athon-labs/help-widget-svelte` instead of this package directly.\n\nThe widget never sees an Athon live key. It POSTs multipart form data to **your** backend. Your server adds `Authorization: Bearer sk_live_…` and forwards to Athon ingest.\n\n## Payload\n\nField names match `POST /api/v1/ingest/issues`:\n\n| Field | Source |\n| --- | --- |\n| `title`, `description` | Widget form |\n| `reporterEmail`, `reporterName`, `reporterExternalId` | Logged-in user you pass in |\n| `screenshots` | Screen capture or attached photos (max 5) |\n| `route`, `browser`, `viewport` | Collected in the browser |\n| `metadata` | Optional JSON of host-supplied key-values (user type, phone, …) |\n| `diagnostics` | JSON of recent console logs and fetch/XHR (bodies and secrets redacted) |\n\nYour proxy should add `appId` or `projectId`.\n\n## Backend proxy\n\nSee [docs/proxy.md](./docs/proxy.md) for Node.js, Express, Next.js, SvelteKit, and Hono.\n\nSet these on the server only:\n\n```bash\nATHON_LIVE_KEY=sk_live_…\nATHON_APP_ID=app_…\nATHON_INGEST_URL=https://YOUR_ATHON_HOST/api/v1/ingest/issues\n```\n\n### Node.js\n\n```js\nimport { createServer } from 'node:http';\n\nconst server = createServer(async (req, res) => {\n  if (req.method !== 'POST' || req.url !== '/api/support/report') {\n    res.writeHead(404);\n    res.end('Not found');\n    return;\n  }\n\n  const incoming = new Request('http://local/api/support/report', {\n    method: 'POST',\n    headers: req.headers,\n    body: req,\n    duplex: 'half',\n  });\n\n  const form = await incoming.formData();\n  form.set('appId', process.env.ATHON_APP_ID ?? '');\n\n  const upstream = await fetch(process.env.ATHON_INGEST_URL ?? '', {\n    method: 'POST',\n    headers: { Authorization: `Bearer ${process.env.ATHON_LIVE_KEY}` },\n    body: form,\n  });\n\n  res.writeHead(upstream.status, {\n    'content-type': upstream.headers.get('content-type') ?? 'application/json',\n  });\n  res.end(await upstream.text());\n});\n\nserver.listen(3000);\n```\n\nDo not run a JSON body parser on this route. An Express variant is in [docs/proxy.md](./docs/proxy.md).\n\n### Next.js\n\n`app/api/support/report/route.ts`:\n\n```ts\nexport async function POST(request: Request) {\n  const form = await request.formData();\n  form.set('appId', process.env.ATHON_APP_ID ?? '');\n\n  const upstream = await fetch(process.env.ATHON_INGEST_URL ?? '', {\n    method: 'POST',\n    headers: { Authorization: `Bearer ${process.env.ATHON_LIVE_KEY}` },\n    body: form,\n  });\n\n  return new Response(await upstream.text(), {\n    status: upstream.status,\n    headers: { 'content-type': upstream.headers.get('content-type') ?? 'application/json' },\n  });\n}\n```\n\n### SvelteKit\n\n`src/routes/api/support/report/+server.ts`:\n\n```ts\nimport { env } from '$env/dynamic/private';\nimport type { RequestHandler } from './$types';\n\nexport const POST: RequestHandler = async ({ request }) => {\n  const form = await request.formData();\n  form.set('appId', env.ATHON_APP_ID);\n\n  const upstream = await fetch(env.ATHON_INGEST_URL, {\n    method: 'POST',\n    headers: { Authorization: `Bearer ${env.ATHON_LIVE_KEY}` },\n    body: form,\n  });\n\n  return new Response(await upstream.text(), {\n    status: upstream.status,\n    headers: { 'content-type': upstream.headers.get('content-type') ?? 'application/json' },\n  });\n};\n```\n","readmeFilename":"README.md","_rev":"1-1ac7ed07741bae72da6e48c342b6d009"}