mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Every word the landing, the header menus, the phone sheet, the footer,
the help corner and the way in (sign-in, sign-up, the reset, the
invitation, the callback, onboarding, the 404) write goes through
@hanzo/i18n's t(): one sentence is one message, its figures, names and
links arguments; copy written as data is phrase('…') where written and
t(label) where drawn. Plans, the chart, the API states and the lines
lib/kai and lib/enso build for the landing do the same.
Right to left: <html lang dir> is set before the first paint (the
package's bootScript first in the head); a figure, clock, range or
price outside a sentence is isolated; sides are logical gui props, the
layout's [data-join] corners logical, a bar grows from the start;
arrows along the line mirror (Onward for "words ->" links). The repo
dates read in the reader's language.
Gates select by slot, never by an English label (rtl, help). New gate
translated.spec.ts: in Arabic the landing at 1440 and 390, every menu
open, the phone sheet, sign-in, sign-up and the app signed in hold no
authored English, nothing scrolls sideways, every range is isolated;
French the same for English's commonest words. What another package
draws with no words prop is listed by name (@hanzo/ui's Footer label,
@hanzo/build's composer row and suggestions).
@hanzo/i18n 0.5.3 (the catalogs: 1,443 keys, every offered locale
complete), @hanzo/app 0.2.1 (the app's words). The link gate imports
the terms versions from @hanzo/app, the one SDK main now resolves.
116 lines
5.8 KiB
TypeScript
116 lines
5.8 KiB
TypeScript
import { phrase } from '@hanzo/i18n'
|
||
|
||
/**
|
||
* WHAT A READER IS INVITED TO START, said once.
|
||
*
|
||
* Both composers on the apex draw from here — the one in the fold and the one
|
||
* that follows the page down — because they had a copy each and the copies had
|
||
* already drifted apart. A prompt is a promise about what this place is for, so
|
||
* two lists is two answers to the same question.
|
||
*
|
||
* EACH ONE IS A COMPANY, not a clever sentence about AI. The templates a new
|
||
* workspace can actually fork are small businesses with a crew — an automation
|
||
* agency with a sales agent and a client manager, a clipping channel with a
|
||
* clipper and a channel manager, a newsletter whose researcher, writer and
|
||
* growth agent hand off to a publisher — so these read in that register: who is
|
||
* on the crew, what they touch, and what waits for a person. A reader who
|
||
* presses enter on one of these should land somewhere that looks like it.
|
||
*
|
||
* THE APPROVAL IS PART OF THE PITCH, not a caveat bolted on. Several of these
|
||
* say plainly that nothing goes out until somebody says so, because the fear a
|
||
* founder brings to this page is an agent acting in their name — and answering
|
||
* it in the prompt is more convincing than a paragraph about it further down.
|
||
*/
|
||
|
||
/**
|
||
* What a reader's own coding agent is told, said once. Every copy control on
|
||
* the page puts THIS on the clipboard — the fold's Copy setup prompt, each
|
||
* "Open in" row under it, and the agent row's button — so the three cannot
|
||
* drift into three different instructions. It stays English on every page:
|
||
* it is an instruction for a coding agent, not copy a reader reads.
|
||
*
|
||
* `/skill.md` is the manual it points at, and every command here was run
|
||
* against the CLI hanzo.sh installs (8.5.732) before it was written down:
|
||
*
|
||
* `hanzo login` is a registered alias of `hanzo auth login`, which is the
|
||
* spelling /skill.md uses — one implementation, two names, and this is the
|
||
* one a person types.
|
||
* `hanzo template list` answers with the public starter catalog, the same
|
||
* catalog /templates reads (GET /v1/templates).
|
||
* `hanzo template get <slug>` answers with one kit, and its `source` is the
|
||
* repository to clone. `hanzo init --template <slug>` is NOT that: it
|
||
* accepts any string, validates nothing and writes a README and a
|
||
* .gitignore, so an agent told to clone with it would report success over
|
||
* an empty directory.
|
||
* `hanzo dev` starts a coding session in the directory it is run from: Hanzo's
|
||
* own agent, its model calls routed through api.hanzo.ai and metered to the
|
||
* reader's org once signed in. It wants a terminal (run by an agent it
|
||
* prints `stdin is not a terminal`), so the agent hands that step to the
|
||
* reader. `hanzo up` boots a local Kubernetes in a microVM, which no new
|
||
* project needs, so it is not a step here.
|
||
*
|
||
* /skill.md covers the credential, the API and the MCP server and says nothing
|
||
* about starters or the coding session, so for those two the CLI is the
|
||
* authority and this prompt follows it.
|
||
*/
|
||
export const SETUP = [
|
||
'Read https://hanzo.ai/skill.md and follow it to set up a Hanzo company in my project:',
|
||
'register or sign in with `hanzo login`, pick a starter with `hanzo template list`,',
|
||
'clone the repository `hanzo template get <slug>` names in its `source`, then tell me to run `hanzo dev` in it to start building.',
|
||
'Check you are in the project directory first — if not, ask me where it is.',
|
||
].join(' ')
|
||
|
||
/** The line that cycles in an empty field.
|
||
*
|
||
* SHORT ENOUGH TO FINISH. The field is about 500px, which is roughly 55
|
||
* characters; a longer line is cut off mid-word and an invitation that does not
|
||
* reach its own verb is worse than no invitation. Each of these names the
|
||
* company and one thing about how it runs, and stops. A field's hint, so each
|
||
* is authored copy (`phrase`): the composer draws it with `t()`. */
|
||
export const PROMPTS = [
|
||
phrase('Start an automation agency with a workspace per client…'),
|
||
phrase('Launch an SEO agency that ranks clients in AI answers…'),
|
||
phrase('Open a store whose agents write every listing…'),
|
||
phrase('Run a clipping channel: long-form in, shorts out…'),
|
||
phrase('Build a CRM with an agent working the pipeline…'),
|
||
phrase('Start a newsletter that never sends unapproved…'),
|
||
]
|
||
|
||
/**
|
||
* A named starter, for a reader who would rather press than type. The `label`
|
||
* is authored copy (`phrase`), drawn with `t()`; the `prompt` is what is sent to
|
||
* the agent, and stays as written.
|
||
*/
|
||
export const CHIPS: { label: string; prompt: string }[] = [
|
||
{
|
||
label: phrase('Automation agency'),
|
||
prompt:
|
||
'Start an AI automation agency: a CRM, a public site, and a workspace for each client, with a sales agent and a client manager working the pipeline through Gmail, GitHub and Vercel',
|
||
},
|
||
{
|
||
label: phrase('SEO agency'),
|
||
prompt:
|
||
'Launch an SEO agency that ranks clients in search and in AI answers, with a sales agent and a client manager reading Search Console and reporting by email every Monday',
|
||
},
|
||
{
|
||
label: phrase('Ecommerce store'),
|
||
prompt:
|
||
'Open an ecommerce store: a catalog, a checkout, and agents that write the listings, watch the stock and answer buyers before you are awake',
|
||
},
|
||
{
|
||
label: phrase('CRM'),
|
||
prompt:
|
||
'Build a CRM for my business: contacts, deals, and an agent that works the pipeline every morning and drafts the follow-ups for me to send',
|
||
},
|
||
{
|
||
label: phrase('Clipping channel'),
|
||
prompt:
|
||
'Run a clipping channel: a clipper cuts long-form into shorts and a channel manager posts them to TikTok, YouTube and Instagram on a schedule',
|
||
},
|
||
{
|
||
label: phrase('Recruiting desk'),
|
||
prompt:
|
||
'Open a recruiting desk: a sourcer finds candidates, a screener runs the first call, and an account manager books the shortlist onto the hiring manager’s calendar',
|
||
},
|
||
]
|