Skip to content
raydocsPublic

About

Fells.dev: Astro main site, Synara landing, and Apple Launch theme prototypes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

fells.dev

Fells marketing site and customer console. The existing UI now connects to the fells-api backend through same-origin HTTP APIs for accounts, API keys, usage, billing, workspace/chat storage and online support.

Cloud computers, environment controls, workspace files, Canvas, plugins, user sites and scheduled tasks have been removed from the product UI and public routes. The remaining workspace feature stores conversations and manages members; it does not execute agents. The static marketing catalog is reference data, not an inventory of products on sale.

Development

Use Node 24+ and the pnpm version pinned in package.json.

pnpm install
pnpm dev       # http://127.0.0.1:4321
pnpm test      # adapter, state/schema, local-storage and theme unit tests
pnpm build     # astro check + static build to dist/

Open the Fells frontend at http://127.0.0.1:4321/zh/app/start for the customer login, or /app/start for English. The other locale prefixes are /zh-hant/, /ja/, /ko/ and /es/. The backend process listens on http://127.0.0.1:18080; it supplies APIs and does not require opening a separate user portal. The former /portal/ customer pages return 404.

astro.config.mjs proxies /api/app, /api/support and /v1 to the local backend while preserving the browser Host and Origin. Keep frontend requests same-origin so server cookies and origin checks work. The backend must use an independent local PostgreSQL database with configured test accounts; the frontend does not seed users or connect directly to a database.

The static build needs an equivalent same-origin API reverse proxy in production; astro preview or a static file server alone does not supply authentication or business services. Configure the backend's email, payment information, model upstreams and offered subscriptions separately. An unconfigured service displays its actual unavailable state.

Where things live

