Adding a Ticket Center to Astro gives your signed in users a full support portal: open conversations, view history, and reply, all without leaving your app. This guide assumes you already have authentication in place.
The Ticket Center uses HMAC SHA256 authentication. Your server signs the user's email with a secret, the embed sends the signature, and Helpdesky verifies both before rendering. For the underlying concepts, read the Ticket Center Setup Guide. Below is the Astro specific path.
Ticket Center vs Contact Form: the Ticket Center is for signed in users. If you only need anonymous visitors to send a message, use a Contact Form instead. SSR required: Astro's static (SSG) mode cannot compute the HMAC at request time. You need an SSR adapter (Node, Vercel, Netlify, Cloudflare, etc) and
output: "server"oroutput: "hybrid"inastro.config.mjs. Static only Astro sites should use the Contact Form instead.
Set Up Your Helpdesk
Open the Helpdesky dashboard and go to Ticket Center in the sidebar. From this page you will need:
- Your Helpdesk ID, visible in the embed snippet at the top
- The Verification Tool further down, used later to confirm your HMAC matches
Generate Your HMAC Secret
On the Ticket Center page, click Generate HMAC Secret and copy it immediately. Helpdesky never shows it a second time.
Add the secret to .env (and to your hosting provider's env vars for production):
HELPDESKY_HMAC_SECRET=hdh_secret_xxxxxxxxxxxxxxxx
HELPDESKY_HELPDESK_ID=your_helpdesk_id
In Astro, env vars without the PUBLIC_ prefix are server only by default, so these stay off the client.
The secret must stay server side. Never expose it to the browser, embed it in client side bundles, or commit it to a public repo.
Compute the HMAC in the Page
Create src/pages/support.astro. Astro pages run on the server when SSR is enabled, so the HMAC happens at request time:
---
import crypto from "node:crypto";
import Layout from "../layouts/Layout.astro";
import { getSession } from "../lib/auth";
const session = await getSession(Astro.request);
if (!session?.user?.email) {
return Astro.redirect("/login");
}
const email = session.user.email;
const signature = crypto
.createHmac("sha256", import.meta.env.HELPDESKY_HMAC_SECRET)
.update(email)
.digest("hex");
const helpdeskId = import.meta.env.HELPDESKY_HELPDESK_ID;
---
<Layout title="Support">
<main>
<h1>Support</h1>
<div id="hdh-ticket-center"></div>
<script
is:inline
src="https://helpdesky.io/ticket-center.js"
data-helpdesk-id={helpdeskId}
data-email={email}
data-signature={signature}
></script>
</main>
</Layout>
Replace ../lib/auth with whatever auth helper your Astro app uses (Auth.js, Lucia, Clerk Astro, Supabase, etc).
The is:inline directive tells Astro to leave the script tag alone instead of bundling it. That matters because Helpdesky's script reads its config from its own data-* attributes, which Astro's bundler would strip otherwise.
Test It
Sign in to your app as a real user and open the support route. The Ticket Center should render with that user's conversations.
If you see an authentication error, copy the email and signature your server generated, then paste them into the Verification Tool in the Helpdesky dashboard. The expected signature must match yours exactly.
Common issues:
- Signature mismatch. Usually trailing whitespace in the secret, or signing the wrong field. Sign the user's email exactly as Helpdesky stores it.
- Empty panel. Make sure the test user has at least one conversation, or start one from another channel first.
- Secret leaked into client bundle. If your build inlined the secret, the env var name probably had a public prefix (
VITE_,PUBLIC_,NEXT_PUBLIC_). Rename it and rebuild.
Next Steps
Add a public Contact Form on your marketing pages for visitors who are not signed in. Route inbound support email into the same inbox with the Email Forwarding Setup Guide.