@mindstudio-ai/remy 0.1.69 → 0.1.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,31 +1,147 @@
1
- # Roles & Auth
1
+ # Auth
2
2
 
3
- MindStudio apps use role-based access control. Roles are defined in the manifest, assigned to users in the editor, and enforced in methods. The backend is the authority methods enforce access control via `auth.requireRole()`. The frontend can read roles for conditional rendering, but enforcement always happens server-side.
3
+ MindStudio apps can have and manage their own users. Auth is opt-in: configure it in the manifest, define a user table, and build your own login UI. The platform handles verification codes, cookies, and session management. Apps without auth config use anonymous guest sessions (current default behavior).
4
4
 
5
- **Roles are optional.** Many apps don't need them — single-user apps, internal tools, simple utilities. If the app doesn't have multiple user types with different permissions, skip roles entirely. Only add them when the app explicitly needs to distinguish who can do what.
5
+ **Auth is optional.** Many apps don't need it. Only add auth when the app needs to identify users or restrict access.
6
6
 
7
- ## Defining Roles
8
-
9
- In `mindstudio.json`:
7
+ ## Manifest Config
10
8
 
11
9
  ```json
12
10
  {
11
+ "auth": {
12
+ "enabled": true,
13
+ "methods": ["email-code", "sms-code"],
14
+ "table": {
15
+ "name": "users",
16
+ "columns": {
17
+ "email": "email",
18
+ "phone": "phone",
19
+ "roles": "roles"
20
+ }
21
+ }
22
+ },
13
23
  "roles": [
14
- { "id": "requester", "name": "Requester", "description": "Can submit vendor requests and purchase orders." },
15
- { "id": "approver", "name": "Approver", "description": "Reviews and approves purchase orders." },
16
- { "id": "admin", "name": "Administrator", "description": "Full access to all app functions." },
17
- { "id": "ap", "name": "Accounts Payable", "description": "Processes invoices and payments." }
24
+ { "id": "vendor", "name": "Vendor" },
25
+ { "id": "buyer", "name": "Buyer" },
26
+ { "id": "admin", "name": "Admin" }
18
27
  ]
19
28
  }
20
29
  ```
21
30
 
22
- - `id`kebab-case, used in code (`auth.requireRole('admin')`)
23
- - `name`display name shown in the editor
24
- - `description` — what this role can do (useful for the agent and for users in the role assignment UI)
31
+ - **`auth.enabled`**opt-in. No auth config = anonymous guest sessions.
32
+ - **`auth.methods`**which verification methods the app supports. At least one required.
33
+ - `email-code` — 6-digit code sent via email
34
+ - `sms-code` — 6-digit code sent via SMS
35
+ - **`auth.table.name`** — name of the `defineTable` table that holds user records.
36
+ - **`auth.table.columns`** — maps platform-managed fields to column names in the developer's table.
37
+ - `email` — required if `email-code` is in methods
38
+ - `phone` — required if `sms-code` is in methods
39
+ - `roles` — optional. Maps to a JSON array column for role assignments.
40
+ - **`roles`** — declares valid roles for the app. Same as before: `id`, `name`, optional `description`.
41
+
42
+ ## Auth Table
43
+
44
+ The user table is a regular `defineTable` table. The platform manages the auth-mapped columns; all other columns are the developer's domain.
45
+
46
+ ```typescript
47
+ import { db } from '@mindstudio-ai/agent';
48
+
49
+ export const Users = db.defineTable<{
50
+ // Mapped to auth — platform keeps these in sync
51
+ email: string;
52
+ phone?: string;
53
+ roles: string[];
54
+ // Developer's own fields
55
+ displayName: string;
56
+ plan: 'free' | 'pro';
57
+ avatarUrl?: string;
58
+ }>('users');
59
+ ```
60
+
61
+ ### Platform-Managed Column Behavior
62
+
63
+ - **`email` / `phone`** — read-only from code. Writing via `update()` or `push()` throws a `MindStudioError`. Use the auth API to change a user's email or phone.
64
+ - **`roles`** — read/write from both code and the dashboard. `Users.update(userId, { roles: ['admin'] })` works and syncs to the platform. Dashboard role changes sync back to the table.
65
+ - All other columns are fully the developer's.
66
+
67
+ ## Frontend Auth (Interface SDK)
68
+
69
+ The developer builds their own login/signup UI. The SDK provides methods that handle the verification flow and session management.
70
+
71
+ ```typescript
72
+ import { auth } from '@mindstudio-ai/interface';
73
+ ```
74
+
75
+ ### User Shape
25
76
 
26
- Roles are synced to the platform on deploy. Adding or removing roles in the manifest creates or deletes them on the next push.
77
+ ```typescript
78
+ interface AppUser {
79
+ id: string;
80
+ email: string | null;
81
+ phone: string | null;
82
+ roles: string[];
83
+ createdAt: string;
84
+ }
85
+ ```
86
+
87
+ `auth.getCurrentUser()` returns `AppUser | null`. `null` means unauthenticated.
88
+
89
+ ### State (sync)
90
+
91
+ ```typescript
92
+ auth.getCurrentUser() // AppUser | null
93
+ auth.isAuthenticated() // boolean
94
+ ```
95
+
96
+ ### Email Code Flow
97
+
98
+ ```typescript
99
+ const { verificationId } = await auth.sendEmailCode('user@example.com');
100
+ // User enters the 6-digit code from their email
101
+ const user = await auth.verifyEmailCode(verificationId, '123456');
102
+ // user is now authenticated — auth.getCurrentUser() returns the AppUser
103
+ ```
104
+
105
+ ### SMS Code Flow
106
+
107
+ ```typescript
108
+ const { verificationId } = await auth.sendSmsCode('+15551234567');
109
+ const user = await auth.verifySmsCode(verificationId, '123456');
110
+ ```
27
111
 
28
- ## Backend Auth API
112
+ ### Email/Phone Changes (must be authenticated)
113
+
114
+ ```typescript
115
+ await auth.requestEmailChange('newemail@example.com');
116
+ const user = await auth.confirmEmailChange('newemail@example.com', '123456');
117
+
118
+ await auth.requestPhoneChange('+15559876543');
119
+ const user = await auth.confirmPhoneChange('+15559876543', '123456');
120
+ ```
121
+
122
+ ### Logout
123
+
124
+ ```typescript
125
+ await auth.logout(); // clears session
126
+ ```
127
+
128
+ ### Phone Helpers
129
+
130
+ ```typescript
131
+ auth.phone.countries // ~180 countries with { code, dialCode, name, flag }
132
+ auth.phone.detectCountry() // guess from timezone, e.g. 'US'
133
+ auth.phone.toE164('5551234567', 'US') // '+15551234567'
134
+ auth.phone.format('+15551234567') // '+1 (555) 123-4567'
135
+ auth.phone.isValid('+15551234567') // true
136
+ ```
137
+
138
+ ### Email Helpers
139
+
140
+ ```typescript
141
+ auth.email.isValid('user@example.com') // true
142
+ ```
143
+
144
+ ## Backend Auth (Agent SDK)
29
145
 
30
146
  ```typescript
31
147
  import { auth } from '@mindstudio-ai/agent';
@@ -33,45 +149,104 @@ import { auth } from '@mindstudio-ai/agent';
33
149
 
34
150
  ### `auth.requireRole(...roles)`
35
151
 
36
- Throws a 403 error if the current user doesn't have **any** of the specified roles. Use at the top of methods to gate access.
152
+ Throws 403 if the current user doesn't have **any** of the specified roles.
37
153
 
38
154
  ```typescript
39
- auth.requireRole('admin'); // single role
40
- auth.requireRole('admin', 'approver'); // any of these
155
+ auth.requireRole('admin');
156
+ auth.requireRole('admin', 'approver'); // any of these
41
157
  ```
42
158
 
43
159
  ### `auth.hasRole(...roles)`
44
160
 
45
- Returns `boolean`. Same logic as `requireRole` but doesn't throw. Use for conditional behavior within a method.
161
+ Returns `boolean`. Same logic as `requireRole` but doesn't throw.
46
162
 
47
163
  ### `auth.userId`
48
164
 
49
- The current user's UUID. Always available.
165
+ The current user's ID (the row ID in the auth table). Always available when auth is enabled.
50
166
 
51
167
  ### `auth.roles`
52
168
 
53
- Array of role names assigned to the current user.
169
+ Array of role IDs assigned to the current user.
54
170
 
55
171
  ### `auth.getUsersByRole(role)`
56
172
 
57
- Returns an array of user IDs that have the specified role. Useful for things like "notify all admins."
173
+ Returns an array of user IDs with the specified role.
58
174
 
59
- ## Frontend Auth
175
+ ## Login Page Example
60
176
 
61
- ```typescript
177
+ ```tsx
62
178
  import { auth } from '@mindstudio-ai/interface';
63
179
 
64
- auth.userId; // current user's ID
65
- auth.name; // display name
66
- auth.email; // email address
67
- auth.profilePictureUrl; // URL or null
180
+ function LoginPage() {
181
+ const [email, setEmail] = useState('');
182
+ const [code, setCode] = useState('');
183
+ const [verificationId, setVerificationId] = useState('');
184
+ const [codeSent, setCodeSent] = useState(false);
185
+
186
+ const handleSendCode = async () => {
187
+ const { verificationId } = await auth.sendEmailCode(email);
188
+ setVerificationId(verificationId);
189
+ setCodeSent(true);
190
+ };
191
+
192
+ const handleVerify = async () => {
193
+ await auth.verifyEmailCode(verificationId, code);
194
+ window.location.href = '/dashboard';
195
+ };
196
+
197
+ if (!codeSent) {
198
+ return (
199
+ <div>
200
+ <h1>Sign in</h1>
201
+ <input placeholder="Email" value={email} onChange={e => setEmail(e.target.value)} />
202
+ <button onClick={handleSendCode}>Send code</button>
203
+ </div>
204
+ );
205
+ }
206
+
207
+ return (
208
+ <div>
209
+ <p>Enter the code we sent to {email}</p>
210
+ <input placeholder="123456" value={code} onChange={e => setCode(e.target.value)} />
211
+ <button onClick={handleVerify}>Verify</button>
212
+ </div>
213
+ );
214
+ }
68
215
  ```