What File
Landing copy, 6 languages src/i18n/{en,zh,zh-hant,ja,ko,es}.ts (same shape, type-checked)
Inner-page copy, 6 languages src/i18n/pages/*.ts (PagesDict)
Inner pages src/components/pages/*Page.astro, routes in src/pages/ and src/pages/[lang]/
Static marketing channels, product examples and price calculations src/data/catalog.ts
Public contact email src/site.ts
Real login, signup and password reset src/components/pages/AuthPage.astro
Real CNY wallet, USD allowance and subscription Checkout src/components/pages/CheckoutPage.astro
Same-origin HTTP transport and account/billing DTOs src/lib/app-http.ts, src/lib/account-api.ts
Console persistence, workspace roles and session binding src/lib/app-service.ts
Console rendering, copy and design examples src/scripts/app.ts, src/i18n/app/*.ts, src/data/app.ts
Online support DTOs and HTTP adapter src/lib/support-api.ts, src/lib/support-http.ts, src/lib/support-service.ts
Local-only storage used by unit tests src/lib/preview-store.ts, src/lib/support-store.ts
Development API proxy astro.config.mjs
Section order src/components/Landing.astro
Design tokens (colors, radius, fonts) src/styles/global.css
AI, vendor and plugin icons src/data/icons.ts, SVGs in src/data/brand-icons.ts

Accounts and console

/app/start is a real account entry with password login, email-code registration and password reset. Registration collects a separate login username (3–32 lowercase letters, digits, underscores or hyphens) and a verified email address. It uses the current server agreement and any configured verification challenge. If email delivery is not configured, the UI reports that failure; it does not create a preview identity. Already authenticated users continue to their requested console or Checkout page.

Terms open in a modal dialog using the current UI language (Chinese or English server text), and consent stays an explicit checkbox. Server markup is displayed as safe text. On desktop, the left artwork stays fixed while a long account form scrolls within the right panel. The public authentication configuration reports email_enabled without exposing mail credentials; unavailable email disables registration/reset code sending while existing accounts can still sign in with a password.

/app preserves the existing onboarding, sidebar, hash routes, settings, dialogs, mobile drawer and theme choices. The server is the source of user identity, permissions, API keys and money. Current capabilities are:

Area Current behavior
Profile, avatar, preferences and notification switches Real authenticated server reads and writes
API keys and per-key limits Real server keys and limit settings, subject to the account's self-service permission
Usage, request logs and model catalog Real account-scoped API data; no example traffic is inserted
Wallet and API allowance Separate CNY cash/grant and USD API balances from the backend
Workspace and chat history Real creation, settings, saved user messages, explicit history import, editing and deletion
Workspace members Consent-based: the owner sends an in-console invitation (editor/viewer) that the invitee accepts or declines from Invitations; members can leave. The owner sees masked pending invitations and can cancel them. Invites always answer “sent” and never confirm that an account exists; no email is sent. Other members appear by their chosen name or Member #<id>, never by email or phone
Customer support Real server conversations, attachments, read status and events
Example workspace and marketing/model-picker examples Read-only design data, not an executing workspace or a server product offer
Cloud computer, environment controls, files, Canvas, plugins, user sites and scheduled tasks Removed from the product UI and public routes

Saving a chat instruction is not an Agent execution result. The app does not fabricate Agent responses, task completion, uploads, installation or payments.

The connected pages do not use IndexedDB as account, billing or support storage. The old preview stores remain for explicit local-storage unit tests. Per-tab workspace selection and an uncertain Checkout operation's idempotency key may be kept in sessionStorage; neither is an authentication credential.

Session boundaries

Authentication uses backend-issued HttpOnly cookies. Private requests bind to the user ID and session_id returned by /api/app/bootstrap, so an old page cannot write under a new account or a replaced session. Same-page events and BroadcastChannel('fells.session.changed') notify other tabs; server validation also applies when browser notifications are unavailable. Logout revokes the real server session. Pending requests are cancelled or their late results discarded when the account changes.

public/_headers supplies framing, referrer and content-type protections on hosts that support that file. Other hosts need equivalent response headers: Content-Security-Policy: frame-ancestors 'none'; base-uri 'self'; object-src 'none', X-Frame-Options: DENY, Referrer-Policy: no-referrer, and X-Content-Type-Options: nosniff. The same file sets Cache-Control: public, max-age=0, s-maxage=3600 on HTML (paths ending in /) and a one-year immutable cache on /favicon.svg, /favicon-32.png, /apple-touch-icon.png, and /og.png. Hashed /_astro assets are left to the host default. On Cloudflare, HTML still needs a Cache Everything rule, and Email Obfuscation plus managed robots.txt must be off. Account and console pages also refuse to activate inside frames. Local checks do not establish a production host's configuration.

Billing and Checkout

Checkout follows the backend's existing rules and offers, rather than the static marketing catalog:

  • CNY wallet: cash and promotional grant are displayed separately. Alipay top-up creates a real recharge request. Confirming that a payment was made does not fabricate approval, deposit money or automatically buy a service.
  • USD API allowance: a configured one-time CNY cash exchange creates a separate USD API quota with the server's price and validity. It is not a monthly Token Plan guarantee or idle-capacity burst product. CNY and USD balances are never added together.
  • Subscriptions: available pools, shared tiers, prices, capacity and held subscriptions come from the server. Purchases use the backend month rules; buying 12 months does not add an annual discount. Checkout sends the confirmed maximum CNY charge, and a changed price requires another user confirmation.
  • Unavailable products: legacy Token Plan/g2/g5/g10 marketing links, product CDKs and marketplace-order delivery cannot silently purchase a different product. Missing products or payment configuration are reported explicitly.

Current entry parameters are /checkout?mode=wallet, ?mode=allowance and ?mode=subscription&pool=<server-pool-id>&tier=<server-tier>. The CDK tab remains visible with an unavailable message. Old plan, seat or sku parameters require an explicit choice of an actual server offer.

Financial requests carry a stable Idempotency-Key. A network retry or reload reuses the original identity, payload and key. An uncertain server result remains pending for reconciliation; the UI does not automatically create a new purchase. A successful result is shown only after server confirmation.

Online support

The bottom-right customer window uses same-origin /api/support for real text and image messages, persisted conversations, read positions and status. Customer sessions cannot access the operator desk. Operators use a separately configured private entry and a separate backend-authenticated HttpOnly cookie; operator login/logout does not replace the customer session.

Configure the build-only SUPPORT_PORTAL_PATH in gitignored .env.local or the build environment. It accepts 2–5 lowercase English words joined with hyphens, 2–16 letters per word, without a conflict with public routes. Do not use a PUBLIC_ prefix or commit the real value. Without it, operator pages are omitted. The customer widget does not expose the entry. Private pages omit public URL metadata and third-party fonts, and use noindex,nofollow,noarchive. Changing the entry requires replacing the full build output, including old private pages.

The URL itself grants no permissions: the backend authorizes each request and binds it to the selected customer/operator session. Real SSE carries updates; messages use UUID retries and uploaded attachment IDs. Current online/typing leases are held in a single backend instance's memory, so multi-instance operation needs shared leases and event transport.

See the support integration contract and test configuration.

Archived design sources

The old /themes/ preview routes are no longer published. Their source HTML and assets remain under templates/ for reference; those files describe concepts, not available Fells features.

The marketing section order is promo bar → nav → hero → client marquee → Token Plan → group buy → model/provider introduction → pay-as-you-go examples and marketplace → Developer API → clients → security → FAQ → referral → blog → account CTA → footer. Static prices, quotas and discounts are computed from src/data/catalog.ts and translated with deal(); these are presentation examples, not billing authority.

Public inner pages include /market, /developer-api, /security, /faq and /blog, in all six languages. Use link(t, "market") for locale-aware links.

The app keeps light/dark/system themes, ⌘K navigation and mobile controls. Its client/model selector records conversation metadata; messages are saved without running an agent. The read-only workspace example is design data. Account spending protection, a default PAYG channel and monthly credits products have no matching current service and remain unavailable. Every effect uses CSS transforms or gradients, with no canvas/WebGL requirement; motion respects prefers-reduced-motion.

Tests

pnpm exec playwright install chromium  # once, if no existing Chrome is available
pnpm test                             # unit/adapter/local-store tests
pnpm test:browser                     # built dist/ + browser regressions
pnpm test:all                         # build + unit tests + browser regressions

Browser tests use ephemeral browser contexts and loopback servers. Set PLAYWRIGHT_CHROMIUM_EXECUTABLE to use an existing browser. Build first for tests that serve dist/. Auth/Checkout and support HTTP-contract tests use test-only API fixtures; production pages still use real HTTP. Operator-page contract cases require SUPPORT_PORTAL_PATH at build time.

The security browser suite uses a real local API and writes test data. Before pnpm test:browser or pnpm test:all, prepare a separate local PostgreSQL test environment (testenv), start its backend, and seed two disposable customer accounts with API-key self-service enabled. Set FELLS_BACKEND_ORIGIN (default loopback port 18080), FELLS_BROWSER_USER, FELLS_BROWSER_USER2 and FELLS_BROWSER_PASSWORD in that local test environment. Do not use a production database or a person's active account. The suite exercises real persistence, permissions, cross-tab session replacement and logout, and cleans up its own workspaces/keys and restores tested preferences. A missing backend or test account is a failure, not a successful mocked security check.

tests/browser/support-live.test.mjs is an additional opt-in live customer/desk regression. Supply FELLS_LIVE_TEST=1, FELLS_LIVE_TEST_PASSWORD and isolated customer/operator accounts; optional FELLS_BROWSER_BASE, FELLS_TEST_USER, FELLS_TEST_OPERATOR and FELLS_TEST_SUPPORT_PORTAL select that environment. It accepts loopback addresses only. Keep these settings and the operator entry out of committed files. Backend transaction and permission regressions run separately against its isolated PostgreSQL test database.

Issue #1 remediation records the earlier local-preview security work; it is historical coverage, not a description of the current connected authentication flow.

Before launch

  • Deploy the static frontend and same-origin API proxy to 36.33.98.85; verify the app routes, retired routes, API proxy response, and production headers.
  • Enable HTTPS with a trusted IP certificate and verify production cookie/origin behavior before using login or payment flows. On 2026-10-12, Let's Encrypt HTTP-01 and TLS-ALPN-01 validation both timed out from the issuer network; see reports/frontend-backend-audit-2026-10-12.md.
  • Configure and verify real email delivery, verification challenges, server agreements, payments, API upstreams and subscription offers. Keep missing services visibly unavailable.
  • Replace static marketing prices, quotas, channel metrics, referral amounts and product claims with the actual offers before presenting them as on sale. Configure real shop delivery/CDK services before enabling those flows.
  • Add payment reconciliation/fulfillment and recovery for uncertain pending operations before promising automatic payment-to-service delivery.
  • For multiple backend instances, share support leases and event transport.
  • Verify public contact details and publish the blog posts or keep their unavailable labels.
  • Run adapter, real local security/browser and backend database regressions against the release build with an isolated test environment.
  • Preserve third-party icon licenses: LobeHub Icons (@lobehub/icons-static-svg, MIT) and Simple Icons (CC0); logos remain their owners' trademarks.

About

Fells.dev: Astro main site, Synara landing, and Apple Launch theme prototypes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages