Documentation
Last reviewed 12 July 2026
Overview#
What Astarter AI is#
Astarter AI is a general-purpose AI assistant: chat with it about anything, and it can search the web or open a link you ask it to read when a question needs current information. It works immediately as a guest, with no account required.
The router fails over automatically, so an outage in one upstream service does not drop your conversation. A response-mode picker (Auto, Fast, Expert) lets you trade speed against depth per message.
This page reflects the current code, not the roadmap. If a feature below is not available in the running product, a note says so plainly instead of describing it as if it were live.
Double-check important answers#
The assistant can be genuinely helpful, but it can still get things wrong, and it can sound completely confident while doing it. That is true of AI assistants in general, not just this one. Treat an answer the way you would treat a tip from a smart friend: a great starting point, worth checking before you rely on it, especially for dates, numbers, current events, or medical, legal, and financial specifics.
- Check it against a source when you can, especially before you act on it.
- If an answer looks off, do not just accept it; ask a follow-up question or regenerate it for a fresh attempt.
- If the question was broad or ambiguous, rephrase it with more detail. A sharper question usually gets a more reliable answer.
The surfaces#
Astarter AI ships two connected surfaces today:
- Chat (
/) - the main assistant: streaming responses, sessions, response modes and styles, a Skills menu, attachments, share links, a language switcher, and full settings. - Projects - inside Chat, group related conversations under a project with its own memory and instructions, so follow-up chats start with the right context automatically.
Explore the docs#
Get started#
Sign in#
You do not need an account to use Astarter AI. As a guest, a signed anonymous cookie identifies your browser so fair-use limits can be applied; nothing personal is attached to it.
Three sign-in methods are live today. Each is hidden automatically on a deployment that has not configured it:
- Email and password - sign up with an email and a password of at least 8 characters. Depending on how a deployment is configured, you either verify by email first, or, when no mail service is configured, the account is created and signed in immediately.
- Google - one-click OAuth sign-in.
- Wallet - connect a crypto wallet on BNB Chain (BSC) and sign a one-time message; Solana wallets are supported too. See the note below.
/login or the account menu in the chat header. Any browser-extension wallet on BNB Chain (BSC) is discovered automatically through the EIP-6963 standard; Solana wallets (Phantom, Solflare, Backpack) work as well. If more than one wallet is detected you get a small picker to choose from. See Under the hood for how it works.Start a sign-in from the account menu in the chat header, or from the dedicated /login and /signup screens.
Start a chat#
Open / and type into the composer. Press Enter to send, or Shift+Enter for a new line without sending. Ctrl/Cmd+K starts a fresh chat at any time.
Every reply streams in as it is generated. You can stop generation mid-stream, regenerate the last answer, or edit and resend an earlier message. Answers render full markdown: headings, lists, tables (which scroll horizontally on narrow screens instead of overflowing), and syntax-highlighted code blocks with a one-click copy button. Any math the assistant writes is converted to plain readable text rather than left as raw notation.
What you can do, and how to ask#
The assistant is a general-purpose helper, not a narrow tool for one thing. A few common ways people use it:
- Writing and editing - draft a message, tighten a paragraph, or change the tone of something you already wrote.
- Learning something new - get a concept explained at whatever level you need, from a quick summary to a full step-by-step walkthrough.
- Planning and organizing - turn a messy list of ideas into a plan, a checklist, or a table.
- Coding help - explain an error message, write a function, or review a snippet.
- Quick research - ask about something current; it can look things up and tell you where the information came from.
The Skills menu next to the composer has one-tap shortcuts for some of this too, like summarizing a conversation, pulling out action items, or proofreading your last message. You can also export any single conversation as a PDF or Markdown file from the same menu; there is no one-click export for your whole account yet, just one conversation at a time.
Getting a good answer is mostly about how you ask.
- Start simple. Ask the direct question first. You can always add detail once you see the first answer.
- Be specific. "Write a birthday message for my sister, upbeat, under 50 words" gets you further than "write something nice."
- Give context. Mention who it is for, what you have already tried, or what a good answer would look like.
- Iterate. Treat the first reply as a draft. Ask it to shorten, expand, simplify, or redo one part, rather than starting over.
A few to try:
- "Explain how compound interest works, like I am new to personal finance."
- "Rewrite this paragraph so it sounds more confident: [paste your text]"
- "I have $40 of ingredients and 20 minutes, what can I cook?"
- "Give me a 3-step plan to learn the basics of a new language this month."
The composer#
The composer is a rounded input capsule with a control row underneath it:
- Attach - add images by clicking, pasting, or dragging them onto the page.
- Response mode pill - Auto, Fast, or Expert; see Response modes.
- Skills - one-tap actions like Summarize or Export; see Skills menu.
- Send - a filled accent button that activates once there is text, or an attachment, to send.
A small counter near the composer shows how many messages you have left today on the free tier; it resets 24 hours after your first message, not at a fixed clock time.
Using Astarter#
Chatting and streaming#
Responses stream token by token over the same connection, so you see the answer form in real time instead of waiting for the whole thing. While a reply is streaming you can stop it early; once it finishes you can regenerate it for a different take, or edit your own message and resend it, which replaces everything after it in that conversation.
Formatting support includes nested lists (ordered, unordered, and task checkboxes), block quotes, horizontal rules, autolinked URLs, and fenced code blocks with language-aware syntax highlighting and copy buttons. Rich outputs such as a generated document or diagram render as an artifact card with a live preview and an option to open, copy, or download it.
Response modes#
The mode pill in the composer controls how much effort a reply puts in:
- Auto - picks the right depth for the question automatically.
- Fast - quick, direct answers for simple questions.
- Expert - thinks harder through tougher problems before answering.
It changes how much effort goes into a reply. Your choice is remembered on this device.
Response styles#
Independent of mode, a response style sets the voice: Normal (the default), Formal (polished and professional, no slang or emoji), or Learning (a patient, step-by-step tutor voice with small check-in questions along the way). Styles fold into your custom instructions behind the scenes, so they combine with whatever you have written in Settings.
Skills menu#
The Skills button opens a menu of one-tap actions that run against the current conversation:
- Summarize - recap the conversation so far as bullet points.
- Action items - pull out next steps as a checklist.
- Make a table - reorganize the key information into a markdown table.
- Proofread - polish the writing in your last message.
- Explain simply - a plain-language version of the last answer, with an everyday analogy.
An Export & share group in the same menu offers Export as PDF, Export as Markdown, and Share a link (see Share links).
Projects#
Projects group related chats together. The Projects page gives you a card grid of your projects with search and sort; opening one gives you a project workspace with its own composer (any chat you start here is tagged to the project) plus a right-hand rail for:
- Memory - short facts the assistant should remember for this project.
- Instructions - standing guidance applied to every chat in the project.
- Files - a placeholder for now; project file storage is not available yet.
Attachments and images#
Attach images by clicking the attach button, pasting them, or dragging them onto the window. You can attach more than one at a time, preview or remove them before sending, and click a sent image later to enlarge it.
Whether the assistant can actually see an image depends on how the deployment is configured. When image understanding is not enabled, you get a clear notice explaining that instead of a confusing failure, and it does not count against your daily message limit. Text and code files - plain text, Markdown, JSON, XML, YAML and the like - are read and their contents are sent along with your message, so you can ask about a file you attach. Other binary formats such as PDF or Word are not accepted yet; attaching one is declined with a short notice.
Language switcher#
Settings > General > Language switches the interface itself (menus, labels, buttons) using a small built-in translation dictionary, currently covering English plus five more languages, including one right-to-left script. It only translates the interface chrome, never your own conversation content, which does not need it since the assistant already replies in whatever language you write to it in.
Settings#
Settings is organized into four tabs:
- General - theme, chat font, motion, code font, what to call you (personalizes your greeting, stored only in this browser), custom instructions (up to 2000 characters, applied to every chat unless a project overrides them), and language.
- Account - your sign-in state and sign-out.
- Data - clear local data, or delete your account entirely.
- About - product information.
Keyboard shortcuts#
| Action | Keys |
|---|---|
| Send message | Enter |
| New line | Shift Enter |
| New chat | Ctrl K |
| Focus composer | / |
| Stop generating | Esc |
| Show shortcuts dialog | ? |
Accounts & sync#
How accounts work#
Astarter AI is guest-first: everything works with no sign-in, backed by a signed anonymous cookie used only to apply fair-use limits. Signing in with email/password, Google, or a crypto wallet creates or reaches one account tied to that method; using the same method again from any device reaches the same account. Connecting a wallet (see Wallet connect) is a full sign-in method: the first successful signature creates the account, and signing again from the same address reaches it.
Cross-device sync#
Once you are signed in, your chats (capped at 50 sessions), projects, memory, and settings sync to your account and follow you to any device where you sign in the same way. When the same data changes on two devices before they reconnect, the newer change wins by timestamp. Guests never sync; a guest's data lives only in that one browser and is gone if that browser's storage is cleared.
Wallet connect#
Wallet sign-in works from a single "Connect wallet" button on /login and in the chat header: the client requests a one-time nonce, you sign a message bound to the serving domain and your wallet address, and the server verifies the signature and mints a session the same way any other sign-in method does. Astarter AI runs on BNB Chain (BSC), so any browser-extension EVM wallet is discovered automatically through the EIP-6963 standard.
Solana wallets (Phantom, Solflare, Backpack, or any Solana wallet-standard provider) are supported as well, using the equivalent Sign-In-with-Solana standard with the same nonce-and-signature shape. On a phone, where the browser injects no wallet, open the site inside your wallet's own in-app browser and tap Connect there.
The one button covers both chains: it discovers every injected wallet and, when more than one is found, shows a small picker so you choose which to sign in with. If you dismiss the signature request in your wallet, that reads as a cancellation, not an error, and you can retry. For the cryptographic detail, see Under the hood: wallet sign-in.
Privacy#
As a guest, your chat history and settings stay in your browser and are never sent anywhere unless you sign in. Once signed in, the data you choose to sync is stored so it can follow you across devices. A signed cookie and your network address are used only to apply fair-use limits and stop abuse; a password is stored only as a salted one-way hash. When the assistant needs current information it may search the web or open a link you ask it to read; doing so shares that query or web address with a search provider and, when reading a page, a third-party reader service, the same way any browser or assistant with web access would. Your data is never used to train a model and is never sold. You can clear local data or delete your account at any time from Settings.
Support playbook#
Start here#
- Several reports around the same time? Treat it as deployment-wide. Stop user-level troubleshooting and page on-call; this is an incident, not a browser setting.
- One user, one report? This is almost always local to them: their browser, their account, or their network. Work through the basics below first.
Browser basics cover most single-user reports:
- Try an incognito or private window. It rules out extensions and stale cookies in one step.
- Confirm cookies and JavaScript are allowed for the site. The app depends on both; if either is blocked, sign-in and usage limits can fail with no visible error.
- Disable privacy or ad-blocking extensions, then reload.
- Try another browser, or another network. A VPN, or a restrictive office or school network, is a common actual cause.
Still failing after all four? Move on to Check the account first.
Check the account first#
The most common "my data is gone" report is not data loss, it is a different account. Each sign-in method is its own account, and they never merge automatically:
- Email and password is one account.
- Google is a separate account, even for the same person and the same email address.
- A wallet is its own account too, on BNB Chain (BSC) or on Solana, and a wallet account never merges with an email or Google account. A BNB Chain wallet and a Solana wallet are separate accounts from each other as well.
Before assuming anything was lost, ask which method the person used just now, and which one they used last time. Switching methods, say from Google to email and password, or from one wallet to another, lands on a brand-new, empty account; it does not carry data over from the old one. Getting them back onto the original method is usually the entire fix.
Can't sign in#
Email and password
- Sign-up rejected with an invalid-input message: the password needs at least 8 characters and the email must be a valid address.
- Sign-up says the email already exists: on a deployment with mail delivery configured, sign-up never reveals this in its response, it always answers with the same "check your email" message and just sends a different email behind the scenes, so this exact message can only appear on a deployment running in no-mail auto-verify mode. Tell the person to log in instead.
- Login fails with a generic message: that message is deliberately identical for a wrong password, an unknown email, and a locked account, so the product never confirms which one it is. After 5 failed attempts an account locks for about 15 minutes; if someone just tried several passwords in a row, waiting is often the actual fix.
- No email form appears at all: email sign-in is hidden entirely on a deployment that has not configured an identity store for it. Confirm with GET /auth/methods before assuming it is a user-side issue.
- A reset link lands on an error notice: reset tokens are single-use and expire; send a fresh "Forgot password" request.
- Button missing: Google sign-in is hidden until a deployment has all three of its settings configured and an identity store bound; a configuration gap, not something the user can fix.
- Returns with a cancelled notice: the person declined or closed the Google consent screen; try again and approve it.
- Returns with a state-mismatch notice: usually a cookie or session problem (blocked cookies, or a stale attempt reopened from browser history); retry in a normal browser window.
- Returns with a generic sign-in-failed notice: the code exchange or token check failed, which can be a transient issue on Google's side or a misconfigured redirect address on this deployment; retry once, then escalate.
Wallet. If a "Connect wallet" button is missing entirely, wallet sign-in is not configured on this deployment (the session secret is unset); confirm with GET /auth/methods. For a wallet that is present but will not connect - no extension found, a rejected signature, a stuck mobile handoff - see Wallet connect problems.
Chat and limit issues#
- Nothing streams back at all. Two cases, told apart by the error: an in-stream
ASTARTER-prefixed error (the reply began, then an upstream call failed) is usually transient and fine on retry; a pre-stream503 UNAVAILABLE(nothing streamed, a plain error) means a configuration gap on this deployment (no upstream service available, the signing secret unset, or the spend kill-switch on) and is an escalation, not something the user caused. - A daily-limit or upgrade message appears. The expected free-tier paywall: the daily allowance (per guest cookie, or per account) was reached, and it resets 24 hours after the first message that opened the window (a rolling 24-hour cycle, not a fixed daily clock time). If a signed-in user hits it unexpectedly early, check for a shared network first (office, VPN, or NAT) - a per-IP daily ceiling applies to everyone on one address, ahead of their account cap. If it still looks wrong, note the exact time and escalate.
- A too-many-requests notice after rapid sign-in or sharing. Chatting itself is bounded only by the daily allowance above, not a per-minute limit. That short-window "too many requests" limit guards the sign-in and share-link actions against rapid retries; wait about a minute and try again.
Wallet connect problems#
Wallet sign-in is live: a single "Connect wallet" button on /login and in the chat header (see Accounts & sync: Wallet connect). If someone cannot complete it, the failure modes worth knowing are:
- No "Connect wallet" button at all. Wallet sign-in is hidden on a deployment with no session secret configured; confirm with GET /auth/methods (the
walletfield). BNB Chain specifically appears only whenWALLET_EVM_ENABLEDis turned on. - "No wallet found" on desktop. No wallet extension is injected into the page. Have the person install one (any browser EVM wallet for BNB Chain, or a Solana wallet such as Phantom, Solflare, or Backpack) and reload.
- Nothing seems to happen on mobile. Mobile browsers do not inject a wallet; the person reopens the site inside their wallet's own in-app browser and taps Connect again there.
- "Connection cancelled." The person dismissed or rejected the signature request in their wallet. This is a normal cancellation, not an error; they can retry and approve it.
- "Wallet connect failed." The generic catch-all for anything else (a wallet that exposed no address, or a verify that did not succeed); retry once, then escalate with the matching audit-log event.
My chats didn't sync#
- Confirm the person is actually signed in on both devices with the same method; a guest session never syncs, by design.
- Sync merges by last-updated timestamp. A chat edited offline on one device after the other pulled a copy still resolves correctly once both are back online, but a very old, untouched local chat can appear to "vanish" if it was never pushed before local storage was cleared on the original device.
- Synced chats are capped; anything beyond the cap will not round-trip. If someone has an unusually large number of sessions, this is worth checking first.
- If sync still looks wrong after confirming sign-in state on both sides, escalate with both devices' approximate timestamps of the last known-good state.
Images won't attach#
- Rule out the basics first: is it an image file, and did the attach click, paste, or drag actually register (look for the thumbnail preview before sending)?
- If the image attaches and sends but the assistant says it cannot see it, or ignores it, that is a deployment configuration matter: image understanding is not enabled on that deployment. The user did nothing wrong, and no message was counted against their limit for it.
- Text and code files (plain text, Markdown, JSON, and similar) are read and sent with the message. Other binary files, such as PDF or Word, are declined with an "unsupported file" notice; that is expected, not a bug.
How to diagnose#
email, google, wallet (Solana, on whenever a session secret is set), and walletEvm (BNB Chain, on only with WALLET_EVM_ENABLED). Each flag drives whether that method is shown, so if a method someone expects is missing, this settles whether it is a configuration gap before you look any further.Read the server audit log. Every authentication attempt logs one structured event; here is what each means:
| Event | Meaning |
|---|---|
| login | A wallet session was minted (BNB Chain or Solana). Email and Google sign-ins log email_login and google_login instead. |
| bad_nonce | The one-time sign-in nonce was missing, expired, or failed verification. |
| bad_address | The claimed wallet address failed its format check. |
| bad_message | The signed statement text did not exactly match what the server expected (wrong origin, address, chain, or time) - what a replayed or tampered attempt looks like. |
| bad_signature | The signature did not verify against the claimed address. |
| nonce_replay | The nonce had already been used once; single-use enforcement blocked a repeat. |
| nonce_store_unavailable | The durable single-use nonce store is not bound on this deployment; production fails this closed rather than risk a replay. A deployment configuration gap, escalate it. |
| email_signup / email_signup_existing / email_signup_autologin | Outcomes of an email sign-up attempt. |
| email_verified | A verification link was used successfully. |
| email_login / email_login_fail | Outcome of a password sign-in attempt. |
| password_reset | A password reset token was redeemed. |
| google_declined / google_bad_state / google_bad_token / google_login | Outcomes along the Google sign-in flow. |
| logout | A session was revoked, including sign-out-everywhere. |
| account_deleted | An account and its data were removed. |
Error codes people may see, and what they mean:
| Code | HTTP | What it means |
|---|---|---|
| LIMIT_REACHED | 402 | Daily free-tier message allowance reached; resets 24 hours after the first message of the window. Comes with an upgrade link. |
| ACCOUNT_LIMIT | 429 | A signed-in account's own daily allowance was reached. |
| RATE_LIMITED | 429 | Too many requests in a short window; ask the person to wait about a minute. |
| PAYLOAD_TOO_LARGE | 413 | The request body exceeded its size cap. |
| AUTH_NOT_CONFIGURED | 503 | A required piece of the auth backend is not bound on this deployment; a configuration gap, escalate. |
| UNAVAILABLE | 503 | A required piece is not configured (no upstream service available, sharing, email delivery, a required binding, or the signing secret unset in production), or the spend kill-switch is on. |
| EMAIL_NOT_CONFIGURED | 503 | Email sign-in is not configured on this deployment. |
| UNAUTHENTICATED | 401 | No valid session was presented for a request that needs one. |
| FORBIDDEN | 403 | A cross-site request was blocked as a CSRF precaution. |
| NOT_FOUND | 404 | The route or resource does not exist, or, for a gated feature, is not turned on. |
| EMAIL_EXISTS | 409 | The sign-up target already has an account (only surfaced in no-mail auto-verify mode); direct the person to log in. |
| BAD_REQUEST / INVALID_INPUT / INVALID_ADDRESS / INVALID_TOKEN / INVALID_CREDENTIALS / BAD_NONCE / BAD_MESSAGE / BAD_SIGNATURE | 400 / 401 | The request was malformed, or a credential, token, or signature failed verification. |
| ASTARTER_BUSY / ASTARTER_UNAVAILABLE / ASTARTER_ERROR / ASTARTER_TIMEOUT | in stream | Delivered as an error event inside the chat stream (the HTTP response is already 200): the request reached the router, but the upstream call was busy and retryable, unavailable, errored, or timed out. |
| INTERNAL | 500 | A last-resort catch-all. Should be rare, and is always worth escalating. |
Escalation checklist#
Before escalating to engineering, collect:
- The route or endpoint involved, for example
/v1/chator/auth/email/login. - The exact error code from the response body.
- A timestamp, with time zone.
- The sign-in method in use: guest, email, Google, or wallet.
- Browser, device type, and whether an ad blocker or privacy extension is active (these can interfere with cookies or requests).
- Whether it reproduces, and on which deployment - a local or staging build versus the live site.
With those details collected, send the report to contact@astarter.io.
Under the hood#
Environment variables#
The app's server-side configuration surface, included for transparency; there is nothing here for a visitor to set up. Provider-specific key names are not listed.
| Variable | Required | What it does |
|---|---|---|
| Model service keys | One required | Each supported model service is enabled by its own API key environment variable. See .dev.vars.example in the repository root for the exact names; they are not listed here, so this reference stays generic. At least one must be set for /v1/chat to return real answers. An optional ordering variable controls fallback order across whichever services are configured. |
| Alternative cloud backend | Optional | An additional multi-model cloud backend can be enabled by its own credential set; see .dev.vars.example for the exact variable names. When configured, it takes precedence over the default provider chain. |
| CORS_ORIGINS | Optional | Comma-separated list of allowed cross-origin callers; also used as a fallback allowlist for the CSRF Origin check. |
| GUEST_COOKIE_SECRET | Required in production | Signing secret for the guest and session cookies. Without it, auth-related routes fail closed (503) in production rather than run insecurely. |
| UPGRADE_URL | Optional, default /signup | Where the free-tier paywall points. |
| GUEST_MESSAGES_PER_DAY GUEST_TOKENS_PER_DAY | Optional | Daily free-tier allowance for a guest cookie. Defaults: 10 messages, 25000 tokens. |
| IP_MESSAGES_PER_DAY | Optional, default 20 | A hard per-IP ceiling that applies regardless of account, by design. |
| MAX_OUTPUT_TOKENS | Optional, default 4096 | Per-request output cap, and the main cost lever. Falls back safely if set to an invalid value. |
| ENVIRONMENT | Optional, should be explicit in production | Set to production to require the fail-closed posture described in Security model. Any value other than a small recognized set of development values is already treated as production, so forgetting to set this is safe by default, not a silent hole. |
| SPEND_FROZEN | Optional | Global kill-switch: any truthy value stops every upstream provider call immediately, for incident response. |
| RESEND_API_KEY EMAIL_FROM APP_URL | Optional, all three together | Enables real email delivery for email sign-in (verification and reset messages). APP_URL also anchors absolute share links. Without these, email sign-in either stays hidden or runs in a no-mail auto-verify mode, depending on whether an identity store is bound. |
| GOOGLE_CLIENT_ID GOOGLE_CLIENT_SECRET GOOGLE_REDIRECT_URI | Optional, all three together | Enables Google sign-in (an identity store must also be bound). Register the exact redirect address with the OAuth client. |
| WALLET_EVM_ENABLED | Optional, default off | Enables the BNB Chain (EVM) wallet sign-in routes; only the exact value true turns them on. Anything else, including a typo, keeps those routes returning not-found. |
Architecture overview#
Astarter AI is a single Cloudflare Worker: one program running at the edge that serves every page and answers every request. There is nothing to install and no instance to run; this is the engineering picture, for readers who want it. The main pieces:
index.ts- the Worker's fetch entry point: routing, CORS, security headers, the per-response CSP nonce, and where public pages and the chat, auth, and share endpoints are wired together.config.ts- typed configuration: reads environment variables into a validated config object, including the provider list, limits, and feature flags.types.ts- shared, provider-agnostic request and event types.providers/- one thin adapter per upstream service, each normalizing its stream and errors into the shared internal event type, plus a shared server-sent-event decoder and an output-token budget helper.router.tsandcircuitBreaker.ts- retries within a provider and falls back across providers, commits to whichever provider sends the first token so a stream never flips mid-answer, and opens a cooldown breaker on a provider that keeps failing.limiter/- the free-tier ledger (pure logic, unit-tested), an in-memory fallback for single-isolate or dev use, the signed guest-cookie helper, and a Durable-Object-backed limiter for atomic cross-isolate enforcement in production.sse.ts- the streaming response boundary: builds the client-facing event stream and accounts for tokens spent.handler.ts- the chat request handler: consumes limits, calls the router, streams the answer, and records spend.policy/- the identity and system prompt, and response-safety filters described in Security model.tools/- the agentic tool loop and its registry, currently web search, web fetch, and RSS/Atom feed reading.auth/- sessions, the BNB Chain and Solana wallet verifiers, email and password auth with its own per-account lockout store, Google OAuth, a per-user Durable Object holding profile and synced data, and the shared route handlers for all of the above.pages.ts- the static marketing, legal, and auth pages, sharing one visual shell.widget.ts- the chat application itself, a large self-contained client bundle rendered as one HTML string.docs.ts- this documentation site.httpBody.ts- a streaming byte-capped body reader used everywhere a request body is read, so an unbounded upload can never exhaust memory.
Security model#
The security posture is fail-closed by default. Production is the assumed environment unless a small, explicit set of development values says otherwise, so a deployment that simply forgets to set an environment variable does not accidentally relax its protections. Durable Object bindings for rate limiting and accounts are mandatory in production rather than silently falling back to a weaker in-memory limiter.
Every HTML response carries a fresh, per-response Content-Security-Policy nonce, so only the server's own inline scripts can run. State-changing requests are checked against the browser's own forbidden Sec-Fetch-Site header first, falling back to an Origin allowlist, as CSRF defense in depth. Passwords, when email sign-in is enabled, are stored only as salted PBKDF2 hashes that never leave their single-purpose store, and every API key lives in a Worker secret, never in code, a client response, or a log.
Wallet sign-in#
BNB Chain (BSC). The product's chain. Sign-In-with-Ethereum is implemented in its own module (auth/walletEvm.ts, wired in auth/routes.ts): the client requests a one-time nonce, signs a statement bound to the exact serving domain, wallet address, chain, and the nonce's own issue time, and the server recomputes that exact statement and verifies the signature before minting a session. The nonce is single-use, consumed atomically in a per-user store so a captured signature cannot be replayed within its short window.
Solana. Supported as well, mirroring the same nonce-and-signature shape with the equivalent Sign-In-with-Solana standard and the same server-side statement recomputation. Both chains are offered in one unified "Connect wallet" picker; the EVM routes sit behind the WALLET_EVM_ENABLED config flag covered in the configuration surface above.
Current status. Wallet sign-in is enabled: a unified "Connect wallet" flow on /login and in the chat header discovers every injected wallet (EVM via the EIP-6963 standard, Solana via the known providers) and shows a small picker when more than one is present.
Reference & FAQ#
Routes and endpoints#
| Route | Method | Notes |
|---|---|---|
| / | GET | The chat app. |
| /welcome, /pricing, /login, /signup, /account, /usage, /terms, /privacy | GET | Static marketing, legal, and auth pages. |
| /docs | GET | This documentation site. |
| /manifest.webmanifest, /icon.svg, /brand.png, /brand-wide.png | GET | PWA and brand assets. |
| /.well-known/security.txt | GET | Machine-readable security contact. |
| /v1/chat | POST | The streaming chat endpoint. |
| /v1/share | POST | Create a public, read-only share snapshot. |
| /s/:id | GET | View a shared snapshot, until it expires or is missing. |
| /csp-report | POST | Browser CSP-violation reports; logging only. |
| /auth/methods | GET | Which sign-in methods are enabled on this deployment. |
| /auth/email/signup, /auth/email/login, /auth/email/forgot, /auth/email/reset, /auth/email/verify | POST / GET | Email and password sign-in. |
| /auth/google/start, /auth/google/callback | GET | Google OAuth. |
| /auth/wallet/nonce, /auth/wallet/verify | GET / POST | Solana wallet sign-in (SIWS). Live in the unified "Connect wallet" flow on /login and in the chat header. |
| /auth/wallet-evm/nonce, /auth/wallet-evm/verify | GET / POST | BNB Chain wallet sign-in. Not-found unless WALLET_EVM_ENABLED=true; when enabled it appears in the wallet picker. |
| /auth/logout | POST | Sign out, and revoke the session. |
| /v1/me | GET / DELETE | Read your synced profile and data, or delete your account. |
| /v1/me/data | PUT | Save synced data. |
Rate limits and quotas#
The defaults, read from config.ts and the limiters. Every value is configurable per deployment and is typically raised for production. Anonymous traffic is bounded by the guest and per-IP limits; a signed-in account draws on its own daily budget, still under the per-IP ceiling.
| Scope | Default | Notes |
|---|---|---|
| Guest, per anonymous cookie | 10 messages/day, 25000 tokens/day | GUEST_MESSAGES_PER_DAY, GUEST_TOKENS_PER_DAY. |
| Per IP address | 20 messages/day | IP_MESSAGES_PER_DAY. A hard ceiling for everyone from that address, guest or signed-in, so it is the effective wall from one network. |
Account on /v1/chat, Google | 200 messages/day | Per account, still bounded by the per-IP ceiling above. |
Account on /v1/chat, wallet | 50 messages/day | Per account, still bounded by the per-IP ceiling above. |
| Output per request | 4096 tokens | MAX_OUTPUT_TOKENS. The main cost lever. |
| Auth endpoints, per IP | 40 requests/min | Sign-in and account routes. |
| Password endpoints, per IP | 10 requests/min | Plus a 5-failure, 15-minute per-account lockout. |
| Share create / view, per IP | 10 / 30 requests/min | Creating versus viewing public snapshots. |
The chat API#
The one endpoint you build against. POST /v1/chat takes a JSON body and answers with a Server-Sent-Events stream. Request fields:
| Field | Type | Notes |
|---|---|---|
| messages | array, required | Up to 100. Each has a role (user or assistant) and content: a string, or an array of typed blocks (text or image). Up to 20000 characters per message and 60000 across the request; up to 8 images totalling 10 MB. |
| mode | string | Optional, default auto. One of auto, fast, or expert. |
| customInstructions | string | Optional, up to 2000 characters. Standing guidance, applied behind the identity lock. |
| memory | string array | Optional, up to 50 items of up to 200 characters each. |
The response is a text/event-stream; each event is one of:
tokengives{ "text": "..." }, a chunk of the answer as it streams.toolgives{ "id", "name", "status", "ok", "arg" }, the progress of an agentic tool call (the tool's own name only, never a model or provider).donegives{ "model": "astarter-1" }; the public model id is always the aliasastarter-1.errorgives{ "code": "..." }, a masked code from the table above.
Every streamed response also carries an x-astarter-remaining header with the caller's remaining daily message count. When the allowance is spent, the endpoint returns 402 with { error: { code: "LIMIT_REACHED", remainingMessages, upgradeUrl } } (or 429 ACCOUNT_LIMIT for a signed-in account) instead of a stream.
curl -N https://<deployment>/v1/chat \
-H 'content-type: application/json' \
-d '{"messages":[{"role":"user","content":"Hello"}],"mode":"auto"}'const res = await fetch("https://<deployment>/v1/chat", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
messages: [{ role: "user", content: "Hello" }],
mode: "auto",
}),
});
// res.body streams Server-Sent Events: event: token / done / error
const reader = res.body.getReader();import requests
r = requests.post(
"https://<deployment>/v1/chat",
json={"messages": [{"role": "user", "content": "Hello"}], "mode": "auto"},
stream=True,
)
for line in r.iter_lines():
if line:
print(line.decode()) # event: token / done / errorevent: token
data: {"text":"Hi"}
event: done
data: {"model":"astarter-1"}To see which sign-in methods a deployment has enabled, GET /auth/methods returns four booleans:
{ "wallet": true, "walletEvm": false, "email": true, "google": false }Keyboard shortcuts#
| Action | Keys |
|---|---|
| Send message | Enter |
| New line | Shift Enter |
| New chat | Ctrl K |
| Focus composer | / |
| Stop generating | Esc |
| Show shortcuts dialog | ? |
FAQ#
Is Astarter AI free?
Yes. The free tier needs no account and no card, with a daily message allowance that resets 24 hours after your first message.
Do I need an account?
No. Everything works as a guest; sign in only to sync across devices.
Can I sign in with a crypto wallet?
Yes. A "Connect wallet" button on /login and in the chat header signs you in with a BNB Chain (BSC) wallet, or a Solana wallet; if more than one is detected, you get a picker. See Wallet connect.
What does multi-model routing mean?
Requests are routed across multiple upstream services with automatic failover, so a single outage does not interrupt you.
What happens when I hit my daily limit?
New messages pause until the allowance resets, 24 hours after your first message in the current window. Signing in helps: an account has its own, higher daily allowance separate from the guest bucket (see Rate limits and quotas), though a per-address ceiling still applies.
Does the assistant train on my conversations?
No. Your inputs are never used to train a model; see the Privacy Policy for the full data-handling picture.
Where do I report a bug?
Email contact@astarter.io with the details from the escalation checklist so the report has what is needed to reproduce it. For a security issue specifically, the machine-readable contact is at /.well-known/security.txt.