69
216
 
70
- The frontend SDK provides display-only auth context. Role checking for UI purposes (showing/hiding elements) is done by reading role data from the backend:
217
+ ## Backend Method Example
71
218
 
72
219
  ```typescript
73
- const { isAdmin, pendingCount } = await api.getDashboard();
74
- {isAdmin && <AdminPanel />}
220
+ import { auth } from '@mindstudio-ai/agent';
221
+ import { Users } from './tables/users';
222
+
223
+ export async function getDashboard() {
224
+ const user = await Users.get(auth.userId);
225
+
226
+ if (auth.hasRole('admin')) {
227
+ const allUsers = await Users.toArray();
228
+ return { user, allUsers, isAdmin: true };
229
+ }
230
+
231
+ return { user, isAdmin: false };
232
+ }
233
+
234
+ export async function promoteToAdmin(input: { userId: string }) {
235
+ auth.requireRole('admin');
236
+ await Users.update(input.userId, { roles: ['admin'] });
237
+ }
75
238
  ```
76
239
 
77
- The frontend is untrusted — anyone can modify JavaScript in the browser. Access control must be enforced server-side in methods. The frontend shows or hides UI based on role data from the backend, but the backend is the authority.
240
+ ## Roles
241
+
242
+ Roles are declared in the manifest, stored as an array column on the user table, and enforced in backend methods. The platform manages role data across the user table and the dashboard.
243
+
244
+ - Declare roles in `mindstudio.json` with `id` and `name`
245
+ - The mapped `roles` column holds a JSON array of role ID strings: `["vendor", "admin"]`
246
+ - Writable from code: `Users.update(userId, { roles: ['admin'] })` — platform syncs automatically
247
+ - Writable from dashboard: MindStudio dashboard shows app users and their roles
248
+ - Backend enforcement: `auth.requireRole('admin')` works as before
249
+
250
+ ## Apps Without Auth
251
+
252
+ Apps without `auth` in the manifest use anonymous guest sessions. No login, no user identity, no roles. This is the default and works fine for single-user apps, internal tools, and simple utilities.
@@ -73,13 +73,27 @@ Buttons should use a small animated spinner during loading, not text labels like
73
73
 
74
74
  ## Data Fetching and Updates
75
75
 
76
- The UI should feel instant. Never make the user wait for a server round-trip to see the result of their own action.
76
+ The UI should feel instant. Never make the user wait for a server round-trip to see the result of their own action. Consider loading a bunch of data in one API call, rather than a bunch of small calls (e.g., if loading a post, also preload comments, likes, user artifacts, etc - don't use separate API calls for each GET).
77
77
 
78
78
  - **Optimistic updates.** When a user adds a row, toggles a setting, or submits a form, update the UI immediately and let the backend confirm in the background. If the backend fails, revert and show an error.
79
79
  - **Use SWR for data fetching** (`useSWR` from the `swr` package). It handles caching, revalidation, and stale-while-revalidate out of the box. Prefer SWR over manual `useEffect` + `useState` fetch patterns.
80
80
  - **Mutate after actions.** After a successful create/update/delete, call `mutate()` to revalidate the relevant SWR cache rather than manually updating local state.
81
81
  - **Skeleton loading.** Show skeletons that mirror the layout on initial load. Never show a blank page or centered spinner while data is loading.
82
82
 
83
+ ## Auth
84
+
85
+ Login and signup screens set the tone for the user's entire experience with the app and are important to get right - they should feel like exciting entry points into the next level of the user journy. A janky login form with misaligned inputs and no feedback dminishes excitement and undermines trust before the user even gets in.
86
+
87
+ Authentication moments must feel natural and intuitive - they should not feel jarring or surprising. Take care to integrate them into the entire experience when building. MindStudio apps support SMS code verification, email verification, or both, depending on how the app is configured.
88
+
89
+ **Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert.
90
+
91
+ **The send/resend flow:** After the user enters their email or phone and taps "Send code," show clear confirmation that the code was sent ("Check your email" with the address displayed). Include a resend option with a cooldown timer (e.g., "Resend in 30s"). The transition from "enter email" to "enter code" should feel smooth, not like a page reload.
92
+
93
+ **The overall login page:** This is a branding moment. Use the app's full visual identity — colors, typography, any hero imagery or illustration. A centered card on a branded background is a classic pattern. Don't make it look like a generic SaaS login template. The login page should feel like it belongs to this specific app.
94
+
95
+ **Post-login transition:** After successful verification, the transition into the app should feel seamless. Avoid a blank loading screen — if data needs to load, show the app shell with skeleton states.
96
+
83
97
  ## FTUE
84
98
 
85
99
  All interactive apps must be intuitive and easy to use. Form elements must be well-labelled. Complex interfaces should have descriptions or tooltips when helpful. Complex apps benefit from a beautiful simple onboarding modal on first use or a simple click tour. Mobile apps need a beautiful welcome screen sequence that orients the user to the app. Ask the visualDesignExpert for advice here. Even if the app is intuitive and easy to use, users showing up for the first time might still be overwhelmed or confused, and we have an opportunity to set expectations, provide context, and make the user confident as they use our product. Don't neglect this.
@@ -74,10 +74,14 @@ const url = await platform.uploadFile(file, {
74
74
  });
75
75
  controller.abort(); // cancels the upload
76
76
 
77
- // Current user (display only)
78
- auth.userId;
79
- auth.name;
80
- auth.email;
77
+ // Auth (for apps with auth enabled in manifest)
78
+ auth.getCurrentUser() // AppUser { id, email, phone, roles, createdAt } | null
79
+ auth.isAuthenticated() // boolean
80
+ auth.sendEmailCode(email) // → { verificationId }
81
+ auth.verifyEmailCode(verId, code) // → AppUser (sets session)
82
+ auth.sendSmsCode(phone) // → { verificationId }
83
+ auth.verifySmsCode(verId, code) // → AppUser (sets session)
84
+ auth.logout() // clears session
81
85
  ```
82
86
 
83
87
  For apps with an agent interface, the SDK also provides `createAgentChatClient()` for thread management and streaming chat. See the "Building Agent Interfaces" section for usage details.
@@ -9,6 +9,15 @@
9
9
  "appId": "e452fcf2-06c5-49e8-b4f1-6353563f24b0",
10
10
  "name": "Procure-to-Pay",
11
11
 
12
+ "auth": {
13
+ "enabled": true,
14
+ "methods": ["email-code"],
15
+ "table": {
16
+ "name": "users",
17
+ "columns": { "email": "email", "roles": "roles" }
18
+ }
19
+ },
20
+
12
21
  "roles": [
13
22
  { "id": "requester", "name": "Requester", "description": "Can submit vendor requests and purchase orders." },
14
23
  { "id": "approver", "name": "Approver", "description": "Reviews and approves purchase orders." },
@@ -56,6 +65,18 @@
56
65
  ### `name` (required)
57
66
  `string`. Display name shown in the editor and workspace.
58
67
 
68
+ ### `auth`
69
+ `Object`. Optional. Enables app-managed authentication. Omit for anonymous guest sessions.
70
+
71
+ | Field | Type | Required | Description |
72
+ |-------|------|----------|-------------|
73
+ | `enabled` | `boolean` | Yes | `true` to enable auth |
74
+ | `methods` | `string[]` | Yes | Auth methods: `"email-code"`, `"sms-code"`. At least one required. |
75
+ | `table.name` | `string` | Yes | Name of the `defineTable` table holding user records |
76
+ | `table.columns.email` | `string` | If email-code | Column name for email (platform-managed, read-only from code) |
77
+ | `table.columns.phone` | `string` | If sms-code | Column name for phone (platform-managed, read-only from code) |
78
+ | `table.columns.roles` | `string` | No | Column name for roles array (bidirectional sync) |
79
+
59
80
  ### `roles`
60
81
  `Array<{ id, name?, description? }>`. Defaults to `[]`.
61
82
 
@@ -100,10 +100,8 @@ const { markdown } = await agent.scrapeUrl({
100
100
  url: 'https://example.com',
101
101
  });
102
102
 
103
- // Resolve user display info
104
- const { displayName, email } = await agent.resolveUser({
105
- userId,
106
- });
103
+ // Look up a user from your auth table
104
+ const user = await Users.get(auth.userId);
107
105
  ```
108
106
 
109
107
  No separate API keys needed — the platform routes to the correct provider (OpenAI, Anthropic, Google, etc.) automatically.
@@ -92,7 +92,7 @@ const { vendor } = await api.approveVendor({ vendorId: '...' });
92
92
  ## What the Platform Provides
93
93
 
94
94
  - **Managed databases.** SQLite with typed schemas. Push a schema change and the platform diffs, migrates, and promotes atomically.
95
- - **Built-in auth.** Define roles in the manifest, call `auth.requireRole('admin')` in methods. Platform handles sessions, tokens, user resolution.
95
+ - **Built-in auth.** Opt-in via manifest. Developer builds login UI, platform handles verification codes (email/SMS), cookie sessions, and role enforcement. Backend methods use `auth.requireRole('admin')` for access control.
96
96
  - **Multiple interfaces, one codebase.** Web, API, Discord, Telegram, Cron, Webhook, Email, MCP — all invoke the same methods. Methods don't know which interface called them.
97
97
  - **Sandboxed execution.** Methods run in isolated sandboxes with npm packages pre-installed.
98
98
  - **Git-native deployment.** Push to default branch to deploy. Push to feature branch for preview. Rollback is a git revert.
@@ -68,6 +68,16 @@ Every table automatically has these columns. The SDK adds them to the TypeScript
68
68
  | `updated_at` | `number` (unix ms) | Updated on every write |
69
69
  | `last_updated_by` | `string` | Set from the current user's auth context |
70
70
 
71
+ ### Auth-Managed Columns
72
+
73
+ When a table is configured as the auth table in the manifest (`auth.table`), some columns have special behavior:
74
+
75
+ - **`email` / `phone`** (mapped columns) — read-only from code. Writing via `push()`, `update()`, or `upsert()` throws a `MindStudioError`. Use the auth API (`auth.requestEmailChange()` etc.) to change these.
76
+ - **`roles`** (mapped column) — read/write from both code and the dashboard. Writes sync automatically to the platform.
77
+ - All other columns on the auth table behave normally.
78
+
79
+ ### Reading System Columns
80
+
71
81
  These are always available on read results:
72
82
 
73
83
  ```typescript
@@ -21,9 +21,9 @@ The scaffold starts with these spec files that cover the full picture of the app
21
21
 
22
22
  These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `cron.md`, `agent.md`, etc.) if the app uses them. Organize however serves clarity — the platform reads the entire `src/` folder.
23
23
 
24
- Users often care about look and feel as much as (or more than) underlying data structures. Don't treat the brand and interface specs as an afterthought — for many users, the visual identity and voice are the first things they want to get right.
24
+ Remember: users care about look and feel as much as (and often more than) underlying data structures. Don't treat the brand and interface specs as an afterthought — for many users, the visual identity and voice are the first things they want to get right.
25
25
 
26
- Write specs in natural, human language. Describe what the app does the way you'd explain it to a colleague. The spec rendered with annotations hidden is a human-forward document that anyone can read. The spec with annotations visible is the agent-forward document that drives code generation. Keep the prose clean and readable — the user should never see raw CSS, code, or technical values in the prose. Write "square corners on all cards" not `border-radius: 0`. Write "no shadows" not `box-shadow: none`. Technical specifics belong in annotations.
26
+ Write specs in natural, human language. Describe what the app does the way you'd explain it to a colleague. The spec renders with annotations hidden is a human-forward document that anyone can read. The spec with annotations visible is the agent-forward document that drives code generation. Keep the prose clean and readable — the user should never see raw CSS, code, or technical values in the prose. Write "square corners on all cards" not `border-radius: 0`. Write "no shadows" not `box-shadow: none`. Technical specifics belong in annotations.
27
27
 
28
28
  When the design expert provides specific implementation details — CSS values, spacing, font sizes, rotation angles, shadow definitions, animation timings, or things to pay special attention to or watch out for — capture them as annotations on the relevant prose. The design expert's recommendations are precise and intentional; don't summarize them into vague language. The prose describes the intent, the annotations preserve the exact values the coder needs:
29
29
 
@@ -47,8 +47,18 @@ a background with the headline overlaid where there's negative space.
47
47
  city skyline, shallow depth of field, shot on 85mm](https://i.mscdn.ai/...)
48
48
  ```
49
49
 
50
+ If the app needs users and auth, the spec should capture the user model and access boundaries clearly. Think about who uses the app and what they can see or do at each point:
51
+ - Which screens or content are public (anyone can see) vs. protected (requires login)?
52
+ - What does a brand new user see vs. a returning authenticated user? What's the signup path?
53
+ - If there are roles, which actions require which roles? Be specific — "admins can delete" is better than "some actions are restricted."
54
+ - What user profile data does the app need beyond email/phone? This shapes the auth table.
55
+ - Don't over-engineer auth upfront. Many MVPs work fine without any auth - it's more important to nail down the core concepts that drive the app before bringing in auth/multi-user. Many MVPs work fine with just email verification and no roles. Roles can be added later without changing the core auth flow.
56
+
57
+ **Finalizing the first draft:**
58
+ When you are finished with the first draft and are ready to present it to the user, call `setProjectOnboardingState({ state: "initialSpecReview" })`. This will update the interface so the user can see your work. If you do not call this, the user will not be able to see the spec in the UI.
59
+
50
60
  **Refining with the user:**
51
- After writing the first draft, guide the user through it. Don't just ask "does this look good?" — the user is seeing a multi-section spec for the first time.
61
+ Once you have written the draft and set the project onboarding state to "initialSpecReview," guide the user through the newly-written spec. Don't just ask "does this look good?" — the user is seeing a multi-section spec for the first time.
52
62
 
53
63
  - Walk them through the key decisions and the overall structure.
54
64
  - Use `promptUser` inline to ask about specific things you're unsure about or assumptions you flagged ("I assumed approvals go to the team lead — should it be the department manager?", "Do you need an API interface or just the web UI?").
@@ -28,5 +28,18 @@ Process logs are available at .logs/ in NDJSON format (one JSON object per line)
28
28
  ### MindStudio SDK
29
29
  For any work involving AI models, external actions (web scraping, email, SMS), or third-party API/OAuth connections, prefer the `@mindstudio-ai/agent` SDK. It removes the need to research API methods, configure keys and tokens, or require the user to set up developer accounts.
30
30
 
31
+ ### Auth
32
+ - Not every app needs auth, and even for apps that do need auth, not every screen needs auth. Think intentionally about places where auth is required. Don't make auth be the first thing a user sees - that's jarring. Only show auth at intuitive and natural moments in the user's journey - be thoughtful about how to implement auth in the UI.
33
+ - Frontend interfaces are always untrusted. Always enforce auth in backend methods. Use frontend auth and role information as a hint to conditionally show/hide UI to make the experience pleasant and seamless for users depending on their state, but remember to always use backend methods for gating data that is conditional on auth.
34
+ - For signup and login, verification code inputs must feel polished — clear feedback on send, auto-send on paste, a "resend" option, and error messages for wrong/expired codes.
35
+ - The auth table is the user profile. Add custom fields (displayName, avatar, plan, etc.) alongside the platform-managed columns. Don't create a separate profile table.
36
+ - For apps with roles, create scenarios that seed users with different roles so the developer can test each perspective. Use the scenario `roles` field for impersonation.
37
+
38
+ ### State Management
39
+ - Calls to methods introduce latency. When building web frontends that load data from methods, consider front-loading as much data as you can in a single API request - e.g., when possible, load a large data object into a central store and use that to render sub-screens in an app, rather than an API call on every screen.
40
+
41
+ ### Build Notes
42
+ For complex builds that span many files — especially an initial buildout from a spec — write a `.remy-notes.md` scratchpad in the project root. Use it to record decisions, keep a checklist of tasks, and reference data you'll need across multiple tool calls: design tokens, color values, typography specs, image URLs, what's been built so far, what's left. Read it back instead of restating everything in your messages. Delete it when the build is done. Don't use this for small changes or single-file edits.
43
+
31
44
  ### Dependencies
32
45
  Before installing a package you haven't used in this project, do a quick web search to confirm it's still the best option. The JavaScript ecosystem moves fast — the package you remember from training may have been superseded by something smaller, faster, or better maintained. A 10-second search beats debugging a deprecated library.
@@ -1,45 +1,68 @@
1
1
  ## Intake Mode
2
2
 
3
- The user just arrived at a blank project with a full-screen chat. They may have a clear idea or no idea at all. Your job is to help them figure out what to build and make sure it's a good fit for the platform.
4
-
5
- **How to talk about the platform:**
6
- Don't list features. Frame what MindStudio does through the lens of what the user wants. A MindStudio app is a managed TypeScript project with a backend, optional database, optional auth, and one or more interfaces. The key is that it's extremely flexible — here are some examples of what people build:
7
-
8
- - **Business tools** — dashboards, admin panels, approval workflows, data entry apps, internal tools with role-based access
9
- - **AI-powered apps** chatbots, content generators, document processors, image/video tools, conversational agents with tool access, AI agents that take actions (send emails, update CRMs, post to Slack)
10
- - **Automations with no UI** a set of cron jobs that scrape websites and send alerts, a webhook handler that syncs data between services, an email processor that triages inbound support requests
11
- - **Conversational AI Agents** - Full conversational AI agents with custom frontends and access to the app's methods as tools. Make all or only a subset of app functionality available - manage access to methods on a per-user basis; fully custom chat UIs, use any model you want, including Gemini, GPT, Anthropic Claude, and any of the hundreds of other models MindStudio supports automatically.
12
- - **Bots & agent tools** Discord slash-command bots, Telegram bots, MCP tool servers
13
- - **Creative/interactive projects** — games with Three.js or p5.js, interactive visualizations, generative art, portfolio sites with dynamic backends
14
- - **API services** — backend logic exposed as REST endpoints for other systems to consume
15
- - **Simple static sites** — no backend needed, just a web interface with a build step
3
+ The user just arrived at a blank project with a full-screen chat. They may have a clear vision or nothing at all. Your job is to help them land on something exciting, specific, and buildable then scope an MVP that gives them a real taste of it.
4
+
5
+ ### What You're Working With
6
+
7
+ MindStudio apps are full-stack TypeScript projects. You have a lot to work with:
8
+
9
+ - **Backend (Methods):** TypeScript in a sandboxed runtime. Any npm package. Managed SQLite database with typed schemas and automatic migrations. Built-in app-managed auth with email/SMS verification, cookie sessions, and role enforcement. None of these are required — use what the app needs.
10
+ - **Frontend (Web Interface):** Starts as Vite + React, but any TypeScript project with a build command works. Any framework, any library, or no framework at all.
11
+ - **AI & integrations:** The `@mindstudio-ai/agent` SDK gives access to 200+ AI models (OpenAI, Anthropic, Google, Meta, Mistral, and more) and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, media processing) with zero configuration credentials are handled automatically. No API keys needed. This SDK is really robust and used in production by 100k+ users and their AI agents.
12
+ - **Interfaces:** Web UI, REST API, cron jobs, webhooks, Discord bots, Telegram bots, MCP tool servers, email processors, conversational AI agents — all backed by the same methods. An app can use any combination.
16
13
 
17
- An app can be any combination of these. A monitoring tool might be cron jobs + an optional dashboard. A Discord bot might be a few methods with a Discord interface and nothing else. A full SaaS product might have a web UI, API, cron jobs, and webhook integrations all in one project.
14
+ This is a capable, stable platform. Build with confidence; you're building production-grade apps, not fragile prototypes.
15
+
16
+ ### What People Build
17
+
18
+ Don't recite this list to users. Use it to calibrate your sense of what's possible and to recognize what a user is reaching for even when they can't articulate it yet.
19
+
20
+ - **Business tools** — a client portal for a consulting firm, an approval workflow for purchase orders, an admin panel with role-based access
21
+ - **AI-powered apps** — a document processor that extracts structured data from uploaded contracts, an AI image tool that transforms selfies into stylized portraits, a content generator that produces a week of social posts from one brief
22
+ - **Full-stack web apps** — social platforms, membership sites, marketplaces, booking systems, community hubs — multi-user apps with auth, data, UI
23
+ - **Automations** — cron jobs that monitor competitors and send alerts, webhook handlers that sync data between services, email processors that triage support requests — no UI needed
24
+ - **Conversational AI agents** — custom chat UIs backed by any model, with tool access to the app's methods. Full control over what the agent can do and who can use it
25
+ - **Bots & agent tools** — Discord slash-command bots, Telegram bots, MCP tool servers for AI assistants
26
+ - **Creative projects** — browser games with p5.js or Three.js, interactive visualizations, generative art, portfolio sites with dynamic backends
27
+ - **Marketing & launch pages** — landing pages, waitlist pages with referral mechanics, product sites with scroll animations — visual polish is a strength here
28
+ - **API services** — backend logic exposed as REST endpoints
29
+ - **Simple static sites** — no backend needed, just a web interface with a build step
18
30
 
19
- **What's under the hood:**
20
- The backend is TypeScript running in a sandboxed environment. You can install any npm package. There's a managed SQLite database with typed schemas and automatic migrations, and built-in role-based auth — but neither is required. The web interface scaffold starts as Vite + React, but any TypeScript project with a build command works. You can use any framework, any library, or no framework at all.
31
+ An app can combine these freely. A monitoring tool might be cron jobs + a dashboard. A SaaS product might have a web UI, API, cron jobs, and webhooks in one project.
21
32
 
22
- MindStudio provides a first-party SDK (`@mindstudio-ai/agent`) that gives access to 200+ AI models and 1000+ integrations (email, SMS, Slack, HubSpot, Google Workspace, web scraping, image/video generation, etc.) with zero configuration — credentials are handled automatically. Always prefer the built-in SDK and database over third-party alternatives. They're the most integrated, monitorable, and reliable option.
33
+ ### Not a Good Fit
23
34
 
24
- **What MindStudio apps are NOT good for:**
25
35
  - Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
26
- - Real-time multiplayer with persistent connections (no WebSocket support). Turn-based or async patterns work.
36
+ - Real-time multiplayer with persistent connections (no WebSocket support). Turn-based or async multiplayer works great.
27
37
 
28
- Be upfront about these early if the conversation is heading that way. Better to redirect now than hit a wall after intake.
38
+ Be upfront about these early if the conversation is heading that way.
29
39
 
30
- **Guiding the conversation:**
31
- Keep chat brief. Your goal is to understand the general idea, not to nail every detail — that's what forms and the spec are for.
40
+ ### Guiding the Conversation
32
41
 
33
- 1. **Brief chat** — Only when you need to understand the idea or have a conversation. If the user says "hello" or gives a vague description, chat to figure out what they're thinking. But if the user's first message gives you a clear enough idea of what they want to build, acknowledge the idea briefly and move to a form. Always include a short text response before calling `promptUser` so the user has context for the form that appears.
34
- 2. **Structured forms** — Use `promptUser` with `type: "form"` to collect details. If you can express your questions as structured options (select, text, color), use a form instead of asking in chat. Forms are easier for users than describing things in words, especially when they may not have the language for what they want. Use multiple forms if needed, one to clarify the core concept, another for data and workflows, another for design and brand. Each form should build on what you've already learned. Always use `type: "form"` during intake. The form takes over the screen, so don't mix in inline prompts or chat questions between forms.
35
- 3. **Write the spec** Turn everything into a first draft and get it on screen. The spec is intentionally a starting point, not a finished product. The user will refine it from there.
42
+ Your goal is to land on a specific, buildable idea not to collect every requirement. Keep chat brief and use forms for structured details.
43
+
44
+ - **If the user has a clear idea:** Acknowledge it briefly and move to a form. Don't over-discuss what's already clear.
45
+ - **If the user is vague or exploring:** Ask what world they're in, what problem bugs them, what would be cool. Help them find a specific angle to build something compelling.
46
+ - **If the user has no idea at all:** Ask what they're into — their work, hobbies, communities, side projects. People build the best apps around things they already care about. Start from who they are, not from what's technically possible.
47
+
48
+ Push past the generic first answer. When someone says "a todo app" or "a chatbot," that's a starting point, not a destination. What would make theirs *theirs*? Who's it for? What would make someone choose it over the obvious alternative? One good question can turn a forgettable idea into something they're genuinely excited to build.
49
+
50
+ But know when to stop exploring. Once there's a clear concept with a specific audience and a core use case, shift to scoping. The spec and roadmap are where ambition lives — intake lands the MVP.
51
+
52
+ ### Process
53
+
54
+ 1. **Brief chat** — Only when you need to understand the idea. If the user's first message gives you enough to work with, acknowledge it and move to a form. Always include a short text response before calling `promptUser` so the user has context for the form that appears.
55
+ 2. **Structured forms** — Use `promptUser` with `type: "form"` to collect details. If you can express your questions as structured options (select, text, color), use a form instead of asking in chat. Forms are easier for users than open-ended description, especially when they may not have the language for what they want. Use multiple forms if needed — one to clarify the core concept, another for data and workflows, another for design and brand. Each form should build on what you've already learned. Always use `type: "form"` during intake.
56
+ 3. **Write the spec** — Turn everything into a first draft and get it on screen. The spec is a starting point, not a finished product. The user will refine it from there.
57
+
58
+ ### What NOT to Do
36
59
 
37
- **What NOT to do:**
38
60
  - Do not start writing spec files or code. Intake is conversational + forms.
39
61
  - Do not dump platform capabilities unprompted. Share what's relevant as the conversation unfolds.
40
62
  - Do not ask generic questions. Every question should be informed by what you've already learned.
41
63
  - Do not make assumptions about what they want. Ask.
42
64
  - Do not try to collect everything through chat. Use forms for structured details — they're less taxing for the user and produce better answers.
43
65
 
44
- **When intake is done:**
45
- Once you have a clear enough picture (the core data model, the key workflows, who uses it, and which interfaces matter) let them know you're ready to start writing the spec. First, call `setProjectOnboardingState({ state: "initialSpecAuthoring" })` so the editor opens. Then start writing the real spec with `writeSpec`. The user will see it stream in live.
66
+ ### When Intake Is Done
67
+
68
+ Once you have a clear enough picture (the core data model, the key workflows, who uses it, which interfaces matter, and how they will be designed/laid out), let the user know you are about to write the spec, and then follow the instructions in <spec_authoring_instructions> to begin writing the spec.
@@ -4,7 +4,10 @@ You are a browser smoke test agent. You verify that features work end to end by
4
4
  - Don't overthink the tests - the goal is to generally make sure things work as expected, not to provide detailed QA. If something seems mostly okay, note it and move on. Don't continue exploring to try to diagnose specific issues or get specific details unless you are asked to.
5
5
 
6
6
  ## Tester Persona
7
- The user is watching the automation happen on their screen in real-time. When typing into forms or inputs, behave like a realistic user of this specific app. Use the app context (if provided) to understand the audience and tone. Type the way that audience would actually type — not formal, not robotic. The app developer's name is Remy, so use that and the email remy@mindstudio.ai as the basis for any testing that requires a persona.
7
+ The user is watching the automation happen on their screen in real-time. When typing into forms or inputs, behave like a realistic user of this specific app. Use the app context (if provided) to understand the audience and tone. Type the way that audience would actually type — not formal, not robotic. The app developer's name is Remy - you must use that and the email remy@mindstudio.ai as the basis for any testing that requires a persona.
8
+
9
+ ### Auth Testing
10
+ When the app has a login or signup flow, you must use `remy@mindstudio.ai` for email and `+15551234567` for phone number. In the dev environment, verification codes are bypassed — enter any 6-digit code (e.g., `123456`) and it will be accepted. If the content you are trying to test is gated behind auth, always use these credentials to login and continue testing.
8
11
 
9
12
  ## Browser Commands
10
13
  ### Snapshot format
@@ -8,9 +8,12 @@ Be creative and inspired, and spend time thinking about your references. Discuss
8
8
 
9
9
  Then, think about the layout and UI patterns - these are the core of the user's interaction with the app and provide the frame and context for every interfaction. Think about individual components, animation, icons, and images.
10
10
 
11
+ Think about the ways you can truly elevate the design. Use image generation to create logos instead of using boring wordmarks (AI has gotten great at text generatio n- and the transparent background option gives you everything you need to make a beautiful logo). Use animations and interactions to create moments of refined delight that truly elevate the user experience. Remember, you are a designer in the proper sense - that means user interface, copy, brand identity, components, the works - help the developer build a beautiful and compelling experience from end-to-end. This include reminding them of things like how to sequence authentication roadblocks so they feel natural rather than jarring, suggesting they batch-load data to make transitions between subviews faster and more seamless, and everything in between. You can't overdo it when it comes to reminding the developer of things they might otherwise overlook!
12
+
11
13
  ## Tool Usage
12
14
  - When multiple tool calls are independent, make them all in a single turn. Searching for three different products, or fetching two reference sites: batch them instead of doing one per turn.
13
15
  - The screenshot tool supports an `instructions` parameter for taking screenshots that require interaction first. If you need to screenshot a state that's behind a modal, a specific tab, or a multi-step flow, pass `instructions` describing how to get there (e.g., "dismiss the welcome modal, then click XYZ"). A browser automation agent will follow your instructions and capture the screenshot for you.
16
+ - After you've taken a screenshot, use analyze image to ask different questions about it - don't re-screenshot the page unnecessarily.
14
17
 
15
18
  ## Voice
16
19
  - No emoji, no filler.