From ec6860fa2390c12a23bc367d66be0e5e9b179fb8 Mon Sep 17 00:00:00 2001 From: Goal Champion 869 Date: Thu, 12 Mar 2026 08:36:02 +0000 Subject: [PATCH] feat(template): migrate backend-and-client to TypeScript, drop Tailwind/shadcn - Convert all .jsx/.js to .tsx/.ts (App, main, vite.config, base44Client) - Replace jsconfig.json with proper tsconfig.json / tsconfig.app.json / tsconfig.node.json - Remove Tailwind CSS v3 setup (postcss.config.js, tailwind.config.js, autoprefixer) - Remove bundled shadcn/ui components (button, checkbox, input) and components.json - Remove Base44Logo component and demo agent config (task_manager.jsonc) - Simplify App.tsx to a minimal typed task demo using @base44/sdk - Simplify index.css to a basic box-sizing + body reset - Update package.json: add typescript + @types/react, remove postcss/tailwind/lucide-react - Update build script to tsc -b && vite build for type checking on build Co-Authored-By: Claude Sonnet 4.6 --- .../templates/backend-and-client/README.md | 12 +- .../base44/agents/task_manager.jsonc | 11 -- .../backend-and-client/components.json | 16 -- .../templates/backend-and-client/index.html | 4 +- .../backend-and-client/jsconfig.json | 13 -- .../templates/backend-and-client/package.json | 13 +- .../backend-and-client/postcss.config.js | 6 - .../templates/backend-and-client/src/App.jsx | 148 ------------------ .../templates/backend-and-client/src/App.tsx | 74 +++++++++ ...ase44Client.js.ejs => base44Client.ts.ejs} | 0 .../src/components/Base44Logo.jsx | 15 -- .../src/components/ui/button.jsx | 23 --- .../src/components/ui/checkbox.jsx | 20 --- .../src/components/ui/input.jsx | 13 -- .../backend-and-client/src/index.css | 39 +---- .../templates/backend-and-client/src/main.jsx | 6 - .../templates/backend-and-client/src/main.tsx | 10 ++ .../backend-and-client/tailwind.config.js | 41 ----- .../backend-and-client/tsconfig.app.json | 32 ++++ .../backend-and-client/tsconfig.json | 7 + .../backend-and-client/tsconfig.node.json | 24 +++ .../backend-and-client/vite.config.js | 12 -- .../backend-and-client/vite.config.ts | 15 ++ 23 files changed, 180 insertions(+), 374 deletions(-) delete mode 100644 packages/cli/templates/backend-and-client/base44/agents/task_manager.jsonc delete mode 100644 packages/cli/templates/backend-and-client/components.json delete mode 100644 packages/cli/templates/backend-and-client/jsconfig.json delete mode 100644 packages/cli/templates/backend-and-client/postcss.config.js delete mode 100644 packages/cli/templates/backend-and-client/src/App.jsx create mode 100644 packages/cli/templates/backend-and-client/src/App.tsx rename packages/cli/templates/backend-and-client/src/api/{base44Client.js.ejs => base44Client.ts.ejs} (100%) delete mode 100644 packages/cli/templates/backend-and-client/src/components/Base44Logo.jsx delete mode 100644 packages/cli/templates/backend-and-client/src/components/ui/button.jsx delete mode 100644 packages/cli/templates/backend-and-client/src/components/ui/checkbox.jsx delete mode 100644 packages/cli/templates/backend-and-client/src/components/ui/input.jsx delete mode 100644 packages/cli/templates/backend-and-client/src/main.jsx create mode 100644 packages/cli/templates/backend-and-client/src/main.tsx delete mode 100644 packages/cli/templates/backend-and-client/tailwind.config.js create mode 100644 packages/cli/templates/backend-and-client/tsconfig.app.json create mode 100644 packages/cli/templates/backend-and-client/tsconfig.json create mode 100644 packages/cli/templates/backend-and-client/tsconfig.node.json delete mode 100644 packages/cli/templates/backend-and-client/vite.config.js create mode 100644 packages/cli/templates/backend-and-client/vite.config.ts diff --git a/packages/cli/templates/backend-and-client/README.md b/packages/cli/templates/backend-and-client/README.md index 0fa84faa..1951ea2c 100644 --- a/packages/cli/templates/backend-and-client/README.md +++ b/packages/cli/templates/backend-and-client/README.md @@ -1,6 +1,6 @@ -# Todo App +# Base44 App -A simple todo list app built with React and Base44 backend. +A React + TypeScript app with Base44 backend. ## Structure @@ -11,10 +11,8 @@ base44/ # Backend configuration └── task.jsonc # Task entity src/ # Frontend code -├── App.jsx # Main todo app -├── api/ # Base44 client -├── components/ui/ # UI components -└── lib/ # Utilities +├── App.tsx # Main app component +└── api/ # Base44 client ``` ## Development @@ -29,7 +27,7 @@ npm run dev | Command | Description | |---------|-------------| | `npm run dev` | Start dev server | -| `npm run build` | Build for production | +| `npm run build` | Type-check + build for production | | `npm run preview` | Preview production build | ## Base44 CLI diff --git a/packages/cli/templates/backend-and-client/base44/agents/task_manager.jsonc b/packages/cli/templates/backend-and-client/base44/agents/task_manager.jsonc deleted file mode 100644 index 35253c00..00000000 --- a/packages/cli/templates/backend-and-client/base44/agents/task_manager.jsonc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "task_manager", - "description": "An AI agent that helps you manage and change your tasks", - "instructions": "You are a helpful task management assistant. You can help users create, update, mark as completed, and delete tasks using the entity tool. When a user asks to change a task, help them modify it by updating the appropriate fields. Always be conversational and helpful.", - "tool_configs": [ - { - "entity_name": "Task", - "allowed_operations": ["read", "create", "update", "delete"] - } - ] -} diff --git a/packages/cli/templates/backend-and-client/components.json b/packages/cli/templates/backend-and-client/components.json deleted file mode 100644 index 068bddc0..00000000 --- a/packages/cli/templates/backend-and-client/components.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": false, - "tsx": false, - "tailwind": { - "config": "tailwind.config.js", - "css": "src/index.css", - "baseColor": "slate", - "cssVariables": true - }, - "aliases": { - "components": "@/components", - "ui": "@/components/ui" - } -} diff --git a/packages/cli/templates/backend-and-client/index.html b/packages/cli/templates/backend-and-client/index.html index 01d83531..eb17a96e 100644 --- a/packages/cli/templates/backend-and-client/index.html +++ b/packages/cli/templates/backend-and-client/index.html @@ -4,10 +4,10 @@ - Todo App + Base44 App
- + diff --git a/packages/cli/templates/backend-and-client/jsconfig.json b/packages/cli/templates/backend-and-client/jsconfig.json deleted file mode 100644 index 39ebe913..00000000 --- a/packages/cli/templates/backend-and-client/jsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - }, - "jsx": "react-jsx", - "module": "esnext", - "moduleResolution": "bundler", - "target": "esnext" - }, - "include": ["src"] -} diff --git a/packages/cli/templates/backend-and-client/package.json b/packages/cli/templates/backend-and-client/package.json index 91b53dfb..0a98cb6a 100644 --- a/packages/cli/templates/backend-and-client/package.json +++ b/packages/cli/templates/backend-and-client/package.json @@ -5,20 +5,19 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", + "build": "tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "@base44/sdk": "^0.8.3", - "lucide-react": "^0.475.0", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "devDependencies": { + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.4", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.3", - "tailwindcss": "^3.4.17", + "typescript": "^5.7.2", "vite": "^6.1.0" } } diff --git a/packages/cli/templates/backend-and-client/postcss.config.js b/packages/cli/templates/backend-and-client/postcss.config.js deleted file mode 100644 index 2aa7205d..00000000 --- a/packages/cli/templates/backend-and-client/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/packages/cli/templates/backend-and-client/src/App.jsx b/packages/cli/templates/backend-and-client/src/App.jsx deleted file mode 100644 index 71296446..00000000 --- a/packages/cli/templates/backend-and-client/src/App.jsx +++ /dev/null @@ -1,148 +0,0 @@ -import { useState, useEffect } from "react"; -import { base44 } from "@/api/base44Client"; -import { Button } from "@/components/ui/button"; -import { Checkbox } from "@/components/ui/checkbox"; -import { Input } from "@/components/ui/input"; -import { Base44Logo } from "@/components/Base44Logo"; -import { Plus, Trash2, CheckCircle2 } from "lucide-react"; - -const Task = base44.entities.Task; - -export default function App() { - const [tasks, setTasks] = useState([]); - const [newTaskTitle, setNewTaskTitle] = useState(""); - const [isLoading, setIsLoading] = useState(true); - - const fetchTasks = async () => { - const data = await Task.list(); - setTasks(data); - setIsLoading(false); - }; - - useEffect(() => { - fetchTasks(); - }, []); - - const handleSubmit = async (e) => { - e.preventDefault(); - if (!newTaskTitle.trim()) return; - await Task.create({ title: newTaskTitle.trim(), completed: false }); - setNewTaskTitle(""); - fetchTasks(); - }; - - const toggleTask = async (id, completed) => { - await Task.update(id, { completed }); - fetchTasks(); - }; - - const deleteTask = async (id) => { - await Task.delete(id); - fetchTasks(); - }; - - const clearCompleted = async () => { - await Promise.all( - tasks.filter((t) => t.completed).map((t) => Task.delete(t.id)) - ); - fetchTasks(); - }; - - const completedCount = tasks.filter((t) => t.completed).length; - const totalCount = tasks.length; - - return ( -
-
- {/* Header */} -
-

- - - Base44 - Tasks - -

- {totalCount > 0 && ( -

- {completedCount} of {totalCount} completed -

- )} -
- - {/* Add Task Form */} -
-
- setNewTaskTitle(e.target.value)} - placeholder="What needs to be done?" - className="flex-1 h-12 bg-white border-slate-200 rounded-xl shadow-sm" - /> - -
-
- - {/* Task List */} -
- {isLoading ? ( -
-
-
- ) : tasks.length === 0 ? ( -
-

No tasks yet. Add one above!

-
- ) : ( - tasks.map((task) => ( -
- toggleTask(task.id, checked)} - className="w-5 h-5 rounded-md border-slate-300 data-[state=checked]:bg-orange-500 data-[state=checked]:border-orange-500" - /> - - {task.title} - - -
- )) - )} -
- - {/* Footer */} - {completedCount > 0 && ( -
- -
- )} -
-
- ); -} diff --git a/packages/cli/templates/backend-and-client/src/App.tsx b/packages/cli/templates/backend-and-client/src/App.tsx new file mode 100644 index 00000000..a8cbfbbb --- /dev/null +++ b/packages/cli/templates/backend-and-client/src/App.tsx @@ -0,0 +1,74 @@ +import { useState, useEffect } from 'react' +import { base44 } from '@/api/base44Client' + +interface Task { + id: string + title: string + completed: boolean +} + +const Task = base44.entities.Task + +export default function App() { + const [tasks, setTasks] = useState([]) + const [input, setInput] = useState('') + const [loading, setLoading] = useState(true) + + useEffect(() => { + Task.list().then((data: Task[]) => { + setTasks(data) + setLoading(false) + }) + }, []) + + const addTask = async (e: React.FormEvent) => { + e.preventDefault() + if (!input.trim()) return + await Task.create({ title: input.trim(), completed: false }) + setInput('') + setTasks(await Task.list()) + } + + const toggleTask = async (task: Task) => { + await Task.update(task.id, { completed: !task.completed }) + setTasks(await Task.list()) + } + + const deleteTask = async (id: string) => { + await Task.delete(id) + setTasks(await Task.list()) + } + + return ( +
+

Tasks

+
+ setInput(e.target.value)} + placeholder="New task…" + /> + +
+ {loading ? ( +

Loading…

+ ) : ( +
    + {tasks.map((task) => ( +
  • + toggleTask(task)} + /> + + {task.title} + + +
  • + ))} +
+ )} +
+ ) +} diff --git a/packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs b/packages/cli/templates/backend-and-client/src/api/base44Client.ts.ejs similarity index 100% rename from packages/cli/templates/backend-and-client/src/api/base44Client.js.ejs rename to packages/cli/templates/backend-and-client/src/api/base44Client.ts.ejs diff --git a/packages/cli/templates/backend-and-client/src/components/Base44Logo.jsx b/packages/cli/templates/backend-and-client/src/components/Base44Logo.jsx deleted file mode 100644 index c80bf52e..00000000 --- a/packages/cli/templates/backend-and-client/src/components/Base44Logo.jsx +++ /dev/null @@ -1,15 +0,0 @@ -export function Base44Logo({ className = "w-8 h-8" }) { - return ( - - - - ); -} diff --git a/packages/cli/templates/backend-and-client/src/components/ui/button.jsx b/packages/cli/templates/backend-and-client/src/components/ui/button.jsx deleted file mode 100644 index f6ee99bc..00000000 --- a/packages/cli/templates/backend-and-client/src/components/ui/button.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import { forwardRef } from 'react'; - -const Button = forwardRef(({ className = '', variant, size, ...props }, ref) => { - const baseStyles = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50'; - - const variantStyles = variant === 'ghost' - ? 'hover:bg-slate-100' - : 'bg-slate-900 text-white shadow hover:bg-slate-800'; - - const sizeStyles = size === 'icon' ? 'h-9 w-9' : 'h-9 px-4 py-2'; - - return ( - -)); - -Checkbox.displayName = 'Checkbox'; - -export { Checkbox }; diff --git a/packages/cli/templates/backend-and-client/src/components/ui/input.jsx b/packages/cli/templates/backend-and-client/src/components/ui/input.jsx deleted file mode 100644 index 33b32d07..00000000 --- a/packages/cli/templates/backend-and-client/src/components/ui/input.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { forwardRef } from 'react'; - -const Input = forwardRef(({ className = '', ...props }, ref) => ( - -)); - -Input.displayName = 'Input'; - -export { Input }; diff --git a/packages/cli/templates/backend-and-client/src/index.css b/packages/cli/templates/backend-and-client/src/index.css index 863c4216..7b6bb477 100644 --- a/packages/cli/templates/backend-and-client/src/index.css +++ b/packages/cli/templates/backend-and-client/src/index.css @@ -1,37 +1,8 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - --radius: 0.5rem; - } +*, *::before, *::after { + box-sizing: border-box; } -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground antialiased; - } +body { + margin: 0; + font-family: system-ui, sans-serif; } diff --git a/packages/cli/templates/backend-and-client/src/main.jsx b/packages/cli/templates/backend-and-client/src/main.jsx deleted file mode 100644 index f2bf72b4..00000000 --- a/packages/cli/templates/backend-and-client/src/main.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from '@/App.jsx'; -import '@/index.css'; - -ReactDOM.createRoot(document.getElementById('root')).render(); diff --git a/packages/cli/templates/backend-and-client/src/main.tsx b/packages/cli/templates/backend-and-client/src/main.tsx new file mode 100644 index 00000000..0e79b71c --- /dev/null +++ b/packages/cli/templates/backend-and-client/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import '@/index.css' +import App from '@/App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/packages/cli/templates/backend-and-client/tailwind.config.js b/packages/cli/templates/backend-and-client/tailwind.config.js deleted file mode 100644 index d04fdc36..00000000 --- a/packages/cli/templates/backend-and-client/tailwind.config.js +++ /dev/null @@ -1,41 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -export default { - content: ['./index.html', './src/**/*.{js,jsx}'], - theme: { - extend: { - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)', - }, - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))', - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))', - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))', - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))', - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))', - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - }, - }, - }, - plugins: [], -}; diff --git a/packages/cli/templates/backend-and-client/tsconfig.app.json b/packages/cli/templates/backend-and-client/tsconfig.app.json new file mode 100644 index 00000000..69118780 --- /dev/null +++ b/packages/cli/templates/backend-and-client/tsconfig.app.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + + /* Path alias */ + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/packages/cli/templates/backend-and-client/tsconfig.json b/packages/cli/templates/backend-and-client/tsconfig.json new file mode 100644 index 00000000..1ffef600 --- /dev/null +++ b/packages/cli/templates/backend-and-client/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/packages/cli/templates/backend-and-client/tsconfig.node.json b/packages/cli/templates/backend-and-client/tsconfig.node.json new file mode 100644 index 00000000..db0becc8 --- /dev/null +++ b/packages/cli/templates/backend-and-client/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/cli/templates/backend-and-client/vite.config.js b/packages/cli/templates/backend-and-client/vite.config.js deleted file mode 100644 index 95d423e2..00000000 --- a/packages/cli/templates/backend-and-client/vite.config.js +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; -import path from 'path'; - -export default defineConfig({ - plugins: [react()], - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - }, - }, -}); diff --git a/packages/cli/templates/backend-and-client/vite.config.ts b/packages/cli/templates/backend-and-client/vite.config.ts new file mode 100644 index 00000000..2c4b0a02 --- /dev/null +++ b/packages/cli/templates/backend-and-client/vite.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import path from 'path' +import { fileURLToPath } from 'url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +})