Start here
Install HappyToHelp
On this page
You need Node.js 22 or later (with npm) and Git. Check with node --version;
if it is older or missing, install Node 22 from nodejs.org,
or with a version manager (nvm install 22, fnm install 22, or brew install node@22
on macOS). The global rer command itself needs that Node. It then provisions the
checkout's own pinned Node and pnpm. Install dependencies, then start local setup:
npm install -g @runeditrun/rer@0.2.23
git clone https://github.com/just-every/run-happytohelp
cd run-happytohelp
rer install
rer dev
Dev uses its local address for the chat widget and generates a private owner
password. Wait for RER_READY, then open the RER_OPEN address to enter as the
real local owner and reach Setup. No private answers, email service or AI
account are needed. Use rer dev --stop from the checkout to stop the managed app.
Contributor setup
For source work, select Node 22.20.0 and pnpm 10.12.4:
pnpm install --frozen-lockfile
pnpm exec rer describe --json
pnpm exec rer check --profile first-party
This installs frozen dependencies without creating an owner or starting the app. The following private-answer path is also available for scripted setup or to choose your own website and password.
Private setup answers
Create .seed with mode 0700 and .seed/local-answers.json with mode 0600 using
your editor. Keep the file inside the checkout. Use your own values. Explicit
rer setup requires the website, owner email and owner password:
{
"WIDGET_ORIGIN": "https://example.com",
"OWNER_PASSWORD": "Enter your own password of at least 12 characters"
}
The email comes from --owner-email below. An OWNER_EMAIL in the file must
agree with that flag. These answers are optional; a missing one is not sent and
the workspace derives it:
| Answer | Left out |
|---|---|
WORKSPACE_NAME | named from the website or company email domain, otherwise My workspace; change it in Project settings |
PRIMARY_COLOR | a colour is chosen for you; change it in Widget settings |
OWNER_NAME | taken from the first part of the owner email |
AI_PROVIDER | later: no AI key is stored and no provider is contacted |
To store an AI key now, set AI_PROVIDER to openai, anthropic, google,
deepseek, xai or openrouter and add one key answer for that provider:
OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, DEEPSEEK_API_KEY,
XAI_API_KEY or OPENROUTER_API_KEY. The key lands in the private .dev.vars
under that name and nowhere else; a key for a provider other than the chosen one
is refused. Setup does not contact the provider.
rer-setup.json owns field names and conditional requirements. Secrets belong in
the private answer file, never command arguments, logs or source. Native password
identity is retained. Local setup selects rer dev v2 mail and refuses to
overwrite a saved remote provider.
Generated and optional settings
Automatic rer dev setup uses the selected local origin as WIDGET_ORIGIN and
generates OWNER_PASSWORD when unanswered. The password is stored only in the
checkout's private .dev.vars, never printed. Supplied private answers and saved
settings take precedence; an OWNER_PASSWORD environment value is used when no
password was saved or answered. These local defaults do not relax explicit setup
or hosted owner password requirements.
Setup generates three private secrets in .dev.vars: H2H_SETUP_TOKEN,
INTEGRATION_ENCRYPTION_KEY and INBOUND_EMAIL_TOKEN. None is printed in
command output or logs. INBOUND_EMAIL_TOKEN is the bearer value your email
provider's inbound routing presents when it forwards replies to
/api/integrations/email/inbound. Deployment supplies the generated token to the
hosted Worker. A token and a provisioned mailbox do not route email by themselves:
configure your provider's inbound domain, forwarding and webhook for the deployed
endpoint, with the matching bearer token. Cloudflare secrets cannot be read back,
so keep a private copy from .dev.vars before configuring the provider.
Rerunning setup keeps an existing .dev.vars as it is. The one exception: a
checkout set up before INBOUND_EMAIL_TOKEN existed gains that single generated
line on its next setup, and no existing value is changed or rotated. New answers,
such as an AI key, are not applied to an existing .dev.vars; add the key there
yourself or deploy it as an installation secret.
INBOUND_EMAIL_DOMAIN is an optional variable for hosted installations: the domain
that workspace reply mailboxes are created under (for example in.example.com).
Without it, mailboxes default to in. followed by the workspace's website host. The
delivery packaging declares the domain as a public variable and the generated
token as a deploy secret. Rer supplies the token to the hosted installation and
retains an existing secret; older archives still import. A Workers deployment
hostname does not become your workspace name: a workers.dev website defaults
to My workspace regardless of owner email. An explicitly chosen native workspace
name takes precedence; you can change it in Project settings.
Run it locally
rer setup --owner-email you@example.com --answers .seed/local-answers.json
rer dev --foreground
Setup builds, applies local migrations, prepares private settings and the first owner and stops its temporary runtime. Creating the owner provisions the workspace; local email is suppressed without storage or external sending. Reruns preserve the same owner, data and exact existing private settings. Conflicting saved email or origin is refused; preserve data before any recovery or reset.
Dev reports RER_READY after real health checks. Open RER_OPEN to enter as
the local owner. Native password sign-in remains available. Use rer dev --stop
to stop the managed app, or rer dev --foreground to keep it in the terminal and
stop with Ctrl+C.
Choose an explicit loopback port with --port 8788, using the same saved origin
for setup. See Local command reference for preview and
bounded serving. Sign-in takes you to the workspace Setup page described in
First-run setup.
Try the customer widget locally
Use a real page to send a customer message, then reply from your workspace inbox:
-
In Settings → Widget → Code, copy the installation snippet. It already points at this HappyToHelp app and contains the workspace's public widget key.
-
Create an
index.htmlin a separate test folder with a normal HTML document and paste the snippet before</body>. Serve that folder with your website's development server. For example, if Python 3 is installed, run this from the test folder:python3 -m http.server 8840 --bind 127.0.0.1 -
In Settings → Widget → Settings, set Widget website origin to
http://127.0.0.1:8840and save. Use the actual origin if your server differs: scheme, hostname and optional port, without a path.localhostand127.0.0.1are different hosts, and different ports are different origins. The widget has no email field by default. To collect an address for emailed operator replies, enable Required contact details → Require email on this same settings page and save. Visitors then enter their email before sending. -
Open
http://127.0.0.1:8840in another browser profile or private window. Open the widget and send a message. In your signed-in app, open Inbox, choose the conversation and reply. Check the reply in the visitor's widget. Local visitor and teammate email is suppressed without storage or sending.
The website origin is where your customer page runs. The app origin is the
RER_READY address serving HappyToHelp, its API and widget.js; keep that app
address in the copied snippet. Saving a website origin replaces the previously
allowed external website, while the app's own origin always remains allowed.
An online website needs an online HappyToHelp installation reachable by its visitors.
Unverified on the contact means the website has not signed the visitor's identity with the optional server secret. It does not prevent an operator reply from being emailed to the address the visitor entered. Local mail uses rer dev v2 and is suppressed without storage or external sending. On a hosted installation with sending configured, Email sent to provider · delivery not confirmed on a reply records provider acceptance, not confirmed inbox delivery. Inbound mail routing is configured separately.
Verify, reset and move data
Stop dev, then run rer verify. Export before destructive reset
if you need the data. Reset requires rer reset --yes after
reviewing its printed inventory. Export/import use --output FILE and
--input FILE --yes; import requires an empty destination. Native owners survive
restore. Re-enter private configuration before setup/dev. See
Operations.
Deploy and inspect
Rer 0.2.23 requires the same private mail inputs for deployment dry runs and real
deployment: EMAIL_PROVIDER, EMAIL_FROM and EMAIL_API_KEY. The declaration maps
these to both rer's MAIL_* preflight bindings and HappyToHelp's native EMAIL_*
bindings. For Cloudflare mail, supply the additional account ID described in
Operations.
rer deploy --dry-run validates the input shape and builds locally. It makes no
provider requests, sends no mail and makes no deployment. rer deploy --environment production requires owner authorization and the private credentials/declaration
in Operations. Local development still needs no email account.
rer describe lists the remaining commands and real flags.
All new verbs accept --help, --cwd PATH, --non-interactive and --json;
release has its own preserved parser. No command implies provider acceptance.