@mindstudio-ai/remy 0.1.121 → 0.1.122
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.
- package/dist/headless.js +5 -0
- package/dist/index.js +5 -0
- package/dist/prompt/compiled/auth.md +39 -2
- package/dist/prompt/compiled/design.md +1 -1
- package/dist/prompt/compiled/interfaces.md +115 -20
- package/dist/prompt/compiled/manifest.md +3 -2
- package/dist/prompt/compiled/methods.md +40 -0
- package/dist/prompt/compiled/platform.md +2 -1
- package/dist/prompt/compiled/secrets.md +40 -0
- package/dist/prompt/static/authoring.md +1 -1
- package/dist/prompt/static/coding.md +6 -1
- package/dist/prompt/static/instructions.md +1 -1
- package/dist/subagents/codeSanityCheck/prompt.md +8 -0
- package/dist/subagents/designExpert/prompts/frontend-design-notes.md +1 -1
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -378,6 +378,10 @@ Current date: ${now}
|
|
|
378
378
|
<scenarios>
|
|
379
379
|
{{compiled/scenarios.md}}
|
|
380
380
|
</scenarios>
|
|
381
|
+
|
|
382
|
+
<secrets>
|
|
383
|
+
{{compiled/secrets.md}}
|
|
384
|
+
</secrets>
|
|
381
385
|
</platform_docs>
|
|
382
386
|
|
|
383
387
|
<mindstudio_agent_sdk_docs>
|
|
@@ -4056,6 +4060,7 @@ TypeScript running in a sandboxed environment. Any npm package can be installed.
|
|
|
4056
4060
|
|
|
4057
4061
|
- Managed SQLite database with typed schemas and automatic migrations. Define a TypeScript interface, push, and the platform handles diffing and migrating.
|
|
4058
4062
|
- Built-in app-managed auth. Opt-in via manifest \u2014 developer builds login UI, platform handles verification codes (email/SMS), cookie sessions, and role enforcement. Backend methods use auth.requireRole() for access control.
|
|
4063
|
+
- Encrypted secrets with separate dev/prod values, injected as process.env. For third-party service credentials not covered by the SDK.
|
|
4059
4064
|
- Git-native deployment. Push to default branch to deploy.
|
|
4060
4065
|
|
|
4061
4066
|
## MindStudio SDK
|
package/dist/index.js
CHANGED
|
@@ -3941,6 +3941,7 @@ TypeScript running in a sandboxed environment. Any npm package can be installed.
|
|
|
3941
3941
|
|
|
3942
3942
|
- Managed SQLite database with typed schemas and automatic migrations. Define a TypeScript interface, push, and the platform handles diffing and migrating.
|
|
3943
3943
|
- Built-in app-managed auth. Opt-in via manifest \u2014 developer builds login UI, platform handles verification codes (email/SMS), cookie sessions, and role enforcement. Backend methods use auth.requireRole() for access control.
|
|
3944
|
+
- Encrypted secrets with separate dev/prod values, injected as process.env. For third-party service credentials not covered by the SDK.
|
|
3944
3945
|
- Git-native deployment. Push to default branch to deploy.
|
|
3945
3946
|
|
|
3946
3947
|
## MindStudio SDK
|
|
@@ -5938,6 +5939,10 @@ Current date: ${now}
|
|
|
5938
5939
|
<scenarios>
|
|
5939
5940
|
{{compiled/scenarios.md}}
|
|
5940
5941
|
</scenarios>
|
|
5942
|
+
|
|
5943
|
+
<secrets>
|
|
5944
|
+
{{compiled/secrets.md}}
|
|
5945
|
+
</secrets>
|
|
5941
5946
|
</platform_docs>
|
|
5942
5947
|
|
|
5943
5948
|
<mindstudio_agent_sdk_docs>
|
|
@@ -16,7 +16,8 @@ MindStudio apps can have and manage their own users. Auth is opt-in: configure i
|
|
|
16
16
|
"columns": {
|
|
17
17
|
"email": "email",
|
|
18
18
|
"phone": "phone",
|
|
19
|
-
"roles": "roles"
|
|
19
|
+
"roles": "roles",
|
|
20
|
+
"apiKey": "apiKey"
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
},
|
|
@@ -32,11 +33,13 @@ MindStudio apps can have and manage their own users. Auth is opt-in: configure i
|
|
|
32
33
|
- **`auth.methods`** — which verification methods the app supports. At least one required.
|
|
33
34
|
- `email-code` — 6-digit code sent via email
|
|
34
35
|
- `sms-code` — 6-digit code sent via SMS
|
|
36
|
+
- `api-key` — programmatic access via `Authorization: Bearer sk_...` header. Resolves to a user with full RBAC.
|
|
35
37
|
- **`auth.table.name`** — name of the `defineTable` table that holds user records.
|
|
36
38
|
- **`auth.table.columns`** — maps platform-managed fields to column names in the developer's table.
|
|
37
39
|
- `email` — required if `email-code` is in methods
|
|
38
40
|
- `phone` — required if `sms-code` is in methods
|
|
39
41
|
- `roles` — optional. Maps to a JSON array column for role assignments.
|
|
42
|
+
- `apiKey` — optional. Required if `api-key` is in methods. Platform stores masked value (`sk_...xxxx`) for display; one key per user.
|
|
40
43
|
- **`roles`** — declares valid roles for the app. Same as before: `id`, `name`, optional `description`.
|
|
41
44
|
|
|
42
45
|
## Auth Table
|
|
@@ -51,6 +54,7 @@ export const Users = db.defineTable<{
|
|
|
51
54
|
email: string;
|
|
52
55
|
phone?: string;
|
|
53
56
|
roles: string[];
|
|
57
|
+
apiKey?: string; // masked value (sk_...xxxx), read-only from code
|
|
54
58
|
// Developer's own fields
|
|
55
59
|
displayName: string;
|
|
56
60
|
plan: 'free' | 'pro';
|
|
@@ -60,7 +64,7 @@ export const Users = db.defineTable<{
|
|
|
60
64
|
|
|
61
65
|
### Platform-Managed Column Behavior
|
|
62
66
|
|
|
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.
|
|
67
|
+
- **`email` / `phone` / `apiKey`** — read-only from code. Writing via `update()` or `push()` throws a `MindStudioError`. Use the auth API to change a user's email or phone, and `auth.createApiKey()` / `auth.revokeApiKey()` for API keys.
|
|
64
68
|
- **`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
69
|
- All other columns are fully the developer's. When auth creates a user row, only the managed columns (email/phone, roles) are populated. All user-defined columns start as null until the user completes onboarding — type them as optional and guard against null.
|
|
66
70
|
|
|
@@ -80,6 +84,7 @@ interface AppUser {
|
|
|
80
84
|
email: string | null;
|
|
81
85
|
phone: string | null;
|
|
82
86
|
roles: string[];
|
|
87
|
+
apiKey: string | null; // masked value (sk_...xxxx), null if no key
|
|
83
88
|
createdAt: string;
|
|
84
89
|
}
|
|
85
90
|
```
|
|
@@ -139,6 +144,24 @@ const user = await auth.confirmPhoneChange('+15559876543', '123456');
|
|
|
139
144
|
await auth.logout(); // clears session
|
|
140
145
|
```
|
|
141
146
|
|
|
147
|
+
### API Keys
|
|
148
|
+
|
|
149
|
+
For apps with `api-key` in their auth methods. API keys resolve to a user with the same `auth.userId`, `auth.roles`, and `requireRole()` enforcement as a cookie session.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Generate a key for the current user (must be logged in)
|
|
153
|
+
const { key } = await auth.createApiKey();
|
|
154
|
+
// key = "sk_..." — show once, not stored. user.apiKey updates to masked value.
|
|
155
|
+
|
|
156
|
+
// Revoke current user's key
|
|
157
|
+
await auth.revokeApiKey();
|
|
158
|
+
// user.apiKey becomes null
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Both methods fire `onAuthStateChanged` since they modify the user object. One key per user — creating a new key replaces the old one.
|
|
162
|
+
|
|
163
|
+
Consumers use the key as a Bearer token: `Authorization: Bearer sk_...`. The platform resolves it to the user, populates the auth context, and executes the method normally. Invalid or revoked key: 401.
|
|
164
|
+
|
|
142
165
|
### Error Codes
|
|
143
166
|
|
|
144
167
|
All auth methods throw on failure with a `code` property:
|
|
@@ -151,6 +174,7 @@ All auth methods throw on failure with a `code` property:
|
|
|
151
174
|
| `max_attempts_exceeded` | 400 | Too many failed attempts |
|
|
152
175
|
| `not_authenticated` | 401 | No active session |
|
|
153
176
|
| `invalid_session` | 401 | Session expired or invalid |
|
|
177
|
+
| `not_supported` | 400 | Feature not enabled for this app (e.g. API keys without `api-key` in methods) |
|
|
154
178
|
|
|
155
179
|
### Phone Helpers
|
|
156
180
|
|
|
@@ -200,6 +224,19 @@ Array of role IDs assigned to the current user.
|
|
|
200
224
|
|
|
201
225
|
Returns an array of user IDs with the specified role.
|
|
202
226
|
|
|
227
|
+
### System Role (Platform Triggers)
|
|
228
|
+
|
|
229
|
+
When the platform invokes a method on behalf of the app (cron, webhook, email, Discord, Telegram), the execution runs as a system user with `auth.roles: ['system']`. Use `auth.requireRole('system')` to restrict methods to platform triggers only:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
export async function regenerateCache(input: {}) {
|
|
233
|
+
auth.requireRole('system');
|
|
234
|
+
// Only cron, webhooks, and users with 'system' role can reach this
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Web frontend calls (`/_/methods`), API interface calls (`/_/api`), and agent chat all run as the authenticated user — they don't get the system role unless the user has been explicitly assigned it. You can assign `system` to app users via the dashboard or SDK if they need to manually trigger these methods.
|
|
239
|
+
|
|
203
240
|
## Login Page Example
|
|
204
241
|
|
|
205
242
|
```tsx
|
|
@@ -98,7 +98,7 @@ Even if the app is intuitive and easy to use, users showing up for the first tim
|
|
|
98
98
|
## What to Actively Avoid At All Costs
|
|
99
99
|
|
|
100
100
|
- **Avoid generic fonts.** Overused defaults that strip away all personality. Instead: pick a distinctive Google Font that fits the app's character.
|
|
101
|
-
- **Avoid purple or indigo anything.** Purple gradients, purple buttons, purple accents are overused. The user will be dismissive of our designs if they come out looking purple or indigo.
|
|
101
|
+
- **Avoid purple or indigo anything.** Purple gradients, purple buttons, purple accents are overused. The user will be dismissive of our designs if they come out looking purple or indigo. Avoid terracotta for similar reasons.
|
|
102
102
|
- **Avoid colored left-border callout boxes.** Rounded divs with a thick colored `border-left` — the generic "info card" pattern. Instead: use typography, spacing, and background tints to create hierarchy. If you need to call something out, use a full subtle background or a top border.
|
|
103
103
|
- **Avoid three equal boxes with icons.** The default AI landing page layout. Instead: use asymmetric layouts, varied column widths, or a single focused content area.
|
|
104
104
|
- **Avoid timid color palettes.** Evenly distributed, non-committal colors. Instead: one or two dominant colors with sharp accents. Commit to a direction.
|
|
@@ -94,36 +94,131 @@ On deploy, the platform runs `npm install && npm run build` in the web directory
|
|
|
94
94
|
|
|
95
95
|
## API Interface
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
REST endpoints for external consumers — other services, mobile apps, integrations. This is separate from the web frontend's internal RPC (`@mindstudio-ai/interface` calls `/_/methods` directly and does not use the API interface). The API interface lives at `/_/api/` and exposes only the methods you choose to route.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```json
|
|
102
|
-
{
|
|
103
|
-
"methods": ["submit-vendor-request", "list-vendors", "get-dashboard"]
|
|
104
|
-
}
|
|
105
|
-
```
|
|
99
|
+
Use it for receiving webhooks (Stripe, Twilio), sync endpoints for other services, a public REST API, batch tools — anything where something outside the app's own frontend needs to call a method over HTTP.
|
|
106
100
|
|
|
107
|
-
|
|
101
|
+
### Spec: `src/interfaces/api.md`
|
|
108
102
|
|
|
109
|
-
|
|
103
|
+
The human-readable spec. Frontmatter declares the API name and description; the body maps methods to REST routes using MSFM.
|
|
110
104
|
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
105
|
+
```yaml
|
|
106
|
+
---
|
|
107
|
+
name: Vendor Management API
|
|
108
|
+
description: API for managing vendors and purchase orders.
|
|
109
|
+
type: interface/api
|
|
110
|
+
---
|
|
116
111
|
```
|
|
117
112
|
|
|
118
|
-
|
|
113
|
+
Routes are declared as `VERB /path → methodExportName` under resource headings, with annotations for params and descriptions:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
## Vendors
|
|
117
|
+
|
|
118
|
+
### List vendors
|
|
119
|
+
GET /vendors → listVendors
|
|
120
|
+
~~~
|
|
121
|
+
Returns all vendors, optionally filtered by status.
|
|
122
|
+
query: status (string, optional) — filter by vendor status
|
|
123
|
+
~~~
|
|
124
|
+
|
|
125
|
+
### Create vendor
|
|
126
|
+
POST /vendors → submitVendorRequest
|
|
127
|
+
~~~
|
|
128
|
+
Submit a new vendor for approval.
|
|
129
|
+
body: name (string, required) — vendor name
|
|
130
|
+
contactEmail (string, required) — billing contact
|
|
131
|
+
~~~
|
|
132
|
+
|
|
133
|
+
### Delete vendor
|
|
134
|
+
DELETE /vendors/:vendorId → deleteVendor
|
|
135
|
+
~~~
|
|
136
|
+
path: vendorId (string, required) — the vendor's unique identifier
|
|
137
|
+
~~~
|
|
138
|
+
```
|
|
119
139
|
|
|
120
|
-
###
|
|
140
|
+
### Compiled Output: `dist/interfaces/api/api.json`
|
|
121
141
|
|
|
122
|
-
```
|
|
123
|
-
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"api": {
|
|
145
|
+
"name": "Vendor Management API",
|
|
146
|
+
"description": "API for managing vendors and purchase orders.",
|
|
147
|
+
"routes": [
|
|
148
|
+
{
|
|
149
|
+
"method": "GET",
|
|
150
|
+
"path": "/vendors",
|
|
151
|
+
"handler": "list-vendors",
|
|
152
|
+
"summary": "List vendors",
|
|
153
|
+
"description": "Returns all vendors, optionally filtered by status.",
|
|
154
|
+
"tag": "Vendors",
|
|
155
|
+
"params": {
|
|
156
|
+
"query": {
|
|
157
|
+
"status": { "type": "string", "required": false, "description": "Filter by vendor status" }
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"method": "POST",
|
|
163
|
+
"path": "/vendors",
|
|
164
|
+
"handler": "submit-vendor-request",
|
|
165
|
+
"summary": "Create vendor",
|
|
166
|
+
"description": "Submit a new vendor for approval.",
|
|
167
|
+
"tag": "Vendors",
|
|
168
|
+
"params": {
|
|
169
|
+
"body": {
|
|
170
|
+
"name": { "type": "string", "required": true, "description": "Vendor name" },
|
|
171
|
+
"contactEmail": { "type": "string", "required": true, "description": "Billing contact" }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"method": "DELETE",
|
|
177
|
+
"path": "/vendors/:vendorId",
|
|
178
|
+
"handler": "delete-vendor",
|
|
179
|
+
"summary": "Delete vendor",
|
|
180
|
+
"description": "Permanently remove a vendor.",
|
|
181
|
+
"tag": "Vendors",
|
|
182
|
+
"params": {
|
|
183
|
+
"path": {
|
|
184
|
+
"vendorId": { "type": "string", "required": true, "description": "The vendor's unique identifier" }
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
124
191
|
```
|
|
125
192
|
|
|
126
|
-
|
|
193
|
+
| Field | Description |
|
|
194
|
+
|-------|-------------|
|
|
195
|
+
| `name` | API display name (used in generated OpenAPI spec) |
|
|
196
|
+
| `description` | API description |
|
|
197
|
+
| `routes[].method` | HTTP method: `GET`, `POST`, `PUT`, `PATCH`, `DELETE` |
|
|
198
|
+
| `routes[].path` | URL path with `:param` placeholders for path params |
|
|
199
|
+
| `routes[].handler` | Method `id` from the manifest (kebab-case) |
|
|
200
|
+
| `routes[].summary` | Short description for the endpoint |
|
|
201
|
+
| `routes[].description` | Longer description |
|
|
202
|
+
| `routes[].tag` | Resource grouping (becomes a tag in OpenAPI) |
|
|
203
|
+
| `routes[].params` | Parameter declarations: `path`, `query`, and/or `body` objects |
|
|
204
|
+
|
|
205
|
+
### Platform Behavior
|
|
206
|
+
|
|
207
|
+
Routes are mounted at `/_/api{path}` (e.g. `DELETE /_/api/vendors/abc123`).
|
|
208
|
+
|
|
209
|
+
- **Path params** are extracted and merged into the method's input: `/:vendorId` → `{ vendorId: "abc123" }`
|
|
210
|
+
- **Query params** are merged into input for GET requests: `?status=approved` → `{ status: "approved" }`
|
|
211
|
+
- **Request body** for POST/PUT/PATCH is the input directly (no `{ input: {...} }` wrapper)
|
|
212
|
+
- **Response** is the method output directly (no `{ output: {...} }` wrapper)
|
|
213
|
+
- **Auth** via `Authorization: Bearer sk_...` (API key resolves to a user with full RBAC)
|
|
214
|
+
- **Streaming**: `Accept: text/event-stream` header returns SSE chunks
|
|
215
|
+
- **Raw request context**: Every API method receives `input._request` with `{ method, headers, rawBody }`. `rawBody` is the original unparsed body as a UTF-8 string — critical for webhook signature verification (Stripe, GitHub, Shopify). For most methods you don't need `_request` at all.
|
|
216
|
+
|
|
217
|
+
### Manifest
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{ "type": "api", "path": "dist/interfaces/api/api.json" }
|
|
221
|
+
```
|
|
127
222
|
|
|
128
223
|
## Discord Bot
|
|
129
224
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
"interfaces": [
|
|
42
42
|
{ "type": "web", "path": "dist/interfaces/web/web.json" },
|
|
43
|
-
{ "type": "api" },
|
|
43
|
+
{ "type": "api", "path": "dist/interfaces/api/api.json" },
|
|
44
44
|
{ "type": "cron", "path": "dist/interfaces/cron/interface.json" }
|
|
45
45
|
],
|
|
46
46
|
|
|
@@ -71,11 +71,12 @@
|
|
|
71
71
|
| Field | Type | Required | Description |
|
|
72
72
|
|-------|------|----------|-------------|
|
|
73
73
|
| `enabled` | `boolean` | Yes | `true` to enable auth |
|
|
74
|
-
| `methods` | `string[]` | Yes | Auth methods: `"email-code"`, `"sms-code"`. At least one required. |
|
|
74
|
+
| `methods` | `string[]` | Yes | Auth methods: `"email-code"`, `"sms-code"`, `"api-key"`. At least one required. |
|
|
75
75
|
| `table.name` | `string` | Yes | Name of the `defineTable` table holding user records |
|
|
76
76
|
| `table.columns.email` | `string` | If email-code | Column name for email (platform-managed, read-only from code) |
|
|
77
77
|
| `table.columns.phone` | `string` | If sms-code | Column name for phone (platform-managed, read-only from code) |
|
|
78
78
|
| `table.columns.roles` | `string` | No | Column name for roles array (bidirectional sync) |
|
|
79
|
+
| `table.columns.apiKey` | `string` | If api-key | Column name for API key (platform-managed, stores masked value) |
|
|
79
80
|
|
|
80
81
|
### `roles`
|
|
81
82
|
`Array<{ id, name?, description? }>`. Defaults to `[]`.
|
|
@@ -252,3 +252,43 @@ const result = await api.generateReport(
|
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
The platform handles the SSE transport. The method returns normally — streaming is managed by the SDK and platform, not by your method code.
|
|
255
|
+
|
|
256
|
+
## Raw Request Context (API Interface)
|
|
257
|
+
|
|
258
|
+
Methods invoked via the API interface receive `input._request` alongside the parsed input:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
input._request: {
|
|
262
|
+
method: string; // "GET", "POST", etc.
|
|
263
|
+
headers: Record<string, string>; // all headers (lowercase keys)
|
|
264
|
+
rawBody: string | undefined; // original unparsed body (UTF-8)
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`rawBody` preserves the exact bytes the client sent — whitespace, key ordering, encoding. Use it for webhook signature verification:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
export async function stripeWebhook(input: {
|
|
272
|
+
type: string;
|
|
273
|
+
data: any;
|
|
274
|
+
_request: { headers: Record<string, string>; rawBody: string };
|
|
275
|
+
}) {
|
|
276
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
|
|
277
|
+
|
|
278
|
+
const event = stripe.webhooks.constructEvent(
|
|
279
|
+
input._request.rawBody,
|
|
280
|
+
input._request.headers['stripe-signature'],
|
|
281
|
+
process.env.STRIPE_WEBHOOK_SECRET!,
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
switch (event.type) {
|
|
285
|
+
case 'payment_intent.succeeded':
|
|
286
|
+
// ...
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return { received: true };
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
For most methods, you don't need `_request` — the parsed path params, query params, and body fields are already on `input` directly.
|
|
@@ -40,7 +40,7 @@ my-app/
|
|
|
40
40
|
web.json dev server config
|
|
41
41
|
package.json
|
|
42
42
|
src/
|
|
43
|
-
api/
|
|
43
|
+
api/api.json REST API config
|
|
44
44
|
discord/interface.json Discord bot config
|
|
45
45
|
telegram/interface.json Telegram bot config
|
|
46
46
|
cron/interface.json cron config
|
|
@@ -96,6 +96,7 @@ const { vendor } = await api.approveVendor({ vendorId: '...' });
|
|
|
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.** Each method invocation runs in its own isolated execution context 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.
|
|
99
|
+
- **Secrets.** Encrypted environment variables with separate dev/prod values. Injected as `process.env` in methods. For third-party service credentials not covered by the SDK.
|
|
99
100
|
|
|
100
101
|
## Minimum Viable App
|
|
101
102
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Secrets & Environment Variables
|
|
2
|
+
|
|
3
|
+
Apps can store encrypted secrets (API keys, database URLs, tokens) that get injected into method execution as `process.env` variables. Secrets have separate dev and prod values — dev values are used in the editor sandbox, prod values are used in deployed releases.
|
|
4
|
+
|
|
5
|
+
## When to Use Secrets
|
|
6
|
+
|
|
7
|
+
Secrets are for third-party services that aren't covered by the MindStudio SDK. If the SDK already provides a capability (AI models, SMS, email, web search, image generation, etc.), use the SDK — it handles auth, billing, and key management automatically.
|
|
8
|
+
|
|
9
|
+
Use secrets for things like Stripe, webhook signing secrets, or any other external service you connect to directly.
|
|
10
|
+
|
|
11
|
+
Never expose secrets to frontends or interfaces. You can only consume secrets in backend methods.
|
|
12
|
+
|
|
13
|
+
## Accessing Secrets
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
export async function createPaymentIntent(input: { amount: number }) {
|
|
17
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
|
|
18
|
+
// stripe.create....
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Never hardcode credentials in method source — always use `process.env`.
|
|
23
|
+
|
|
24
|
+
## Key Format
|
|
25
|
+
|
|
26
|
+
Uppercase snake_case, starting with a letter: `STRIPE_SECRET_KEY`, `DATABASE_URL`, `GITHUB_TOKEN`.
|
|
27
|
+
|
|
28
|
+
## Dev vs Prod
|
|
29
|
+
|
|
30
|
+
Each secret has a dev value and a prod value. The same code (`process.env.STRIPE_SECRET_KEY`) automatically resolves to the right value based on execution context. Use test/sandbox keys for dev, live keys for prod - or use the same value for both if the service does not make a distinction.
|
|
31
|
+
|
|
32
|
+
## Management
|
|
33
|
+
|
|
34
|
+
Secrets are managed through the app's dashboard or the `mindstudio-prod secrets` CLI.
|
|
35
|
+
|
|
36
|
+
## What NOT to Store
|
|
37
|
+
|
|
38
|
+
- AI model API keys (OpenAI, Anthropic, Google) — use the SDK
|
|
39
|
+
- Keys for platform-provided integrations (SMS, email, web search, image gen) — use the SDK
|
|
40
|
+
- Non-sensitive values — use method input parameters or database tables
|
|
@@ -19,7 +19,7 @@ The scaffold starts with these spec files that cover the full picture of the app
|
|
|
19
19
|
- **`src/interfaces/@brand/voice.md`** — voice and terminology: tone, error messages, word choices
|
|
20
20
|
- **`src/roadmap/`** — feature roadmap. One file per feature (`type: roadmap`). See "Roadmap" below.
|
|
21
21
|
|
|
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.
|
|
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. The API interface is useful whenever the app needs to receive or serve external HTTP requests — webhook endpoints, sync APIs, batch tools — not just comprehensive REST APIs. Organize however serves clarity — the platform reads the entire `src/` folder.
|
|
23
23
|
|
|
24
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
|
|
|
@@ -47,12 +47,17 @@ For multi-step tasks with branching logic (research, enrichment, content pipelin
|
|
|
47
47
|
### State Management
|
|
48
48
|
- Calls to methods introduce latency. When building web frontends that load data from methods, front-load 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. User experience and perceived speed/performance are far more valuable than normalization and good REST API design.
|
|
49
49
|
|
|
50
|
+
### Secrets & Third-Party Integrations
|
|
51
|
+
When a method needs credentials for a third-party service, use `process.env` and use the CLI to set it on behalf of the user (chat logs are secure and scrubbed, so it's fine for them to paste) or they can set it manually in the Dashboard.
|
|
52
|
+
|
|
53
|
+
When integrating with external services that have programmable setup APIs (webhook registration, OAuth app config, etc.), automate the setup rather than sending the user to the service's dashboard. If you have the API key in `process.env`, use it to register webhooks, configure endpoints, and store any resulting secrets (like signing keys) automatically. The user shouldn't have to leave the conversation for setup steps you can handle programmatically.
|
|
54
|
+
|
|
50
55
|
### Dependencies
|
|
51
56
|
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.
|
|
52
57
|
|
|
53
58
|
### Production App Management
|
|
54
59
|
You have access to `mindstudio-prod`, a CLI for managing the user's production MindStudio app. Use it via your bash tool. All output is JSON. Run `mindstudio-prod --help` or `mindstudio-prod <command> --help` to discover usage and available options.
|
|
55
60
|
|
|
56
|
-
Available commands: `requests` (logs, error rates, latency), `releases` (deploy status, history), `domains` (custom subdomain management), `users` (list, set roles), `db` (query production sql db), `methods` (list, invoke).
|
|
61
|
+
Available commands: `requests` (logs, error rates, latency), `releases` (deploy status, history), `domains` (custom subdomain management), `users` (list, set roles), `db` (query production sql db), `methods` (list, invoke), `secrets` (list, get, set, delete).
|
|
57
62
|
|
|
58
63
|
Use when the user asks about production behavior (errors, logs, metrics), wants to manage their live app (domains, users, roles), needs to seed or query production data, or wants to check release status.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- Pushing to main branch will trigger a deploy. The user presses the publish button in the interface to request publishing.
|
|
18
18
|
|
|
19
19
|
### Build Notes
|
|
20
|
-
For complex tasks — especially an initial buildout from a spec or making multiple changes in a single turn — write a `.remy-notes.md` scratchpad in the project root. Use it to track progress: a checklist of what's been built and what's remaining. Do not include implementation details or other decisions in the notes - it is solely for keeping track of tasks. Read the spec files directly when you need design details, implementation decisions, or other reference materials. Delete the notes file when your work is done.
|
|
20
|
+
For complex tasks — especially an initial buildout from a spec or making multiple changes in a single turn — write a `.remy-notes.md` scratchpad in the project root. Use it to track progress: a checklist of what's been built and what's remaining. Do not include implementation details or other decisions in the notes - it is solely for keeping track of tasks. Read the spec files directly when you need design details, implementation decisions, or other reference materials - never write them to the notes file. Delete the notes file when your work is done.
|
|
21
21
|
|
|
22
22
|
## Communication
|
|
23
23
|
The user can already see your tool calls, so most of your work is visible without narration. Focus text output on three things:
|
|
@@ -8,6 +8,8 @@ Most things are fine. These are fast-moving products built by non-technical user
|
|
|
8
8
|
|
|
9
9
|
**A package is dead or superseded.** If the plan involves a package, do a quick web search. Only flag it if there's a clearly better, actively maintained alternative. "This works fine" is a valid finding.
|
|
10
10
|
|
|
11
|
+
**External HTTP endpoints should use the API interface.** If the plan involves receiving webhooks from external services (Stripe, Twilio, etc.), exposing sync endpoints, or serving any external HTTP requests, flag that the API interface (`src/interfaces/api.md`) is the right tool. Don't build custom HTTP handling when the platform handles routing, auth, and OpenAPI generation.
|
|
12
|
+
|
|
11
13
|
**There's a managed SDK action for this.** If the plan involves writing custom code for something that sounds like media processing, email/SMS, third-party APIs, or AI model calls — check `askMindStudioSdk`. The managed action handles retries, auth, and scaling.
|
|
12
14
|
|
|
13
15
|
**Project organization needs a reset.** After heavy iteration, a file or folder structure might have grown unwieldy. If things would genuinely benefit from being reorganized, say so. But only at the structural level — "this 500-line component should be a folder" not "rename this variable."
|
|
@@ -16,6 +18,8 @@ Most things are fine. These are fast-moving products built by non-technical user
|
|
|
16
18
|
|
|
17
19
|
These are things we already know about and have decided to accept:
|
|
18
20
|
|
|
21
|
+
- API interface methods have access to `input._request.rawBody` for webhook signature verification (Stripe, GitHub, etc.). Do NOT suggest external proxies or workarounds — the raw body is available natively.
|
|
22
|
+
|
|
19
23
|
- Limited browser support for `oklch` gradients using `in <colorspace>` syntax — we accept the compatibility tradeoff for better color quality
|
|
20
24
|
- Limited browser support for CSS scroll-driven animations (`animation-timeline: scroll()` / `view()`) - we accept this tradeoff
|
|
21
25
|
- Platform SDKs (these are the core of every MindStudio app):
|
|
@@ -36,6 +40,10 @@ These are things we already know about and have decided to accept:
|
|
|
36
40
|
|
|
37
41
|
### Common pitfalls (always flag these)
|
|
38
42
|
|
|
43
|
+
- **External redirects in iframe.** If the plan involves redirecting to a third-party domain (payment checkout, OAuth login, external auth), flag that `window.location.href = url` will break in the preview iframe. Use `window.open(url, '_top')` for same-tab navigation or `window.open(url, '_blank')` for a new tab. This applies to any external redirect — Stripe, OAuth providers, third-party login pages.
|
|
44
|
+
|
|
45
|
+
- **Hardcoded credentials.** If the plan or code contains API keys, tokens, or connection strings inline, flag it — these should be `process.env` secrets managed via the dashboard. Also flag if the plan uses `process.env` for something the MindStudio SDK already handles (AI model keys, email/SMS sending, etc.).
|
|
46
|
+
|
|
39
47
|
These are recurring mistakes the coding agent makes. If you see the conditions for any of these, flag it proactively:
|
|
40
48
|
|
|
41
49
|
- **CSS Module animation scoping.** If the agent defines `@keyframes` in a global CSS file but references the animation name from a CSS Module, the animation will silently fail. CSS Modules scope animation names, so a keyframe defined globally can't be found by a scoped class. The fix: define keyframes in the same CSS Module that uses them, or use `:global()` to escape the scoping.
|
|
@@ -46,7 +46,7 @@ Every interface must work on both desktop and mobile.
|
|
|
46
46
|
## What to Actively Avoid At All Costs
|
|
47
47
|
|
|
48
48
|
- **Avoid generic fonts.** Overused defaults that strip away all personality. Instead: pick a distinctive Google Font that fits the app's character.
|
|
49
|
-
- **Avoid purple or indigo anything.** Purple gradients, purple buttons, purple accents are overused. The user will be dismissive of our designs if they come out looking purple or indigo.
|
|
49
|
+
- **Avoid purple or indigo anything.** Purple gradients, purple buttons, purple accents are overused. The user will be dismissive of our designs if they come out looking purple or indigo. Avoid terracotta for similar reasons. Challenge yourself to choose beautiful, modern, 2026-inspired colors.
|
|
50
50
|
- **Avoid colored left-border callout boxes.** Rounded divs with a thick colored `border-left` — the generic "info card" pattern. Instead: use typography, spacing, and background tints to create hierarchy. If you need to call something out, use a full subtle background or a top border.
|
|
51
51
|
- **Avoid three equal boxes with icons.** The default AI landing page layout. Instead: use asymmetric layouts, varied column widths, or a single focused content area.
|
|
52
52
|
- **Avoid timid color palettes.** Evenly distributed, non-committal colors. Instead: one or two dominant colors with sharp accents. Commit to a direction.
|