-
Notifications
You must be signed in to change notification settings - Fork 607
[feat] Scaffold the mobile web app at /m (1/12) #5679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ardaerzin
wants to merge
9
commits into
main
Choose a base branch
from
feat/mobile-app-scaffold
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,126
−34
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9800eaa
docs(mobile): add agent instructions and skills for the mobile app
ardaerzin 50461c0
feat(mobile): scaffold @agenta/mobile Next.js app mounted at /m
ardaerzin 2e17bc5
feat(mobile): add shadcn foundation, palette token bridge, and motion…
ardaerzin 538caca
fix(mobile): harden token bridge and motion presets after review
ardaerzin dc182e3
feat(mobile): add eslint config with antd and app-layer import bans
ardaerzin 6f3040c
fix(mobile): enforce react-hooks rules and ban lexical imports
ardaerzin e688d01
feat(mobile): wire web-mobile dev compose service behind Traefik /m
ardaerzin 1cdc2d4
feat(mobile): add production gh Dockerfile for web-mobile (build wiri…
ardaerzin 2be5bd8
fix(mobile): keep the manifest in the mobile build's cache key
ardaerzin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| --- | ||
| name: mobile-app-structure | ||
| description: Feature-folder layout, states/ convention, and data-flow rules for the Agenta mobile app (web/mobile). Use when creating or moving files under web/mobile, deciding where a component lives, adding a new feature or screen, or wiring data into mobile components. | ||
| --- | ||
|
|
||
| # Mobile app structure | ||
|
|
||
| The source of truth for how code is organized in `web/mobile`. Load it before | ||
| creating any file there. | ||
|
|
||
| ## Layout | ||
|
|
||
| ```text | ||
| web/mobile/ | ||
| src/ | ||
| pages/ # Pages Router route shells ONLY — no logic, no layout JSX | ||
| features/ | ||
| <feature>/ # e.g. sessions/, chat/, auth/, project-drawer/ | ||
| <Component>.tsx # one component per file, named export = file name | ||
| states/ # designed states for this feature | ||
| <X>Skeleton.tsx # mirrors the final layout geometry (no shift on swap) | ||
| <X>Empty.tsx # designed empty state with a call to action | ||
| <X>Error.tsx # error + retry affordance; preserves user input | ||
| components/ui/ # shadcn registry components (see mobile-shadcn-conventions) | ||
| lib/ # cn util, motion presets, api glue, context resolution | ||
| styles/ # globals.css, theme.generated.css (generated) | ||
| scripts/ # generate-shadcn-tokens.ts (token bridge) | ||
| ``` | ||
|
|
||
| ## Rules | ||
|
|
||
| - **Pages are thin shells.** A page file resolves route params and renders one | ||
| feature screen component. Anything else belongs in `features/`. | ||
| - **One component per file.** No secondary exported components; small private | ||
| helpers inside a file are fine if they never leave it. | ||
| - **Every data-bearing component has designed states.** Before writing the | ||
| happy path, create the `states/` siblings (skeleton, empty, error). A screen | ||
| is not done if any of its states is a browser default or an unstyled string. | ||
| - **Data flow:** components get data via hooks from `@agenta/*` packages | ||
| (`@agenta/entities`, `@agenta/shared`, later `@agenta/chat`) or thin fetchers | ||
| in `lib/`. NEVER import `@/oss/*`, `@agenta/oss`, `@agenta/ee` — the mobile | ||
| app has zero app-layer imports (lint enforces this). | ||
| - **No provider fleet.** `_app.tsx` stays minimal; add a provider only when a | ||
| concrete feature needs it, scoped as narrowly as possible. | ||
|
|
||
| ## Adding a new feature (checklist) | ||
|
|
||
| 1. Create `src/features/<feature>/` with the screen component. | ||
| 2. Create `states/` siblings for every data-bearing component. | ||
| 3. Add the route shell in `src/pages/` that renders the screen. | ||
| 4. Use `useMotionPresets()` for any transitions (see mobile-motion-patterns). | ||
| 5. `pnpm --filter @agenta/mobile lint && pnpm --filter @agenta/mobile types:check`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| --- | ||
| name: mobile-motion-patterns | ||
| description: Motion design rules for the Agenta mobile app (web/mobile) — the shared presets in src/lib/motion, when to animate, and reduced-motion requirements. Use when adding any animation or transition under web/mobile, animating navigation, sheets, skeletons, or list/chat surfaces. | ||
| --- | ||
|
|
||
| # Mobile motion patterns | ||
|
|
||
| All animation in `web/mobile` uses the `motion` package through the shared | ||
| presets module `src/lib/motion/presets.ts`. Components never define their own | ||
| durations, easings, or springs. | ||
|
|
||
| ## The presets | ||
|
|
||
| Consume via the hook (reduced-motion aware — this is mandatory): | ||
|
|
||
| ```tsx | ||
| import {useMotionPresets} from "@/lib/motion/presets" | ||
|
|
||
| const {sharedAxisPush, sheetSlideUp, crossfade, reduced} = useMotionPresets() | ||
| ``` | ||
|
|
||
| - **`sharedAxisPush`** — list → chat navigation (and any parent → child screen | ||
| push). Forward uses `custom={1}`, back uses `custom={-1}`; the back | ||
| gesture/button reverses the same preset. Wrap sibling screens in | ||
| `<AnimatePresence custom={direction} initial={false}>`. | ||
| - **`sheetSlideUp`** — spring-based bottom sheets (project drawer). Pair with a | ||
| `crossfade` scrim. | ||
| - **`crossfade`** — skeleton → content swaps. Skeleton and content must occupy | ||
| identical geometry so the fade causes zero layout shift. | ||
|
|
||
| ## Rules | ||
|
|
||
| - **Animate navigation, containment, and state swaps — not decoration.** No | ||
| attention-seeking motion, no animating properties that trigger layout | ||
| (animate `transform`/`opacity` only). | ||
| - **Reduced motion is not optional.** `useMotionPresets()` returns instant | ||
| variants when `prefers-reduced-motion` is set; any animation built outside | ||
| the presets module must justify itself in review AND handle reduced motion | ||
| itself (prefer extending the presets module instead). | ||
| - **Message entrance/streaming** (WP3b+): subtle and consistent with the | ||
| playground's feel — entrance is a small fade/rise on the preset tokens; text | ||
| streaming is never per-character animated. | ||
| - New shared patterns go INTO `presets.ts` (one exported preset + doc comment), | ||
| not into a component file. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| --- | ||
| name: mobile-shadcn-conventions | ||
| description: How the Agenta mobile app (web/mobile) installs and extends shadcn/ui registry components, themes them via the palette token bridge, and uses Vercel AI Elements. Use when adding UI components under web/mobile, changing theme colors, editing components.json or globals.css, or building chat UI with AI Elements. | ||
| --- | ||
|
|
||
| # Mobile shadcn conventions | ||
|
|
||
| `web/mobile` uses shadcn/ui on Tailwind v4 with CSS variables. No antd, ever. | ||
|
|
||
| ## Installing registry components | ||
|
|
||
| - Always install via the CLI from `web/mobile/`: | ||
| `pnpm dlx shadcn@latest add <component>` (e.g. `button`, `sheet`, `dialog`, | ||
| `command`, `skeleton`, `input`). | ||
| - Components land in `src/components/ui/` (aliases in `components.json`). They | ||
| are owned code: you may adapt them, but keep diffs minimal and expressed in | ||
| semantic tokens so upstream refreshes stay cheap. | ||
| - The CLI adds any peer deps (e.g. `@radix-ui/react-slot`) to | ||
| `web/mobile/package.json` — commit the manifest and `web/pnpm-lock.yaml` | ||
| changes together with the component. | ||
| - Never copy component source from the shadcn website by hand; the CLI resolves | ||
| the Tailwind v4 variant correctly. | ||
| - Installing a shadcn component that references a NEW token (e.g. `bg-sidebar`, | ||
| `chart-*`) requires extending VARS in `scripts/generate-shadcn-tokens.ts` + | ||
| the `@theme inline` map in `globals.css` first — Tailwind v4 silently | ||
| generates nothing for unmapped tokens. | ||
|
|
||
| ## Theming — the token bridge | ||
|
|
||
| - shadcn variables (`--background`, `--primary`, ...) are NOT hand-maintained. | ||
| They are generated into `src/styles/theme.generated.css` from | ||
| `web/oss/src/styles/theme/palette.ts` by `scripts/generate-shadcn-tokens.ts`. | ||
| - To change a color: edit `palette.ts` (if the design-system value is wrong) or | ||
| the ROLE MAP in the script (if the mapping is wrong), then run | ||
| `pnpm --filter @agenta/mobile generate:tokens` and commit the regenerated CSS. | ||
| - Never edit `theme.generated.css` directly; never introduce raw hex values in | ||
| components — if a needed role is missing, extend the bridge. | ||
| - Dark mode is the `.dark` class on `<html>` (`@custom-variant dark` in | ||
| `globals.css`), set pre-paint by the `_document.tsx` init script from the | ||
| shared `agenta-theme` localStorage key. Both themes must be checked for every | ||
| new surface. | ||
|
|
||
| ## Extending components | ||
|
|
||
| - Wrap, don't fork: feature-specific variants live in `src/features/*` as thin | ||
| wrappers over `components/ui/*` primitives (cva variants where appropriate). | ||
| - Use the `cn` util from `@/lib/utils` for all class merging. | ||
|
|
||
| ## Vercel AI Elements (chat render layer, WP3b+) | ||
|
|
||
| - AI Elements are shadcn registry components; install them the same way | ||
| (`pnpm dlx shadcn@latest add <ai-elements registry item>`), landing in | ||
| `src/components/ui/` / `src/components/ai-elements/` per the registry config. | ||
| - They are the base of the chat skin (Conversation, Message, Response, | ||
| Reasoning, Tool, PromptInput); behavior comes from `@agenta/chat` hooks — | ||
| never re-implement orchestration inside a rendered component. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../.agents/skills/mobile-app-structure |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../.agents/skills/mobile-motion-patterns |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../.agents/skills/mobile-shadcn-conventions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .next/ | ||
| .turbo/ | ||
| tsconfig.tsbuildinfo | ||
| # runtime config written by web/entrypoint.sh (dev mounts this dir from the host) | ||
| public/__env.js |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Agenta Mobile (`web/mobile`) conventions | ||
|
|
||
| Greenfield mobile web app served at `/m` (Next.js Pages Router, `basePath: "/m"`, | ||
| standalone output). This is the always-loaded instruction layer for work under | ||
| `web/mobile`. The general frontend conventions in `web/AGENTS.md` (Fern client, | ||
| state management, React practices) still apply EXCEPT where this file overrides | ||
| them — styling and import rules here are deliberately different. Design doc: | ||
| `docs/design/agenta-mobile/design.md`. | ||
|
|
||
| ## Hard rules (lint-enforced — see `eslint.config.mjs`) | ||
|
|
||
| - **No antd. Ever.** No `antd`, `@ant-design/*`, `@ant-design/x`, no Lexical. | ||
| UI comes from shadcn/ui components in `src/components/ui/` and (for chat, | ||
| WP3b+) Vercel AI Elements. Icons come from `lucide-react`. | ||
| - **No app-layer imports.** Never import `@/oss/*`, `@agenta/oss`, or | ||
| `@agenta/ee`. Data and state come from the `@agenta/*` packages only | ||
| (`@agenta/entities`, `@agenta/shared`, `@agenta/chat` when it exists). | ||
| - **One component per file**, exported with a name matching the file name. | ||
| - **No slab components.** Pages under `src/pages/` are thin route shells only; | ||
| each feature is a folder of small single-purpose components. | ||
|
|
||
| ## Structure | ||
|
|
||
| ```text | ||
| web/mobile/src/ | ||
| pages/ # thin route shells only (Pages Router) | ||
| features/<feature>/ # SessionCard.tsx, SessionSearchBar.tsx, ... one component per file | ||
| states/ # Skeleton.tsx, Empty.tsx, Error.tsx — designed sibling states | ||
| components/ui/ # shadcn registry components (installed, then owned) | ||
| lib/ # motion presets, cn util, api glue — no JSX except tiny helpers | ||
| styles/ # globals.css + theme.generated.css (generated, committed) | ||
| ``` | ||
|
|
||
| ## States are designed, not defaulted | ||
|
|
||
| Every screen and every data-bearing component defines loading, empty, error | ||
| (and partial, where relevant) states as first-class sibling components in the | ||
| feature's `states/` folder. Skeletons mirror the final layout geometry so | ||
| content replaces them without shift. Errors carry a retry affordance and never | ||
| lose entered state (a failed send never loses the draft). | ||
|
|
||
| ## Motion | ||
|
|
||
| All animation uses the `motion` package through the shared presets in | ||
| `src/lib/motion/presets.ts`, consumed via `useMotionPresets()` (reduced-motion | ||
| aware). Never hardcode durations, easings, or springs in components. Load the | ||
| `mobile-motion-patterns` skill before writing any animation code. | ||
|
|
||
| ## Styling and theming | ||
|
|
||
| - Tailwind v4, CSS-first config in `src/styles/globals.css`. No | ||
| `tailwind.config.*` file exists on purpose. | ||
| - Style exclusively with the semantic tokens (`bg-background`, | ||
| `text-muted-foreground`, `border-border`, ...). Never hardcode hex/rgb values | ||
| in components. | ||
| - The color source of truth is `web/oss/src/styles/theme/palette.ts`, bridged | ||
| by `scripts/generate-shadcn-tokens.ts` into `src/styles/theme.generated.css` | ||
| (committed, never hand-edited). To change a color: edit `palette.ts` or the | ||
| role map in the script, then run `pnpm --filter @agenta/mobile generate:tokens`. | ||
| - Dark mode is class-based (`.dark` on `<html>`), keyed off the same | ||
| `agenta-theme` localStorage value as the desktop app. | ||
|
|
||
| ## shadcn registry workflow | ||
|
|
||
| Install or update registry components with `pnpm dlx shadcn@latest add <name>` | ||
| run from `web/mobile/`. Installed components live in `src/components/ui/` and | ||
| are owned code — adapt them, but keep diffs from upstream minimal and | ||
| token-driven. Load the `mobile-shadcn-conventions` skill for the full workflow. | ||
|
|
||
| ## Skills to load when working here | ||
|
|
||
| - `mobile-app-structure` — feature folders, `states/` convention, data-flow rules. | ||
| - `mobile-shadcn-conventions` — registry workflow, theming bridge, AI Elements. | ||
| - `mobile-motion-patterns` — shared presets, when to animate, reduced motion. | ||
|
|
||
| Also use the plugin skills when relevant: `vercel:nextjs` (Pages Router | ||
| specifics), `vercel:shadcn`, `vercel:react-best-practices`. | ||
|
|
||
| ## Commands (run from `web/`) | ||
|
|
||
| - Dev: `pnpm dev-mobile` (→ http://localhost:3000/m) | ||
| - Build: `pnpm build-mobile` | ||
| - Lint / types: `pnpm --filter @agenta/mobile lint` / `pnpm --filter @agenta/mobile types:check` | ||
| - Token bridge: `pnpm --filter @agenta/mobile generate:tokens` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| AGENTS.md |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.