This uses Gemini's native [thinking summaries](https://cloud.google.com/vertex-ai/generative-ai/docs/thinking#thought-summaries) which were recently added to the API. Why? The grafted thinking would sometimes cause weird issues where the model, especially Gemini 2.5 Flash, got confused and put dyad tags like `<dyad-write>` inside the `<think>` tags. This also improves the UX because you can see the native thoughts rather than having the Gemini response load for a while without any feedback. I tried adding Anthropic extended thinking, however it requires temp to be set at 1, which isn't ideal for Dyad's use case where we need precise syntax following.
372 lines
28 KiB
Plaintext
372 lines
28 KiB
Plaintext
{
|
|
"body": {
|
|
"model": "gpt-4.1",
|
|
"max_tokens": 32768,
|
|
"temperature": 0,
|
|
"messages": [
|
|
{
|
|
"role": "system",
|
|
"content": "[[SYSTEM_MESSAGE]]"
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": "[dump] tc=turbo-edits"
|
|
}
|
|
],
|
|
"stream": true,
|
|
"dyad_options": {
|
|
"files": [
|
|
{
|
|
"path": "AI_RULES.md",
|
|
"content": "# Tech Stack\n\n- You are building a React application.\n- Use TypeScript.\n- Use React Router. KEEP the routes in src/App.tsx\n- Always put source code in the src folder.\n- Put pages into src/pages/\n- Put components into src/components/\n- The main page (default page) is src/pages/Index.tsx\n- UPDATE the main page to include the new components. OTHERWISE, the user can NOT see any components!\n- ALWAYS try to use the shadcn/ui library.\n- Tailwind CSS: always use Tailwind CSS for styling components. Utilize Tailwind classes extensively for layout, spacing, colors, and other design aspects.\n\nAvailable packages and libraries:\n\n- The lucide-react package is installed for icons.\n- You ALREADY have ALL the shadcn/ui components and their dependencies installed. So you don't need to install them again.\n- You have ALL the necessary Radix UI components installed.\n- 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.\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "eslint.config.js",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "index.html",
|
|
"content": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>dyad-generated-app</title>\n </head>\n\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "package.json",
|
|
"content": "{\n \"dependencies\": {\n \"@hookform/resolvers\": \"^3.9.0\",\n \"@radix-ui/react-accordion\": \"^1.2.0\",\n \"@radix-ui/react-alert-dialog\": \"^1.1.1\",\n \"@radix-ui/react-aspect-ratio\": \"^1.1.0\",\n \"@radix-ui/react-avatar\": \"^1.1.0\",\n \"@radix-ui/react-checkbox\": \"^1.1.1\",\n \"@radix-ui/react-collapsible\": \"^1.1.0\",\n \"@radix-ui/react-context-menu\": \"^2.2.1\",\n \"@radix-ui/react-dialog\": \"^1.1.2\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.1\",\n \"@radix-ui/react-hover-card\": \"^1.1.1\",\n \"@radix-ui/react-label\": \"^2.1.0\",\n \"@radix-ui/react-menubar\": \"^1.1.1\",\n \"@radix-ui/react-navigation-menu\": \"^1.2.0\",\n \"@radix-ui/react-popover\": \"^1.1.1\",\n \"@radix-ui/react-progress\": \"^1.1.0\",\n \"@radix-ui/react-radio-group\": \"^1.2.0\",\n \"@radix-ui/react-scroll-area\": \"^1.1.0\",\n \"@radix-ui/react-select\": \"^2.1.1\",\n \"@radix-ui/react-separator\": \"^1.1.0\",\n \"@radix-ui/react-slider\": \"^1.2.0\",\n \"@radix-ui/react-slot\": \"^1.1.0\",\n \"@radix-ui/react-switch\": \"^1.1.0\",\n \"@radix-ui/react-tabs\": \"^1.1.0\",\n \"@radix-ui/react-toast\": \"^1.2.1\",\n \"@radix-ui/react-toggle\": \"^1.1.0\",\n \"@radix-ui/react-toggle-group\": \"^1.1.0\",\n \"@radix-ui/react-tooltip\": \"^1.1.4\",\n \"@tanstack/react-query\": \"^5.56.2\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cmdk\": \"^1.0.0\",\n \"date-fns\": \"^3.6.0\",\n \"embla-carousel-react\": \"^8.3.0\",\n \"input-otp\": \"^1.2.4\",\n \"lucide-react\": \"^0.462.0\",\n \"next-themes\": \"^0.3.0\",\n \"react\": \"^18.3.1\",\n \"react-day-picker\": \"^8.10.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-hook-form\": \"^7.53.0\",\n \"react-resizable-panels\": \"^2.1.3\",\n \"react-router-dom\": \"^6.26.2\",\n \"recharts\": \"^2.12.7\",\n \"sonner\": \"^1.5.0\",\n \"tailwind-merge\": \"^2.5.2\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"vaul\": \"^0.9.3\",\n \"zod\": \"^3.23.8\"\n },\n \"devDependencies\": {\n \"@dyad-sh/react-vite-component-tagger\": \"^0.8.0\",\n \"@eslint/js\": \"^9.9.0\",\n \"@tailwindcss/typography\": \"^0.5.15\",\n \"@types/node\": \"^22.5.5\",\n \"@types/react\": \"^18.3.3\",\n \"@types/react-dom\": \"^18.3.0\",\n \"@vitejs/plugin-react-swc\": \"^3.9.0\",\n \"autoprefixer\": \"^10.4.20\",\n \"eslint\": \"^9.9.0\",\n \"eslint-plugin-react-hooks\": \"^5.1.0-rc.0\",\n \"eslint-plugin-react-refresh\": \"^0.4.9\",\n \"globals\": \"^15.9.0\",\n \"postcss\": \"^8.4.47\",\n \"tailwindcss\": \"^3.4.11\",\n \"typescript\": \"^5.5.3\",\n \"typescript-eslint\": \"^8.0.1\",\n \"vite\": \"^6.3.4\"\n }\n}",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "postcss.config.js",
|
|
"content": "export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n};\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "README.md",
|
|
"content": "# Welcome to your Dyad app\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/App.css",
|
|
"content": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/App.tsx",
|
|
"content": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/made-with-dyad.tsx",
|
|
"content": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/accordion.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/alert-dialog.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/alert.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/aspect-ratio.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/avatar.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/badge.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/breadcrumb.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/button.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/calendar.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/card.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/carousel.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/chart.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/checkbox.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/collapsible.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/command.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/context-menu.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/dialog.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/drawer.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/dropdown-menu.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/form.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/hover-card.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/input-otp.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/input.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/label.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/menubar.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/navigation-menu.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/pagination.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/popover.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/progress.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/radio-group.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/resizable.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/scroll-area.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/select.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/separator.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/sheet.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/sidebar.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/skeleton.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/slider.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/sonner.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/switch.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/table.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/tabs.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/textarea.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/toast.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/toaster.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/toggle-group.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/toggle.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/tooltip.tsx",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/components/ui/use-toast.ts",
|
|
"content": "// Contents omitted for brevity",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/globals.css",
|
|
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n\n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n\n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n\n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n\n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n\n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n\n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n\n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n --ring: 222.2 84% 4.9%;\n\n --radius: 0.5rem;\n\n --sidebar-background: 0 0% 98%;\n\n --sidebar-foreground: 240 5.3% 26.1%;\n\n --sidebar-primary: 240 5.9% 10%;\n\n --sidebar-primary-foreground: 0 0% 98%;\n\n --sidebar-accent: 240 4.8% 95.9%;\n\n --sidebar-accent-foreground: 240 5.9% 10%;\n\n --sidebar-border: 220 13% 91%;\n\n --sidebar-ring: 217.2 91.2% 59.8%;\n }\n\n .dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n\n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n\n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n\n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n\n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n\n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n\n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 40% 98%;\n\n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n --ring: 212.7 26.8% 83.9%;\n --sidebar-background: 240 5.9% 10%;\n --sidebar-foreground: 240 4.8% 95.9%;\n --sidebar-primary: 224.3 76.3% 48%;\n --sidebar-primary-foreground: 0 0% 100%;\n --sidebar-accent: 240 3.7% 15.9%;\n --sidebar-accent-foreground: 240 4.8% 95.9%;\n --sidebar-border: 240 3.7% 15.9%;\n --sidebar-ring: 217.2 91.2% 59.8%;\n }\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n\n body {\n @apply bg-background text-foreground;\n }\n}\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/hooks/use-mobile.tsx",
|
|
"content": "import * as React from \"react\";\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(\n undefined,\n );\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n mql.addEventListener(\"change\", onChange);\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n return () => mql.removeEventListener(\"change\", onChange);\n }, []);\n\n return !!isMobile;\n}\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/hooks/use-toast.ts",
|
|
"content": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/lib/utils.ts",
|
|
"content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/main.tsx",
|
|
"content": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/pages/Index.tsx",
|
|
"content": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/pages/NotFound.tsx",
|
|
"content": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/utils/toast.ts",
|
|
"content": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "src/vite-env.d.ts",
|
|
"content": "/// <reference types=\"vite/client\" />\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "tailwind.config.ts",
|
|
"content": "import type { Config } from \"tailwindcss\";\n\nexport default {\n darkMode: [\"class\"],\n content: [\n \"./pages/**/*.{ts,tsx}\",\n \"./components/**/*.{ts,tsx}\",\n \"./app/**/*.{ts,tsx}\",\n \"./src/**/*.{ts,tsx}\",\n ],\n prefix: \"\",\n theme: {\n container: {\n center: true,\n padding: \"2rem\",\n screens: {\n \"2xl\": \"1400px\",\n },\n },\n extend: {\n colors: {\n border: \"hsl(var(--border))\",\n input: \"hsl(var(--input))\",\n ring: \"hsl(var(--ring))\",\n background: \"hsl(var(--background))\",\n foreground: \"hsl(var(--foreground))\",\n primary: {\n DEFAULT: \"hsl(var(--primary))\",\n foreground: \"hsl(var(--primary-foreground))\",\n },\n secondary: {\n DEFAULT: \"hsl(var(--secondary))\",\n foreground: \"hsl(var(--secondary-foreground))\",\n },\n destructive: {\n DEFAULT: \"hsl(var(--destructive))\",\n foreground: \"hsl(var(--destructive-foreground))\",\n },\n muted: {\n DEFAULT: \"hsl(var(--muted))\",\n foreground: \"hsl(var(--muted-foreground))\",\n },\n accent: {\n DEFAULT: \"hsl(var(--accent))\",\n foreground: \"hsl(var(--accent-foreground))\",\n },\n popover: {\n DEFAULT: \"hsl(var(--popover))\",\n foreground: \"hsl(var(--popover-foreground))\",\n },\n card: {\n DEFAULT: \"hsl(var(--card))\",\n foreground: \"hsl(var(--card-foreground))\",\n },\n sidebar: {\n DEFAULT: \"hsl(var(--sidebar-background))\",\n foreground: \"hsl(var(--sidebar-foreground))\",\n primary: \"hsl(var(--sidebar-primary))\",\n \"primary-foreground\": \"hsl(var(--sidebar-primary-foreground))\",\n accent: \"hsl(var(--sidebar-accent))\",\n \"accent-foreground\": \"hsl(var(--sidebar-accent-foreground))\",\n border: \"hsl(var(--sidebar-border))\",\n ring: \"hsl(var(--sidebar-ring))\",\n },\n },\n borderRadius: {\n lg: \"var(--radius)\",\n md: \"calc(var(--radius) - 2px)\",\n sm: \"calc(var(--radius) - 4px)\",\n },\n keyframes: {\n \"accordion-down\": {\n from: {\n height: \"0\",\n },\n to: {\n height: \"var(--radix-accordion-content-height)\",\n },\n },\n \"accordion-up\": {\n from: {\n height: \"var(--radix-accordion-content-height)\",\n },\n to: {\n height: \"0\",\n },\n },\n },\n animation: {\n \"accordion-down\": \"accordion-down 0.2s ease-out\",\n \"accordion-up\": \"accordion-up 0.2s ease-out\",\n },\n },\n },\n plugins: [require(\"tailwindcss-animate\")],\n} satisfies Config;\n",
|
|
"force": false
|
|
},
|
|
{
|
|
"path": "vite.config.ts",
|
|
"content": "import { defineConfig } from \"vite\";\nimport dyadComponentTagger from \"@dyad-sh/react-vite-component-tagger\";\nimport react from \"@vitejs/plugin-react-swc\";\nimport path from \"path\";\n\nexport default defineConfig(() => ({\n server: {\n host: \"::\",\n port: 8080,\n },\n plugins: [dyadComponentTagger(), react()],\n resolve: {\n alias: {\n \"@\": path.resolve(__dirname, \"./src\"),\n },\n },\n}));\n",
|
|
"force": false
|
|
}
|
|
],
|
|
"enable_lazy_edits": true,
|
|
"enable_smart_files_context": true
|
|
}
|
|
},
|
|
"headers": {
|
|
"authorization": "Bearer testdyadkey"
|
|
}
|
|
} |