@mindstudio-ai/remy 0.1.243 → 0.1.245

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 CHANGED
@@ -557,24 +557,31 @@ function getOrgContext() {
557
557
  function renderOrgContextBlock() {
558
558
  const ctx = cached;
559
559
  const auth = ctx?.auth;
560
- if (!auth || !auth.delegatedAvailable && !auth.requireDelegatedOnly) {
560
+ const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
561
+ const hasDesignSystem = !!ctx?.designSystem;
562
+ if (!hasAuth && !hasDesignSystem) {
561
563
  return "";
562
564
  }
563
- const lines = ["<org_auth_context>"];
565
+ const lines = ["<org_context>"];
564
566
  if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
565
567
  lines.push(`This app is owned by the organization "${ctx.org.name}".`);
566
568
  }
567
- if (auth.delegatedAvailable) {
569
+ if (auth?.delegatedAvailable) {
568
570
  lines.push(
569
571
  '"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
570
572
  );
571
573
  }
572
- if (auth.requireDelegatedOnly) {
574
+ if (auth?.requireDelegatedOnly) {
573
575
  lines.push(
574
576
  "This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
575
577
  );
576
578
  }
577
- lines.push("</org_auth_context>");
579
+ if (hasDesignSystem) {
580
+ lines.push(
581
+ "This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
582
+ );
583
+ }
584
+ lines.push("</org_context>");
578
585
  return lines.join("\n");
579
586
  }
580
587
 
@@ -1874,11 +1881,11 @@ var setProjectMetadataTool = {
1874
1881
  },
1875
1882
  iconUrl: {
1876
1883
  type: "string",
1877
- description: "URL for the app icon (square."
1884
+ description: "URL for the app icon (square)."
1878
1885
  },
1879
1886
  openGraphShareImageUrl: {
1880
1887
  type: "string",
1881
- description: "URL for the Open Graph share image (1200x630)."
1888
+ description: "URL for the Open Graph share image (1200\xD7630 PNG)."
1882
1889
  }
1883
1890
  }
1884
1891
  }
@@ -2812,9 +2819,7 @@ async function analyzeImage(params) {
2812
2819
 
2813
2820
  // src/tools/_helpers/screenshot.ts
2814
2821
  var SCREENSHOT_ANALYSIS_PROMPT = `Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be comprehensive, thorough, and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).`;
2815
- var TEXT_WRAP_DISCLAIMER = `Note: ignore text wrapping issues. Screenshots occasionally show text wrapping onto an extra line compared to the live page \u2014 most noticeable in buttons, badges, and headings. This is a known limitation of SVG foreignObject rendering used the DOM-to-image capture library that took the screenshot. The browser's SVG renderer computes slightly wider text metrics than the HTML layout engine, so text that fits on one line in the live DOM can overflow by a fraction of a pixel in the capture - this is not a real issue.
2816
-
2817
- Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
2822
+ var ANALYSIS_RESPONSE_FORMAT = `Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
2818
2823
  function buildScreenshotAnalysisPrompt(opts) {
2819
2824
  let p = opts?.prompt || SCREENSHOT_ANALYSIS_PROMPT;
2820
2825
  if (opts?.styleMap) {
@@ -2828,7 +2833,7 @@ ${opts.styleMap}
2828
2833
  }
2829
2834
  p += `
2830
2835
 
2831
- ${TEXT_WRAP_DISCLAIMER}`;
2836
+ ${ANALYSIS_RESPONSE_FORMAT}`;
2832
2837
  return p;
2833
2838
  }
2834
2839
  async function streamScreenshotAnalysis(opts) {
@@ -2854,6 +2859,9 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2854
2859
  let model;
2855
2860
  let path13;
2856
2861
  let fullPage = true;
2862
+ let width;
2863
+ let height;
2864
+ let format;
2857
2865
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
2858
2866
  prompt = promptOrOptions.prompt;
2859
2867
  existingUrl = promptOrOptions.imageUrl;
@@ -2861,11 +2869,17 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2861
2869
  if (promptOrOptions.fullPage !== void 0) {
2862
2870
  fullPage = promptOrOptions.fullPage;
2863
2871
  }
2872
+ width = promptOrOptions.width;
2873
+ height = promptOrOptions.height;
2874
+ format = promptOrOptions.format;
2864
2875
  onLog = promptOrOptions.onLog;
2865
2876
  model = promptOrOptions.model;
2866
2877
  } else {
2867
2878
  prompt = promptOrOptions;
2868
2879
  }
2880
+ if (width != null && height != null) {
2881
+ fullPage = false;
2882
+ }
2869
2883
  let url;
2870
2884
  let styleMap;
2871
2885
  if (existingUrl) {
@@ -2873,7 +2887,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2873
2887
  } else {
2874
2888
  const ssResult = await sidecarRequest(
2875
2889
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
2876
- path13 ? { path: path13 } : void 0,
2890
+ {
2891
+ ...path13 ? { path: path13 } : {},
2892
+ ...width != null ? { width } : {},
2893
+ ...height != null ? { height } : {},
2894
+ ...format ? { format } : {}
2895
+ },
2877
2896
  { timeout: fullPage ? 12e4 : 3e4 }
2878
2897
  );
2879
2898
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -4002,7 +4021,7 @@ var screenshotTool = {
4002
4021
  clearable: true,
4003
4022
  definition: {
4004
4023
  name: "screenshot",
4005
- description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps.",
4024
+ description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps. To render a fixed-size image such as an Open Graph share card, set `width` and `height` (e.g. 1200 \xD7 630) and `format: 'png'`: the tool navigates to `path`, clips to exactly those pixel dimensions, and returns the image URL.",
4006
4025
  inputSchema: {
4007
4026
  type: "object",
4008
4027
  properties: {
@@ -4022,6 +4041,19 @@ var screenshotTool = {
4022
4041
  type: "string",
4023
4042
  description: 'Navigate to this path before capturing (e.g. "/settings", "/dashboard"). If omitted, screenshots the current page.'
4024
4043
  },
4044
+ width: {
4045
+ type: "number",
4046
+ description: "Exact capture width in pixels. Set together with `height` to render a fixed-size image; clips to exactly this viewport instead of the default preview size."
4047
+ },
4048
+ height: {
4049
+ type: "number",
4050
+ description: "Exact capture height in pixels. Set together with `width`."
4051
+ },
4052
+ format: {
4053
+ type: "string",
4054
+ enum: ["png", "jpeg"],
4055
+ description: "Output image format. Defaults to 'jpeg'. Use 'png' for crisp flat graphics like share cards, where JPEG artifacts show on sharp type and edges."
4056
+ },
4025
4057
  instructions: {
4026
4058
  type: "string",
4027
4059
  description: "If the screenshot you need requires interaction first (dismissing a modal, clicking a tab, filling out a form, navigating a flow, scrolling to a section, getting through a login/auth checkpoint), describe the steps to get there. A browser automation agent will follow these instructions, then capture per your `fullPage` choice \u2014 so with `fullPage: false` you can scroll to a section and capture just that viewport. It can bypass auth and get right to where it needs to be if you tell it to authenticate as a test user and give it the path/screen to start its test at. Never describe what names or values to use when applying the instructions - the browser automation agent must use its own values for it to work properly. If a specific auth role is required to access the content, be sure to note that - it can automatically assume it for the purpose of testing. Use only when interaction is required to *reach* the state you want to capture \u2014 log in, dismiss a modal, switch a tab, follow a route, scroll to a section. If your steps are exercising the app's functionality across multiple states (running flows, asserting behavior under interaction, multi-step QA), use `runAutomatedBrowserTest` instead."
@@ -4064,6 +4096,9 @@ var screenshotTool = {
4064
4096
  prompt: input.prompt,
4065
4097
  path: input.path,
4066
4098
  fullPage,
4099
+ width: input.width,
4100
+ height: input.height,
4101
+ format: input.format,
4067
4102
  onLog: context?.onLog,
4068
4103
  model: resolveModel("imageAnalysis", context?.models, context?.model)
4069
4104
  });
package/dist/index.js CHANGED
@@ -1462,11 +1462,11 @@ var init_setProjectMetadata = __esm({
1462
1462
  },
1463
1463
  iconUrl: {
1464
1464
  type: "string",
1465
- description: "URL for the app icon (square."
1465
+ description: "URL for the app icon (square)."
1466
1466
  },
1467
1467
  openGraphShareImageUrl: {
1468
1468
  type: "string",
1469
- description: "URL for the Open Graph share image (1200x630)."
1469
+ description: "URL for the Open Graph share image (1200\xD7630 PNG)."
1470
1470
  }
1471
1471
  }
1472
1472
  }
@@ -3555,7 +3555,7 @@ ${opts.styleMap}
3555
3555
  }
3556
3556
  p += `
3557
3557
 
3558
- ${TEXT_WRAP_DISCLAIMER}`;
3558
+ ${ANALYSIS_RESPONSE_FORMAT}`;
3559
3559
  return p;
3560
3560
  }
3561
3561
  async function streamScreenshotAnalysis(opts) {
@@ -3581,6 +3581,9 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3581
3581
  let model;
3582
3582
  let path14;
3583
3583
  let fullPage = true;
3584
+ let width;
3585
+ let height;
3586
+ let format;
3584
3587
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
3585
3588
  prompt = promptOrOptions.prompt;
3586
3589
  existingUrl = promptOrOptions.imageUrl;
@@ -3588,11 +3591,17 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3588
3591
  if (promptOrOptions.fullPage !== void 0) {
3589
3592
  fullPage = promptOrOptions.fullPage;
3590
3593
  }
3594
+ width = promptOrOptions.width;
3595
+ height = promptOrOptions.height;
3596
+ format = promptOrOptions.format;
3591
3597
  onLog = promptOrOptions.onLog;
3592
3598
  model = promptOrOptions.model;
3593
3599
  } else {
3594
3600
  prompt = promptOrOptions;
3595
3601
  }
3602
+ if (width != null && height != null) {
3603
+ fullPage = false;
3604
+ }
3596
3605
  let url;
3597
3606
  let styleMap;
3598
3607
  if (existingUrl) {
@@ -3600,7 +3609,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3600
3609
  } else {
3601
3610
  const ssResult = await sidecarRequest(
3602
3611
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
3603
- path14 ? { path: path14 } : void 0,
3612
+ {
3613
+ ...path14 ? { path: path14 } : {},
3614
+ ...width != null ? { width } : {},
3615
+ ...height != null ? { height } : {},
3616
+ ...format ? { format } : {}
3617
+ },
3604
3618
  { timeout: fullPage ? 12e4 : 3e4 }
3605
3619
  );
3606
3620
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -3627,16 +3641,14 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3627
3641
  model
3628
3642
  });
3629
3643
  }
