Unverified 提交 22f25ef5 authored 作者: Mohamed Aziz Mejri's avatar Mohamed Aziz Mejri 提交者: GitHub

Initial ui theming (#2145)

<!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Introduces initial UI theming with per-app theme selection and a default theme in settings. Theme rules are added to prompts so generated UIs follow the chosen design. - **New Features** - Theme picker in AuxiliaryActionsMenu with app-specific selection and visual check. - New hooks: useThemes and useAppTheme (React Query) with IPC get/set handlers. - Themes data and prompts added (includes “No Theme” and “Default Theme”). - Theme prompt appended to system and local-agent prompts; included in token counting. - Settings now support a default theme (selectedThemeId) applied to new apps. - **Migration** - Adds apps.theme_id (NULL means no theme). <sup>Written for commit f4ef96ccd02a3d9148bd4e570d2204c7b5a12c10. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Introduces initial theming with persistence and prompt influence. > > - UI: Adds Themes submenu in `AuxiliaryActionsMenu` (supports "No Theme" and `default`, app-specific or global via settings) > - Data/IPC: New `apps.theme_id` column (nullable), hooks `useThemes`/`useAppTheme`, IPC handlers (`get-themes`, `set-app-theme`, `get-app-theme`) wired through `ipc_client`, `ipc_host`, and `preload` > - Settings: Adds `selectedThemeId` with default applied to newly created apps > - Prompting: Appends theme prompt (`getThemePrompt`) to system/local-agent prompts and token counting > - Integration: `ChatInput` passes `appId` to menu; `schema.ts` updated > - Tests: E2E verifies default and per-app theme persistence > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ee9ba34aad48f8dc49013e01247cfdcff1b77fad. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
上级 3b66d4de
ALTER TABLE `apps` ADD `theme_id` text;
\ No newline at end of file
差异被折叠。
......@@ -148,6 +148,13 @@
"when": 1766619976318,
"tag": "0020_nebulous_patch",
"breakpoints": true
},
{
"idx": 21,
"version": "6",
"when": 1768167214574,
"tag": "0021_kind_luckman",
"breakpoints": true
}
]
}
\ No newline at end of file
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......@@ -1030,46 +1082,6 @@ export default defineConfig(() => ({
role: assistant
message: OK, got it. I'm ready to help
===
role: user
message: tc=1
===
role: assistant
message: 1
===
role: user
message: tc=2
===
role: assistant
message: 2
===
role: user
message: [dump] tc=3
===
role: assistant
message: [[dyad-dump-path=*]]
===
role: user
message: [dump] tc=4
===
role: assistant
message: [[dyad-dump-path=*]]
===
role: user
message: [dump] tc=5
===
role: assistant
message: [[dyad-dump-path=*]]
===
role: user
message: [dump] tc=6
\ No newline at end of file
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -26,6 +26,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
# Referenced Apps
The user has mentioned the following apps in their prompt: minimal-with-ai-rules. Their codebases have been included in the context for your reference. When referring to these apps, you can understand their structure and code to provide better assistance, however you should NOT edit the files in these referenced apps. The referenced apps are NOT part of the current app and are READ-ONLY.
......
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -27,6 +27,58 @@ Available packages and libraries:
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
......@@ -81,6 +81,58 @@ By following these guidelines, we can build a more robust, maintainable, and con
${BUILD_SYSTEM_POSTFIX}
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
=== src/pages/Index.tsx ===
// Update this page (the content is just a fallback if you fail to update the page)
import { MadeWithDyad } from "@/components/made-with-dyad";
const Index = () => {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<div className="text-center">
<h1 className="text-4xl font-bold mb-4">Welcome to the UPDATED App</h1>
<p className="text-xl text-gray-600">
Start building your amazing project here!
</p>
</div>
<MadeWithDyad />
</div>
);
};
export default Index;
// FILE IS REPLACED WITH FALLBACK WRITE.
\ No newline at end of file
......@@ -114,6 +114,58 @@ def calculate_sum(items):
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>
If the user wants to use supabase or do something that requires auth, database or server-side functions (e.g. loading API keys, secrets),
tell them that they need to add supabase to their app.
......
import { test } from "./helpers/test_helper";
import { expect } from "@playwright/test";
test("theme selection - dyad-wide default theme is persisted", async ({
po,
}) => {
await po.setUp();
// Verify initial settings state
const initialSettings = po.recordSettings();
expect(initialSettings.selectedThemeId).toBe("default");
// Open menu and select "No Theme"
await po
.getHomeChatInputContainer()
.getByTestId("auxiliary-actions-menu")
.click();
await po.page.getByRole("menuitem", { name: "Themes" }).hover();
await expect(po.page.getByTestId("theme-option-default")).toBeVisible();
await po.page.getByTestId("theme-option-none").click();
await expect(po.page.getByTestId("theme-option-none")).not.toBeVisible();
// Verify settings file was updated
expect(po.recordSettings().selectedThemeId).toBe("");
// Re-open and verify UI shows "No Theme" selected, then select "Default Theme" back
await po
.getHomeChatInputContainer()
.getByTestId("auxiliary-actions-menu")
.click();
await po.page.getByRole("menuitem", { name: "Themes" }).hover();
await expect(po.page.getByTestId("theme-option-none")).toHaveClass(
/bg-primary/,
);
await po.page.getByTestId("theme-option-default").click();
await expect(po.page.getByTestId("theme-option-default")).not.toBeVisible();
// Verify settings file was updated back to default
expect(po.recordSettings().selectedThemeId).toBe("default");
});
test("theme selection - app-specific theme is persisted", async ({ po }) => {
await po.setUp({ autoApprove: true });
await po.importApp("minimal");
// Open menu and select "Default Theme" for this app
await po
.getChatInputContainer()
.getByTestId("auxiliary-actions-menu")
.click();
await po.page.getByRole("menuitem", { name: "Themes" }).hover();
await expect(po.page.getByTestId("theme-option-none")).toBeVisible();
await po.page.getByTestId("theme-option-default").click();
await expect(po.page.getByTestId("theme-option-default")).not.toBeVisible();
// Re-open, verify selection, then switch to "No Theme"
await po
.getChatInputContainer()
.getByTestId("auxiliary-actions-menu")
.click();
await po.page.getByRole("menuitem", { name: "Themes" }).hover();
await expect(po.page.getByTestId("theme-option-default")).toHaveClass(
/bg-primary/,
);
await po.page.getByTestId("theme-option-none").click();
await expect(po.page.getByTestId("theme-option-none")).not.toBeVisible();
// Re-open and verify "No Theme" is selected
await po
.getChatInputContainer()
.getByTestId("auxiliary-actions-menu")
.click();
await po.page.getByRole("menuitem", { name: "Themes" }).hover();
await expect(po.page.getByTestId("theme-option-none")).toHaveClass(
/bg-primary/,
);
});
......@@ -70,6 +70,7 @@ describe("readSettings", () => {
"provider": "auto",
},
"selectedTemplateId": "react",
"selectedThemeId": "default",
"telemetryConsent": "unset",
"telemetryUserId": "[scrubbed]",
}
......@@ -319,6 +320,7 @@ describe("readSettings", () => {
"provider": "auto",
},
"selectedTemplateId": "react",
"selectedThemeId": "default",
"telemetryConsent": "unset",
"telemetryUserId": "[scrubbed]",
}
......
import { useState } from "react";
import { Plus, Paperclip, ChartColumnIncreasing } from "lucide-react";
import {
Plus,
Paperclip,
ChartColumnIncreasing,
Palette,
Check,
Ban,
} from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
......@@ -10,9 +17,19 @@ import {
DropdownMenuSeparator,
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Button } from "@/components/ui/button";
import { ContextFilesPicker } from "@/components/ContextFilesPicker";
import { FileAttachmentDropdown } from "./FileAttachmentDropdown";
import { useThemes } from "@/hooks/useThemes";
import { useAppTheme, APP_THEME_QUERY_KEY } from "@/hooks/useAppTheme";
import { useSettings } from "@/hooks/useSettings";
import { IpcClient } from "@/ipc/ipc_client";
import { useQueryClient } from "@tanstack/react-query";
interface AuxiliaryActionsMenuProps {
onFileSelect: (
......@@ -22,6 +39,7 @@ interface AuxiliaryActionsMenuProps {
showTokenBar?: boolean;
toggleShowTokenBar?: () => void;
hideContextFilesPicker?: boolean;
appId?: number;
}
export function AuxiliaryActionsMenu({
......@@ -29,8 +47,34 @@ export function AuxiliaryActionsMenu({
showTokenBar,
toggleShowTokenBar,
hideContextFilesPicker,
appId,
}: AuxiliaryActionsMenuProps) {
const [isOpen, setIsOpen] = useState(false);
const { themes } = useThemes();
const { themeId: appThemeId } = useAppTheme(appId);
const { settings, updateSettings } = useSettings();
const queryClient = useQueryClient();
// Determine current theme: use app theme if appId exists, otherwise use settings
// Note: settings stores empty string for "no theme", convert to null
const currentThemeId =
appId != null ? appThemeId : settings?.selectedThemeId || null;
const handleThemeSelect = async (themeId: string | null) => {
if (appId) {
// Update app-specific theme
await IpcClient.getInstance().setAppTheme({
appId,
themeId,
});
// Invalidate app theme query to refresh
queryClient.invalidateQueries({ queryKey: APP_THEME_QUERY_KEY(appId) });
} else {
// Update default theme in settings (for new apps)
// Store as string for settings (empty string for no theme)
await updateSettings({ selectedThemeId: themeId ?? "" });
}
};
return (
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
......@@ -65,7 +109,62 @@ export function AuxiliaryActionsMenu({
</DropdownMenuSubContent>
</DropdownMenuSub>
{/* Toggle Token Usage */}
{/* Themes Submenu */}
<DropdownMenuSub>
<DropdownMenuSubTrigger className="py-2 px-3">
<Palette size={16} className="mr-2" />
Themes
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
{/* No Theme option (special frontend-only option) */}
<DropdownMenuItem
onClick={() => handleThemeSelect(null)}
className={`py-2 px-3 ${currentThemeId === null ? "bg-primary/10" : ""}`}
data-testid="theme-option-none"
>
<div className="flex items-center w-full">
<Ban size={16} className="mr-2 text-muted-foreground" />
<span className="flex-1">No Theme</span>
{currentThemeId === null && (
<Check size={16} className="text-primary ml-2" />
)}
</div>
</DropdownMenuItem>
{/* Actual themes from themesData */}
{themes?.map((theme) => {
const isSelected = currentThemeId === theme.id;
return (
<Tooltip key={theme.id}>
<TooltipTrigger asChild>
<DropdownMenuItem
onClick={() => handleThemeSelect(theme.id)}
className={`py-2 px-3 ${isSelected ? "bg-primary/10" : ""}`}
data-testid={`theme-option-${theme.id}`}
>
<div className="flex items-center w-full">
{theme.icon === "palette" && (
<Palette
size={16}
className="mr-2 text-muted-foreground"
/>
)}
<span className="flex-1">{theme.name}</span>
{isSelected && (
<Check size={16} className="text-primary ml-2" />
)}
</div>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="right">
{theme.description}
</TooltipContent>
</Tooltip>
);
})}
</DropdownMenuSubContent>
</DropdownMenuSub>
{toggleShowTokenBar && (
<>
<DropdownMenuSeparator />
......
......@@ -486,6 +486,7 @@ export function ChatInput({ chatId }: { chatId?: number }) {
onFileSelect={handleFileSelect}
showTokenBar={showTokenBar}
toggleShowTokenBar={toggleShowTokenBar}
appId={appId ?? undefined}
/>
</div>
{/* TokenBar is only displayed when showTokenBar is true */}
......
......@@ -58,6 +58,8 @@ export const apps = sqliteTable("apps", {
isFavorite: integer("is_favorite", { mode: "boolean" })
.notNull()
.default(sql`0`),
// Theme ID for design system theming (null means "no theme")
themeId: text("theme_id"),
});
export const chats = sqliteTable("chats", {
......
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { IpcClient } from "@/ipc/ipc_client";
export const APP_THEME_QUERY_KEY = (appId: number | undefined) => [
"app-theme",
appId,
];
export function useAppTheme(appId: number | undefined) {
const queryClient = useQueryClient();
const query = useQuery({
queryKey: APP_THEME_QUERY_KEY(appId),
queryFn: async (): Promise<string | null> => {
return IpcClient.getInstance().getAppTheme({ appId: appId! });
},
enabled: !!appId,
});
const invalidate = () => {
queryClient.invalidateQueries({ queryKey: APP_THEME_QUERY_KEY(appId) });
};
return {
themeId: query.data ?? null,
isLoading: query.isLoading,
error: query.error,
invalidate,
};
}
import { useQuery } from "@tanstack/react-query";
import { IpcClient } from "@/ipc/ipc_client";
import { themesData, type Theme } from "@/shared/themes";
export function useThemes() {
const query = useQuery({
queryKey: ["themes"],
queryFn: async (): Promise<Theme[]> => {
const ipcClient = IpcClient.getInstance();
return ipcClient.getThemes();
},
placeholderData: themesData,
meta: {
showErrorToast: true,
},
});
return {
themes: query.data,
isLoading: query.isLoading,
error: query.error,
refetch: query.refetch,
};
}
......@@ -20,6 +20,7 @@ import {
constructSystemPrompt,
readAiRules,
} from "../../prompts/system_prompt";
import { getThemePrompt } from "../../shared/themes";
import {
SUPABASE_AVAILABLE_SYSTEM_PROMPT,
SUPABASE_NOT_AVAILABLE_SYSTEM_PROMPT,
......@@ -609,6 +610,12 @@ ${componentSnippet}
const aiRules = await readAiRules(getDyadAppPath(updatedChat.app.path));
// Get theme prompt for the app (null themeId means "no theme")
const themePrompt = getThemePrompt(updatedChat.app.themeId);
logger.log(
`Theme for app ${updatedChat.app.id}: ${updatedChat.app.themeId ?? "none"}, prompt length: ${themePrompt.length} chars`,
);
let systemPrompt = constructSystemPrompt({
aiRules,
chatMode:
......@@ -616,6 +623,7 @@ ${componentSnippet}
? "build"
: settings.selectedChatMode,
enableTurboEditsV2: isTurboEditsV2Enabled(settings),
themePrompt,
});
// Add information about mentioned apps if any
......
import { createLoggedHandler } from "./safe_handle";
import log from "electron-log";
import { themesData, type Theme } from "../../shared/themes";
import { db } from "../../db";
import { apps } from "../../db/schema";
import { eq, sql } from "drizzle-orm";
import type { SetAppThemeParams, GetAppThemeParams } from "../ipc_types";
const logger = log.scope("themes_handlers");
const handle = createLoggedHandler(logger);
export function registerThemesHandlers() {
handle("get-themes", async (): Promise<Theme[]> => {
return themesData;
});
handle(
"set-app-theme",
async (_, params: SetAppThemeParams): Promise<void> => {
const { appId, themeId } = params;
// Use raw SQL to properly set NULL when themeId is null (representing "no theme")
if (!themeId) {
await db
.update(apps)
.set({ themeId: sql`NULL` })
.where(eq(apps.id, appId));
} else {
await db.update(apps).set({ themeId }).where(eq(apps.id, appId));
}
},
);
handle(
"get-app-theme",
async (_, params: GetAppThemeParams): Promise<string | null> => {
const app = await db.query.apps.findFirst({
where: eq(apps.id, params.appId),
columns: { themeId: true },
});
return app?.themeId ?? null;
},
);
}
......@@ -5,6 +5,7 @@ import {
constructSystemPrompt,
readAiRules,
} from "../../prompts/system_prompt";
import { getThemePrompt } from "../../shared/themes";
import {
SUPABASE_AVAILABLE_SYSTEM_PROMPT,
SUPABASE_NOT_AVAILABLE_SYSTEM_PROMPT,
......@@ -61,6 +62,7 @@ export function registerTokenCountHandlers() {
const mentionedAppNames = parseAppMentions(req.input);
// Count system prompt tokens
const themePrompt = getThemePrompt(chat.app?.themeId ?? null);
let systemPrompt = constructSystemPrompt({
aiRules: await readAiRules(getDyadAppPath(chat.app.path)),
chatMode:
......@@ -69,6 +71,7 @@ export function registerTokenCountHandlers() {
? "build"
: settings.selectedChatMode,
enableTurboEditsV2: isTurboEditsV2Enabled(settings),
themePrompt,
});
let supabaseContext = "";
......
......@@ -86,8 +86,11 @@ import type {
TelemetryEventPayload,
GithubSyncOptions,
ConsoleEntry,
SetAppThemeParams,
GetAppThemeParams,
} from "./ipc_types";
import type { Template } from "../shared/templates";
import type { Theme } from "../shared/themes";
import type {
AppChatContext,
AppSearchResult,
......@@ -1614,6 +1617,19 @@ export class IpcClient {
return this.ipcRenderer.invoke("get-templates");
}
// --- Themes ---
public async getThemes(): Promise<Theme[]> {
return this.ipcRenderer.invoke("get-themes");
}
public async setAppTheme(params: SetAppThemeParams): Promise<void> {
await this.ipcRenderer.invoke("set-app-theme", params);
}
public async getAppTheme(params: GetAppThemeParams): Promise<string | null> {
return this.ipcRenderer.invoke("get-app-theme", params);
}
// --- Prompts Library ---
public async listPrompts(): Promise<PromptDto[]> {
return this.ipcRenderer.invoke("prompts:list");
......
......@@ -28,6 +28,7 @@ import { registerCapacitorHandlers } from "./handlers/capacitor_handlers";
import { registerProblemsHandlers } from "./handlers/problems_handlers";
import { registerAppEnvVarsHandlers } from "./handlers/app_env_vars_handlers";
import { registerTemplateHandlers } from "./handlers/template_handlers";
import { registerThemesHandlers } from "./handlers/themes_handlers";
import { registerPortalHandlers } from "./handlers/portal_handlers";
import { registerPromptHandlers } from "./handlers/prompt_handlers";
import { registerHelpBotHandlers } from "./handlers/help_bot_handlers";
......@@ -68,6 +69,7 @@ export function registerIpcHandlers() {
registerCapacitorHandlers();
registerAppEnvVarsHandlers();
registerTemplateHandlers();
registerThemesHandlers();
registerPortalHandlers();
registerPromptHandlers();
registerHelpBotHandlers();
......
......@@ -735,3 +735,13 @@ export interface TelemetryEventPayload {
eventName: string;
properties?: Record<string, unknown>;
}
// --- Theme Types ---
export interface SetAppThemeParams {
appId: number;
themeId: string | null;
}
export interface GetAppThemeParams {
appId: number;
}
......@@ -287,6 +287,7 @@ export const UserSettingsSchema = z.object({
enableProWebSearch: z.boolean().optional(),
proSmartContextOption: SmartContextModeSchema.optional(),
selectedTemplateId: z.string(),
selectedThemeId: z.string().optional(),
enableSupabaseWriteSqlMigration: z.boolean().optional(),
selectedChatMode: ChatModeSchema.optional(),
acceptedCommunityCode: z.boolean().optional(),
......
......@@ -11,6 +11,7 @@ import { safeStorage } from "electron";
import { v4 as uuidv4 } from "uuid";
import log from "electron-log";
import { DEFAULT_TEMPLATE_ID } from "@/shared/templates";
import { DEFAULT_THEME_ID } from "@/shared/themes";
import { IS_TEST_BUILD } from "@/ipc/utils/test_utils";
const logger = log.scope("settings");
......@@ -34,6 +35,7 @@ const DEFAULT_SETTINGS: UserSettings = {
enableAutoUpdate: true,
releaseChannel: "stable",
selectedTemplateId: DEFAULT_TEMPLATE_ID,
selectedThemeId: DEFAULT_THEME_ID,
isRunning: false,
lastKnownPerformance: undefined,
// Enabled by default in 0.33.0-beta.1
......
......@@ -160,6 +160,14 @@ export default function HomePage() {
});
}
// Apply selected theme to the new app (if one is set)
if (settings?.selectedThemeId) {
await IpcClient.getInstance().setAppTheme({
appId: result.app.id,
themeId: settings.selectedThemeId || null,
});
}
// Stream the message with attachments
streamMessage({
prompt: inputValue,
......
......@@ -167,6 +167,10 @@ const validInvokeChannels = [
// Console logs
"add-log",
"clear-logs",
// Themes
"get-themes",
"set-app-theme",
"get-app-theme",
// Test-only channels
// These should ALWAYS be guarded with IS_TEST_BUILD in the main process.
// We can't detect with IS_TEST_BUILD in the preload script because
......
......@@ -87,9 +87,19 @@ Available packages and libraries:
- Use prebuilt components from the shadcn/ui library after importing them. Note that these files shouldn't be edited, so make new components if you need to change them.
`;
export function constructLocalAgentPrompt(aiRules: string | undefined): string {
return LOCAL_AGENT_SYSTEM_PROMPT.replace(
export function constructLocalAgentPrompt(
aiRules: string | undefined,
themePrompt?: string,
): string {
let prompt = LOCAL_AGENT_SYSTEM_PROMPT.replace(
"[[AI_RULES]]",
aiRules ?? DEFAULT_AI_RULES,
);
// Append theme prompt if provided
if (themePrompt) {
prompt += "\n\n" + themePrompt;
}
return prompt;
}
......@@ -508,20 +508,32 @@ export const constructSystemPrompt = ({
aiRules,
chatMode = "build",
enableTurboEditsV2,
themePrompt,
}: {
aiRules: string | undefined;
chatMode?: "build" | "ask" | "agent" | "local-agent";
enableTurboEditsV2: boolean;
themePrompt?: string;
}) => {
if (chatMode === "local-agent") {
return constructLocalAgentPrompt(aiRules);
return constructLocalAgentPrompt(aiRules, themePrompt);
}
const systemPrompt = getSystemPromptForChatMode({
let systemPrompt = getSystemPromptForChatMode({
chatMode,
enableTurboEditsV2,
});
return systemPrompt.replace("[[AI_RULES]]", aiRules ?? DEFAULT_AI_RULES);
systemPrompt = systemPrompt.replace(
"[[AI_RULES]]",
aiRules ?? DEFAULT_AI_RULES,
);
// Append theme prompt if provided
if (themePrompt) {
systemPrompt += "\n\n" + themePrompt;
}
return systemPrompt;
};
export const getSystemPromptForChatMode = ({
......
export interface Theme {
id: string;
name: string;
description: string;
icon: string;
prompt: string;
}
export const DEFAULT_THEME_ID = "default";
const DEFAULT_THEME_PROMPT = `
<theme>
Any instruction in this theme should override other instructions if there's a contradiction.
### Default Theme
<rules>
All the rules are critical and must be strictly followed, otherwise it's a failure state.
#### Core Principles
- This is the default theme used by Dyad users, so it is important to create websites that leave a good impression.
- AESTHETICS ARE VERY IMPORTANT. All web apps should LOOK AMAZING and have GREAT FUNCTIONALITY!
- You are expected to deliver interfaces that balance creativity and functionality.
#### Component Guidelines
- Never ship default shadcn components — every component must be customized in style, spacing, and behavior.
- Always prefer rounded shapes.
#### Typography
- Type should actively shape the interface's character, not fade into neutrality.
#### Color System
- Establish a clear and confident color system.
- Centralize colors through variables to maintain consistency.
- Avoid using gradient backgrounds.
- Avoid using black as the primary color. Aim for colorful websites.
#### Motion & Interaction
- Apply motion with restraint and purpose.
- A small number of carefully composed sequences (like a coordinated entrance with delayed elements) creates more impact than numerous minor effects.
- Motion should clarify structure and intent, not act as decoration.
#### Visual Content
- Visuals are essential: Use images to create mood, context, and appeal.
- Don't build text-only walls.
#### Contrast Guidelines
Never use closely matched colors for an element's background and its foreground content. Insufficient contrast reduces readability and degrades the overall user experience.
**Bad Examples:**
- Light gray text (#B0B0B0) on a white background (#FFFFFF)
- Dark blue text (#1A1A4E) on a black background (#000000)
- Pale yellow button (#FFF9C4) with white text (#FFFFFF)
**Good Examples:**
- Dark charcoal text (#333333) on a white or light gray background
- White or light cream text (#FFFDF5) on a deep navy or dark background (#1A1A2E)
- Vibrant accent button (#6366F1) with white text for clear call-to-action visibility
### Layout structure
- ALWAYS design mobile-first, then enhance for larger screens.
</rules>
<workflow>
Follow this workflow when building web apps:
1. **Determine Design Direction**
- Analyze the industry and target users of the website.
- Define colors, fonts, mood, and visual style.
- Ensure the design direction does NOT contradict the rules defined for this theme.
2. **Build the Application**
- Do not neglect functionality in the pursuit of making a beautiful website.
- You must achieve both great aesthetics AND great functionality.
</workflow>
</theme>`;
export const themesData: Theme[] = [
{
id: "default",
name: "Default Theme",
description:
"Balanced design system emphasizing aesthetics, contrast, and functionality.",
icon: "palette",
prompt: DEFAULT_THEME_PROMPT,
},
];
export function getThemeById(themeId: string | null): Theme | null {
// null means "no theme" - return null
if (!themeId) {
return null;
}
return themesData.find((t) => t.id === themeId) ?? null;
}
export function getThemePrompt(themeId: string | null): string {
// null means "no theme" - return empty string (no prompt)
if (!themeId) {
return "";
}
const theme = getThemeById(themeId);
return theme?.prompt ?? "";
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论