3630
- var SCREENSHOT_ANALYSIS_PROMPT, TEXT_WRAP_DISCLAIMER;
3644
+ var SCREENSHOT_ANALYSIS_PROMPT, ANALYSIS_RESPONSE_FORMAT;
3631
3645
  var init_screenshot = __esm({
3632
3646
  "src/tools/_helpers/screenshot.ts"() {
3633
3647
  "use strict";
3634
3648
  init_sidecar();
3635
3649
  init_analyzeImage();
3636
3650
  SCREENSHOT_ANALYSIS_PROMPT = `Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be comprehensive, thorough, and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).`;
3637
- TEXT_WRAP_DISCLAIMER = `Note: ignore text wrapping issues. Screenshots occasionally show text wrapping onto an extra line compared to the live page \u2014 most noticeable in buttons, badges, and headings. This is a known limitation of SVG foreignObject rendering used the DOM-to-image capture library that took the screenshot. The browser's SVG renderer computes slightly wider text metrics than the HTML layout engine, so text that fits on one line in the live DOM can overflow by a fraction of a pixel in the capture - this is not a real issue.
3638
-
3639
- Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
3651
+ ANALYSIS_RESPONSE_FORMAT = `Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
3640
3652
  }
3641
3653
  });
3642
3654
 
@@ -4622,7 +4634,7 @@ var init_screenshot2 = __esm({
4622
4634
  clearable: true,
4623
4635
  definition: {
4624
4636
  name: "screenshot",
4625
- description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps.",
4637
+ description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps. To render a fixed-size image such as an Open Graph share card, set `width` and `height` (e.g. 1200 \xD7 630) and `format: 'png'`: the tool navigates to `path`, clips to exactly those pixel dimensions, and returns the image URL.",
4626
4638
  inputSchema: {
4627
4639
  type: "object",
4628
4640
  properties: {
@@ -4642,6 +4654,19 @@ var init_screenshot2 = __esm({
4642
4654
  type: "string",
4643
4655
  description: 'Navigate to this path before capturing (e.g. "/settings", "/dashboard"). If omitted, screenshots the current page.'
4644
4656
  },
4657
+ width: {
4658
+ type: "number",
4659
+ description: "Exact capture width in pixels. Set together with `height` to render a fixed-size image; clips to exactly this viewport instead of the default preview size."
4660
+ },
4661
+ height: {
4662
+ type: "number",
4663
+ description: "Exact capture height in pixels. Set together with `width`."
4664
+ },
4665
+ format: {
4666
+ type: "string",
4667
+ enum: ["png", "jpeg"],
4668
+ description: "Output image format. Defaults to 'jpeg'. Use 'png' for crisp flat graphics like share cards, where JPEG artifacts show on sharp type and edges."
4669
+ },
4645
4670
  instructions: {
4646
4671
  type: "string",
4647
4672
  description: "If the screenshot you need requires interaction first (dismissing a modal, clicking a tab, filling out a form, navigating a flow, scrolling to a section, getting through a login/auth checkpoint), describe the steps to get there. A browser automation agent will follow these instructions, then capture per your `fullPage` choice \u2014 so with `fullPage: false` you can scroll to a section and capture just that viewport. It can bypass auth and get right to where it needs to be if you tell it to authenticate as a test user and give it the path/screen to start its test at. Never describe what names or values to use when applying the instructions - the browser automation agent must use its own values for it to work properly. If a specific auth role is required to access the content, be sure to note that - it can automatically assume it for the purpose of testing. Use only when interaction is required to *reach* the state you want to capture \u2014 log in, dismiss a modal, switch a tab, follow a route, scroll to a section. If your steps are exercising the app's functionality across multiple states (running flows, asserting behavior under interaction, multi-step QA), use `runAutomatedBrowserTest` instead."
@@ -4684,6 +4709,9 @@ var init_screenshot2 = __esm({
4684
4709
  prompt: input.prompt,
4685
4710
  path: input.path,
4686
4711
  fullPage,
4712
+ width: input.width,
4713
+ height: input.height,
4714
+ format: input.format,
4687
4715
  onLog: context?.onLog,
4688
4716
  model: resolveModel("imageAnalysis", context?.models, context?.model)
4689
4717
  });
@@ -5718,24 +5746,31 @@ function getOrgContext() {
5718
5746
  function renderOrgContextBlock() {
5719
5747
  const ctx = cached;
5720
5748
  const auth = ctx?.auth;
5721
- if (!auth || !auth.delegatedAvailable && !auth.requireDelegatedOnly) {
5749
+ const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
5750
+ const hasDesignSystem = !!ctx?.designSystem;
5751
+ if (!hasAuth && !hasDesignSystem) {
5722
5752
  return "";
5723
5753
  }
5724
- const lines = ["<org_auth_context>"];
5754
+ const lines = ["<org_context>"];
5725
5755
  if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
5726
5756
  lines.push(`This app is owned by the organization "${ctx.org.name}".`);
5727
5757
  }
5728
- if (auth.delegatedAvailable) {
5758
+ if (auth?.delegatedAvailable) {
5729
5759
  lines.push(
5730
5760
  '"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
5731
5761
  );
5732
5762
  }
5733
- if (auth.requireDelegatedOnly) {
5763
+ if (auth?.requireDelegatedOnly) {
5734
5764
  lines.push(
5735
5765
  "This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
5736
5766
  );
5737
5767
  }
5738
- lines.push("</org_auth_context>");
5768
+ if (hasDesignSystem) {
5769
+ lines.push(
5770
+ "This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
5771
+ );
5772
+ }
5773
+ lines.push("</org_context>");
5739
5774
  return lines.join("\n");
5740
5775
  }
5741
5776
  var log9, cached;
@@ -34,7 +34,7 @@ Remy apps can have and manage their own users. Auth is opt-in: configure it in t
34
34
  - `email-code` — 6-digit code sent via email
35
35
  - `sms-code` — 6-digit code sent via SMS
36
36
  - `api-key` — programmatic access via `Authorization: Bearer sk_...` header. Resolves to a user with full RBAC.
37
- - `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<org_auth_context>` block signals availability. See *Organization-Managed Sign-In* above.
37
+ - `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<org_context>` block signals availability. See *Organization-Managed Sign-In* above.
38
38
  - **`auth.table.name`** — name of the `defineTable` table that holds user records.
39
39
  - **`auth.table.columns`** — maps platform-managed fields to column names in the developer's table.
40
40
  - `email` — required if `email-code` is in methods
@@ -135,12 +135,12 @@ const user = await auth.verifySmsCode(verificationId, '123456');
135
135
 
136
136
  ## Organization-Managed Sign-In ("Sign in with Remy")
137
137
 
138
- Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<org_auth_context>` block (near the end) stating the organization name and whether delegated sign-in is available. Sign in with Remy is a way to make authentication seamless for internal apps - it should not be used for public-facing applications. The app owner will need to add users to their workspace's team on the Remy platform and those users will need Remy accounts for it to work.
138
+ Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<org_context>` block (near the end); for org-managed sign-in it states the organization name and whether delegated sign-in is available. Sign in with Remy is a way to make authentication seamless for internal apps - it should not be used for public-facing applications. The app owner will need to add users to their workspace's team on the Remy platform and those users will need Remy accounts for it to work.
139
139
 
140
140
  - **When it says "Sign in with Remy" is available** — offer delegated sign-in: a **"Continue with {Org}"** button wired to the `remy` method (see *Sign in with Remy (delegated)* below). Use the exact organization name from the block for the label. For an org-owned app this is usually the primary sign-in — the members already have platform identities, so a verification-code form is redundant.
141
141
  - **When it says the organization requires delegated sign-in** — `remy` is the *only* human method: do not add `email-code` or `sms-code`. Those are blocked at the platform edge for the org's apps, so building them yields a login that can't work.
142
142
 
143
- When no `<org_auth_context>` block is present — the common case — do not build it or offer to build it. This is an auth scheme for enterprises building internal apps only, and it requires a Remy enterprise plan to use. When enabled, the platform decides who the user is (like "Sign in with Google"); the app just starts the flow and reads the result.
143
+ When the `<org_context>` block is absent, or present without a delegated-sign-in line — the common case — do not build it or offer to build it. This is an auth scheme for enterprises building internal apps only, and it requires a Remy enterprise plan to use. When enabled, the platform decides who the user is (like "Sign in with Google"); the app just starts the flow and reads the result.
144
144
 
145
145
  ```typescript
146
146
  // "Continue with {Org}" button — must be triggered by a user gesture (click).
@@ -399,7 +399,7 @@ Consult the `visualDesignExpert` to help you work through authentication at a hi
399
399
  ### Rules for Building Auth Screens
400
400
  **Auth modes:** Think about which mode(s) makes the most sense for the type of app you are building. Consumer apps likely to be used on mobile should probably tend toward SMS auth as the default - business apps used on desktop make more sense to use email verification - or allow both, there's no harm in giving the user choice!
401
401
 
402
- **"Continue with {Org}" (delegated):** When `<org_auth_context>` says delegated sign-in is available, a single "Continue with {Org}" button is the primary path — often the *only* one — and there's no verification-code step to design at all (the platform handles it). Give the button real weight in the branded login moment rather than treating it as a secondary option, and use the exact organization name. If the org also allows code methods, delegated goes first with the code form beneath. On return from the handshake (and on dashboard launch), render a brief "Completing sign-in…" state driven by `auth.authStatus === 'authenticating'` — never the login form — so a successful sign-in doesn't flash the logged-out screen.
402
+ **"Continue with {Org}" (delegated):** When the `<org_context>` block says delegated sign-in is available, a single "Continue with {Org}" button is the primary path — often the *only* one — and there's no verification-code step to design at all (the platform handles it). Give the button real weight in the branded login moment rather than treating it as a secondary option, and use the exact organization name. If the org also allows code methods, delegated goes first with the code form beneath. On return from the handshake (and on dashboard launch), render a brief "Completing sign-in…" state driven by `auth.authStatus === 'authenticating'` — never the login form — so a successful sign-in doesn't flash the logged-out screen.
403
403
 
404
404
  **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, a beautiful animation and 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. Make sure there is no layout shift when loading in the success/error states - loading spinners must never pop in below the input and shift the content, for example.
405
405
 
@@ -76,6 +76,6 @@ When you receive background results:
76
76
 
77
77
  You can only background the following two tasks, unless the user specifically asks you to do work in the background:
78
78
  - `productVision` seeding the intiial roadmap after writing the spec for the first time or updating the roadmap after large work sessions. This task takes a while and we can allow the user to continue building while it happens in the background.
79
- - After writing the spec, once you have finalized the shape of the app, ask `visualDesignExpert` to create an icon and an open graph shring image for the app, then set them with `setProjectMetadata`, alongside the app's name and short description.
79
+ - After writing the spec, once you have finalized the shape of the app, ask `visualDesignExpert` to create an icon and to design an Open Graph share image, then set them with `setProjectMetadata` alongside the app's name and short description. The icon is a generated asset. The share image should be composed as a self-contained HTML card (real lockup, brand fonts, exact type) and captured — not generated: serve the card HTML from `dist/interfaces/web/public/`, screenshot it with the `screenshot` tool at `width: 1200, height: 630, format: 'png'`, and save the resulting PNG into the app's public assets so the deployed site hosts it.
80
80
 
81
81
  Do not background any other tasks. Be aware that sometimes tools like specSync will background on their own - this is not something that is within your control.
@@ -77,7 +77,9 @@ Keep logos and icons consistent - if you already have a logo, use `editImages` t
77
77
 
78
78
  #### Open Graph Sharing Images
79
79
 
80
- OG images show up in iMessage, Slack, Twitter, etc. at small sizes. They're a mood piece, not a messaging opportunity. Keep text minimal: the app name and at most a short tagline (three to five words). Think App Store feature card — one beautiful composition that makes someone want to tap. The text should feel integrated into the scene, not pasted on a background. Generate at 4096 × 2150 and return the CDN URL.
80
+ OG images show up in iMessage, Slack, Twitter, etc. at small sizes. They're a mood piece, not a messaging opportunity. Keep text minimal: the app name and at most a short tagline (three to five words). Think App Store feature card — one beautiful composition that makes someone want to tap. The text should feel integrated into the scene, not pasted on a background.
81
+
82
+ A share card is a wordmark, a short line, and a logo on a brand field — **compose it as HTML, don't generate it with the image model.** A generated image gives you odd letterforms and no brand fidelity; HTML gives you the real SVG lockup, the actual brand fonts, exact colors, and pixel-perfect spacing. Author a self-contained HTML document sized to 1200 × 630 — the lockup inline as SVG, the brand fonts inlined as base64 (so nothing loads late and captures as a fallback), the palette and type exact — then capture it with the `screenshot` tool at `width: 1200, height: 630, format: 'png'`, a faithful real-browser render. Don't route it through a document/HTML-to-image "openGraph" render mode; that pipeline strips CSS backgrounds. The same compose-and-capture approach beats generation for any precise brand graphic where letterforms and spacing carry the design.
81
83
 
82
84
  ### When to use images
83
85
 
@@ -20,7 +20,7 @@ Login and signup screens set the tone for the user's entire experience with the
20
20
 
21
21
  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. Remy apps support SMS code verification, email verification, delegated "Sign in with Remy", or a combination, depending on how the app is configured.
22
22
 
23
- **"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <org_auth_context> - it should not be used for public-facing apps.
23
+ **"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <org_context> - it should not be used for public-facing apps.
24
24
 
25
25
  **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.
26
26
 
@@ -69,12 +69,6 @@ For app icons and logos, the goal is something that reads clearly at phone home
69
69
  - You must specify that the image is full bleed - never say anything about rounded corners or there is a high likelihood that the image will come back as a rounded rectangle on a white background!
70
70
  - Apply the same material/lighting/color density as photography prompts, just to a single object. Describe the surface finish ("high-gloss lacquered finish with clean specular highlights," "soft matte ceramic with subtle surface texture"), the lighting behavior ("warm directional light from upper left producing a bright highlight streak across the curved surface and a soft shadow beneath"), and color as relationships ("deep coral body graduating to warm peach at the highlight edge, with a cream accent on the lens element"). Generic descriptors like "clean surfaces, soft lighting" produce generic icons.
71
71
 
72
- #### Open Graph Sharing Images
73
-
74
- OG images are often a user's first impression of the app — they show up in iMessage, Slack, Twitter, etc. at small sizes. Keep text minimal: the app name and at most a short tagline (three to five words). This is a mood piece, not a messaging opportunity. Think App Store feature card — one beautiful composition that makes someone want to tap.
75
-
76
- Apply the same material/lighting/color density as photography prompts. The text should feel integrated into the scene — typeset within the composition, not pasted on top. Describe the typography treatment (weight, size, color, position) as part of the overall image, and describe how the background interacts with the text (glow, depth, contrast). The whole image should read as one cohesive graphic, not layers.
77
-
78
72
  ## Output
79
73
 
80
74
  Respond with ONLY the enhanced prompt. Be detailed and specific — a good prompt is a dense paragraph of 80-150 words that paints a complete picture: style, subject, materials, lighting behavior, color relationships, atmosphere, and composition. Terse prompts produce generic images.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.243",
3
+ "version": "0.1.245",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",