From 0dce514a51509f6204d7a5a5c50135a111dad060 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Sun, 1 Feb 2026 22:19:54 +0000 Subject: [PATCH] feat: Add Chrome extension template with WXT and Base44 Add a new Chrome extension template featuring: - WXT framework for modern web extension development - Base44 backend integration for data storage - Bookmarking functionality with save, view, and delete - AI-powered search using Base44 agents - React + TypeScript for UI components - Tailwind CSS for styling - Complete documentation and setup instructions The template provides a ready-to-use bookmark manager extension that demonstrates Base44's capabilities in a browser extension context. Closes #173 Co-authored-by: Kfir Stri --- templates/chrome-extension/.nvmrc | 1 + templates/chrome-extension/README.md | 90 +++++++++ .../base44/agents/search_agent.jsonc | 13 ++ .../chrome-extension/base44/app.jsonc.ejs | 9 + .../chrome-extension/base44/config.jsonc.ejs | 8 + .../base44/entities/bookmark.jsonc | 41 ++++ templates/chrome-extension/gitignore.ejs | 25 +++ templates/chrome-extension/package.json | 30 +++ templates/chrome-extension/postcss.config.js | 6 + .../chrome-extension/public/icon/README.md | 12 ++ .../chrome-extension/public/manifest.json | 25 +++ templates/chrome-extension/tailwind.config.js | 8 + templates/chrome-extension/tsconfig.json | 31 +++ templates/chrome-extension/tsconfig.node.json | 10 + .../wxt-src/components/BookmarkCard.tsx | 83 ++++++++ .../wxt-src/components/Button.tsx | 36 ++++ .../wxt-src/components/Input.tsx | 12 ++ .../wxt-src/entrypoints/background.ts | 19 ++ .../wxt-src/entrypoints/popup/App.tsx | 186 ++++++++++++++++++ .../wxt-src/entrypoints/popup/index.html | 12 ++ .../wxt-src/entrypoints/popup/main.tsx | 10 + .../wxt-src/entrypoints/popup/style.css | 21 ++ .../wxt-src/lib/base44Client.ts.ejs | 5 + templates/chrome-extension/wxt.config.ts | 7 + templates/templates.json | 6 + 25 files changed, 706 insertions(+) create mode 100644 templates/chrome-extension/.nvmrc create mode 100644 templates/chrome-extension/README.md create mode 100644 templates/chrome-extension/base44/agents/search_agent.jsonc create mode 100644 templates/chrome-extension/base44/app.jsonc.ejs create mode 100644 templates/chrome-extension/base44/config.jsonc.ejs create mode 100644 templates/chrome-extension/base44/entities/bookmark.jsonc create mode 100644 templates/chrome-extension/gitignore.ejs create mode 100644 templates/chrome-extension/package.json create mode 100644 templates/chrome-extension/postcss.config.js create mode 100644 templates/chrome-extension/public/icon/README.md create mode 100644 templates/chrome-extension/public/manifest.json create mode 100644 templates/chrome-extension/tailwind.config.js create mode 100644 templates/chrome-extension/tsconfig.json create mode 100644 templates/chrome-extension/tsconfig.node.json create mode 100644 templates/chrome-extension/wxt-src/components/BookmarkCard.tsx create mode 100644 templates/chrome-extension/wxt-src/components/Button.tsx create mode 100644 templates/chrome-extension/wxt-src/components/Input.tsx create mode 100644 templates/chrome-extension/wxt-src/entrypoints/background.ts create mode 100644 templates/chrome-extension/wxt-src/entrypoints/popup/App.tsx create mode 100644 templates/chrome-extension/wxt-src/entrypoints/popup/index.html create mode 100644 templates/chrome-extension/wxt-src/entrypoints/popup/main.tsx create mode 100644 templates/chrome-extension/wxt-src/entrypoints/popup/style.css create mode 100644 templates/chrome-extension/wxt-src/lib/base44Client.ts.ejs create mode 100644 templates/chrome-extension/wxt.config.ts diff --git a/templates/chrome-extension/.nvmrc b/templates/chrome-extension/.nvmrc new file mode 100644 index 00000000..209e3ef4 --- /dev/null +++ b/templates/chrome-extension/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/templates/chrome-extension/README.md b/templates/chrome-extension/README.md new file mode 100644 index 00000000..719f981d --- /dev/null +++ b/templates/chrome-extension/README.md @@ -0,0 +1,90 @@ +# Chrome Bookmarks Extension + +A Chrome extension for bookmarking websites with AI-powered search, built with WXT framework and Base44 backend. + +## Features + +- **Save Bookmarks**: Save any website with a single click +- **View Bookmarks**: Browse your saved bookmarks in the popup +- **AI Search**: Search through your bookmarks using natural language +- **Base44 Backend**: Powered by Base44 for data storage and AI capabilities + +## Structure + +``` +base44/ # Backend configuration +├── config.jsonc # Project settings +├── entities/ # Data schemas +│ └── bookmark.jsonc # Bookmark entity +└── agents/ # AI agents + └── search_agent.jsonc # Bookmark search agent + +wxt-src/ # Extension source code +├── entrypoints/ +│ ├── background/ # Background service worker +│ ├── content/ # Content scripts +│ └── popup/ # Extension popup UI +└── components/ # Shared React components + +public/ # Static assets +└── icon/ # Extension icons +``` + +## Development + +```bash +npm install +npm run dev +``` + +This will start WXT in development mode with hot-reload enabled. + +## Commands + +| Command | Description | +|---------|-------------| +| `npm run dev` | Start development mode (Chrome) | +| `npm run dev:firefox` | Start development mode (Firefox) | +| `npm run build` | Build for production (Chrome) | +| `npm run build:firefox` | Build for production (Firefox) | +| `npm run zip` | Create distribution zip (Chrome) | +| `npm run zip:firefox` | Create distribution zip (Firefox) | + +## Base44 Setup + +```bash +base44 login # Authenticate +base44 entities push # Push entity schemas +base44 agents push # Push AI agents +base44 deploy # Deploy backend +``` + +## Loading the Extension + +### Chrome +1. Run `npm run build` to create the production build +2. Open Chrome and navigate to `chrome://extensions/` +3. Enable "Developer mode" +4. Click "Load unpacked" +5. Select the `.output/chrome-mv3` directory + +### Firefox +1. Run `npm run build:firefox` +2. Open Firefox and navigate to `about:debugging#/runtime/this-firefox` +3. Click "Load Temporary Add-on" +4. Select any file in the `.output/firefox-mv3` directory + +## Usage + +1. **Save a Bookmark**: Click the extension icon and press "Save Current Page" +2. **View Bookmarks**: Open the popup to see your saved bookmarks +3. **Search**: Use the search bar with natural language queries like "show me articles about React" +4. **Delete**: Click the trash icon to remove a bookmark + +## Architecture + +- **WXT Framework**: Modern web extension development framework with Vite +- **React**: UI components with hooks +- **Base44 SDK**: Backend integration for data storage +- **AI Agents**: Natural language search powered by Base44 agents +- **Tailwind CSS**: Utility-first styling diff --git a/templates/chrome-extension/base44/agents/search_agent.jsonc b/templates/chrome-extension/base44/agents/search_agent.jsonc new file mode 100644 index 00000000..bfe0b94a --- /dev/null +++ b/templates/chrome-extension/base44/agents/search_agent.jsonc @@ -0,0 +1,13 @@ +{ + "name": "Bookmark Search Agent", + "description": "AI agent that helps users search through their bookmarks using natural language queries", + "instructions": "You are a helpful assistant that searches through a user's bookmarks. When a user asks a question or describes what they're looking for, search through their bookmarks and return the most relevant results. You can understand natural language queries like 'articles about React', 'bookmarks from last week', or 'tutorials I saved'.", + "tools": [ + { + "type": "query", + "entity": "Bookmark", + "description": "Search and filter bookmarks" + } + ], + "model": "gpt-4-turbo-preview" +} diff --git a/templates/chrome-extension/base44/app.jsonc.ejs b/templates/chrome-extension/base44/app.jsonc.ejs new file mode 100644 index 00000000..abfe049b --- /dev/null +++ b/templates/chrome-extension/base44/app.jsonc.ejs @@ -0,0 +1,9 @@ +--- +outputFileName: .app.jsonc +--- +// Base44 App Configuration +// This file links your local project to your Base44 app. +// Do not commit this file to version control. +{ + "id": "<%= projectId %>" +} diff --git a/templates/chrome-extension/base44/config.jsonc.ejs b/templates/chrome-extension/base44/config.jsonc.ejs new file mode 100644 index 00000000..cc71bb1c --- /dev/null +++ b/templates/chrome-extension/base44/config.jsonc.ejs @@ -0,0 +1,8 @@ +// Base44 Project Configuration +// JSONC enables inline documentation and discoverability directly in config files. +// Chrome extension template with WXT framework and Base44 backend. + +{ + "name": "<%= name %>"<% if (description) { %>, + "description": "<%= description %>"<% } %> +} diff --git a/templates/chrome-extension/base44/entities/bookmark.jsonc b/templates/chrome-extension/base44/entities/bookmark.jsonc new file mode 100644 index 00000000..79160893 --- /dev/null +++ b/templates/chrome-extension/base44/entities/bookmark.jsonc @@ -0,0 +1,41 @@ +{ + "name": "Bookmark", + "fields": { + "url": { + "type": "string", + "required": true, + "description": "The URL of the bookmarked page" + }, + "title": { + "type": "string", + "required": true, + "description": "The title of the bookmarked page" + }, + "description": { + "type": "string", + "description": "Optional description or notes about the bookmark" + }, + "favicon": { + "type": "string", + "description": "URL to the site's favicon" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags for categorizing bookmarks" + }, + "createdAt": { + "type": "timestamp", + "autoCreate": true, + "description": "Timestamp when the bookmark was created" + } + }, + "indexes": [ + { + "fields": ["createdAt"], + "direction": "desc" + } + ] +} diff --git a/templates/chrome-extension/gitignore.ejs b/templates/chrome-extension/gitignore.ejs new file mode 100644 index 00000000..aa4fa4f3 --- /dev/null +++ b/templates/chrome-extension/gitignore.ejs @@ -0,0 +1,25 @@ +--- +outputFileName: .gitignore +--- +# Dependencies +node_modules/ + +# Build outputs +.output/ +.wxt/ +dist/ + +# Environment +.env +.env.local +.app.jsonc + +# OS +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo diff --git a/templates/chrome-extension/package.json b/templates/chrome-extension/package.json new file mode 100644 index 00000000..1ae670df --- /dev/null +++ b/templates/chrome-extension/package.json @@ -0,0 +1,30 @@ +{ + "name": "chrome-bookmarks-extension", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "wxt", + "dev:firefox": "wxt -b firefox", + "build": "wxt build", + "build:firefox": "wxt build -b firefox", + "zip": "wxt zip", + "zip:firefox": "wxt zip -b firefox", + "postinstall": "wxt prepare" + }, + "dependencies": { + "@base44/sdk": "^0.8.3", + "lucide-react": "^0.475.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.5.3", + "tailwindcss": "^3.4.17", + "wxt": "^0.19.0" + } +} diff --git a/templates/chrome-extension/postcss.config.js b/templates/chrome-extension/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/templates/chrome-extension/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/templates/chrome-extension/public/icon/README.md b/templates/chrome-extension/public/icon/README.md new file mode 100644 index 00000000..3121e4f8 --- /dev/null +++ b/templates/chrome-extension/public/icon/README.md @@ -0,0 +1,12 @@ +# Extension Icons + +Place your extension icons here: + +- `16.png` - 16x16 pixels (browser toolbar) +- `32.png` - 32x32 pixels (Windows) +- `48.png` - 48x48 pixels (extensions page) +- `128.png` - 128x128 pixels (Chrome Web Store) + +You can use tools like [Figma](https://figma.com), [Canva](https://canva.com), or any image editor to create these icons. + +For now, WXT will generate default icons if these are missing. diff --git a/templates/chrome-extension/public/manifest.json b/templates/chrome-extension/public/manifest.json new file mode 100644 index 00000000..bec58ef5 --- /dev/null +++ b/templates/chrome-extension/public/manifest.json @@ -0,0 +1,25 @@ +{ + "manifest_version": 3, + "name": "Bookmark Manager", + "version": "1.0.0", + "description": "Save and search bookmarks with AI assistance", + "permissions": ["tabs", "storage"], + "action": { + "default_popup": "popup.html", + "default_icon": { + "16": "icon/16.png", + "32": "icon/32.png", + "48": "icon/48.png", + "128": "icon/128.png" + } + }, + "icons": { + "16": "icon/16.png", + "32": "icon/32.png", + "48": "icon/48.png", + "128": "icon/128.png" + }, + "background": { + "service_worker": "background.js" + } +} diff --git a/templates/chrome-extension/tailwind.config.js b/templates/chrome-extension/tailwind.config.js new file mode 100644 index 00000000..00b8f887 --- /dev/null +++ b/templates/chrome-extension/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./wxt-src/**/*.{js,jsx,ts,tsx,html}'], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/templates/chrome-extension/tsconfig.json b/templates/chrome-extension/tsconfig.json new file mode 100644 index 00000000..d17c0881 --- /dev/null +++ b/templates/chrome-extension/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + /* Path aliases */ + "baseUrl": ".", + "paths": { + "@/*": ["./wxt-src/*"] + } + }, + "include": ["wxt-src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/templates/chrome-extension/tsconfig.node.json b/templates/chrome-extension/tsconfig.node.json new file mode 100644 index 00000000..a5983e61 --- /dev/null +++ b/templates/chrome-extension/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["wxt.config.ts"] +} diff --git a/templates/chrome-extension/wxt-src/components/BookmarkCard.tsx b/templates/chrome-extension/wxt-src/components/BookmarkCard.tsx new file mode 100644 index 00000000..b155c005 --- /dev/null +++ b/templates/chrome-extension/wxt-src/components/BookmarkCard.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { ExternalLink, Trash2 } from 'lucide-react'; +import { Button } from './Button'; + +interface Bookmark { + id: string; + url: string; + title: string; + favicon?: string; + description?: string; + createdAt?: string; +} + +interface BookmarkCardProps { + bookmark: Bookmark; + onDelete: () => void; +} + +export const BookmarkCard: React.FC = ({ bookmark, onDelete }) => { + const handleClick = () => { + browser.tabs.create({ url: bookmark.url }); + }; + + return ( +
+ {/* Favicon */} + {bookmark.favicon ? ( + { + (e.target as HTMLImageElement).style.display = 'none'; + }} + /> + ) : ( +
+ )} + + {/* Content */} +
+ + {bookmark.description && ( +

+ {bookmark.description} +

+ )} +
+ + {/* Actions */} +
+ + +
+
+ ); +}; diff --git a/templates/chrome-extension/wxt-src/components/Button.tsx b/templates/chrome-extension/wxt-src/components/Button.tsx new file mode 100644 index 00000000..d6bf651b --- /dev/null +++ b/templates/chrome-extension/wxt-src/components/Button.tsx @@ -0,0 +1,36 @@ +import React from 'react'; + +interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: 'default' | 'ghost'; + size?: 'default' | 'sm' | 'icon'; +} + +export const Button: React.FC = ({ + children, + className = '', + variant = 'default', + size = 'default', + ...props +}) => { + const baseStyles = 'inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-400 disabled:pointer-events-none disabled:opacity-50'; + + const variants = { + default: 'bg-slate-900 text-white hover:bg-slate-800', + ghost: 'hover:bg-slate-100 text-slate-700', + }; + + const sizes = { + default: 'h-10 px-4 py-2', + sm: 'h-8 px-3 text-sm', + icon: 'h-9 w-9', + }; + + return ( + + ); +}; diff --git a/templates/chrome-extension/wxt-src/components/Input.tsx b/templates/chrome-extension/wxt-src/components/Input.tsx new file mode 100644 index 00000000..4b79dacc --- /dev/null +++ b/templates/chrome-extension/wxt-src/components/Input.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +interface InputProps extends React.InputHTMLAttributes {} + +export const Input: React.FC = ({ className = '', ...props }) => { + return ( + + ); +}; diff --git a/templates/chrome-extension/wxt-src/entrypoints/background.ts b/templates/chrome-extension/wxt-src/entrypoints/background.ts new file mode 100644 index 00000000..e6c43fb1 --- /dev/null +++ b/templates/chrome-extension/wxt-src/entrypoints/background.ts @@ -0,0 +1,19 @@ +export default defineBackground(() => { + console.log('Bookmark Extension background loaded'); + + // Listen for messages from popup or content scripts + browser.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'GET_CURRENT_TAB') { + browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { + if (tabs[0]) { + sendResponse({ + url: tabs[0].url, + title: tabs[0].title, + favicon: tabs[0].favIconUrl, + }); + } + }); + return true; // Keep message channel open for async response + } + }); +}); diff --git a/templates/chrome-extension/wxt-src/entrypoints/popup/App.tsx b/templates/chrome-extension/wxt-src/entrypoints/popup/App.tsx new file mode 100644 index 00000000..066fe9f3 --- /dev/null +++ b/templates/chrome-extension/wxt-src/entrypoints/popup/App.tsx @@ -0,0 +1,186 @@ +import { useState, useEffect } from 'react'; +import { base44 } from '@/lib/base44Client'; +import { Button } from '@/components/Button'; +import { Input } from '@/components/Input'; +import { BookmarkCard } from '@/components/BookmarkCard'; +import { Bookmark, Plus, Search, Sparkles } from 'lucide-react'; + +const BookmarkEntity = base44.entities.Bookmark; + +interface CurrentTab { + url?: string; + title?: string; + favicon?: string; +} + +export default function App() { + const [bookmarks, setBookmarks] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + const [currentTab, setCurrentTab] = useState({}); + const [isAISearch, setIsAISearch] = useState(false); + + useEffect(() => { + fetchBookmarks(); + getCurrentTab(); + }, []); + + const getCurrentTab = async () => { + try { + const response = await browser.runtime.sendMessage({ type: 'GET_CURRENT_TAB' }); + setCurrentTab(response); + } catch (error) { + console.error('Error getting current tab:', error); + } + }; + + const fetchBookmarks = async () => { + try { + const data = await BookmarkEntity.list(); + setBookmarks(data); + } catch (error) { + console.error('Error fetching bookmarks:', error); + } finally { + setIsLoading(false); + } + }; + + const saveCurrentPage = async () => { + if (!currentTab.url || !currentTab.title) return; + + setIsSaving(true); + try { + await BookmarkEntity.create({ + url: currentTab.url, + title: currentTab.title, + favicon: currentTab.favicon || '', + tags: [], + }); + await fetchBookmarks(); + } catch (error) { + console.error('Error saving bookmark:', error); + } finally { + setIsSaving(false); + } + }; + + const deleteBookmark = async (id: string) => { + try { + await BookmarkEntity.delete(id); + await fetchBookmarks(); + } catch (error) { + console.error('Error deleting bookmark:', error); + } + }; + + const handleSearch = async () => { + if (!searchQuery.trim()) { + fetchBookmarks(); + return; + } + + if (isAISearch) { + // Use AI agent for natural language search + try { + const agent = base44.agents.BookmarkSearchAgent; + const response = await agent.run(searchQuery); + // Parse agent response and filter bookmarks + // This is a placeholder - actual implementation depends on agent response format + console.log('AI Search result:', response); + } catch (error) { + console.error('Error with AI search:', error); + } + } else { + // Simple text search + const filtered = bookmarks.filter((bookmark) => + bookmark.title.toLowerCase().includes(searchQuery.toLowerCase()) || + bookmark.url.toLowerCase().includes(searchQuery.toLowerCase()) + ); + setBookmarks(filtered); + } + }; + + const filteredBookmarks = searchQuery + ? bookmarks.filter((bookmark) => + bookmark.title.toLowerCase().includes(searchQuery.toLowerCase()) || + bookmark.url.toLowerCase().includes(searchQuery.toLowerCase()) + ) + : bookmarks; + + return ( +
+
+ {/* Header */} +
+
+

+ + My Bookmarks +

+ +
+ + {/* Search Bar */} +
+ setSearchQuery(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleSearch()} + placeholder="Search bookmarks..." + className="pl-9 pr-10" + /> + + +
+
+ + {/* Bookmarks List */} +
+ {isLoading ? ( +
+
+
+ ) : filteredBookmarks.length === 0 ? ( +
+ +

+ {searchQuery ? 'No bookmarks found' : 'No bookmarks yet'} +

+ {!searchQuery && ( +

+ Click "Save Page" to bookmark this page +

+ )} +
+ ) : ( + filteredBookmarks.map((bookmark) => ( + deleteBookmark(bookmark.id)} + /> + )) + )} +
+
+
+ ); +} diff --git a/templates/chrome-extension/wxt-src/entrypoints/popup/index.html b/templates/chrome-extension/wxt-src/entrypoints/popup/index.html new file mode 100644 index 00000000..285d400b --- /dev/null +++ b/templates/chrome-extension/wxt-src/entrypoints/popup/index.html @@ -0,0 +1,12 @@ + + + + + + Bookmarks + + +
+ + + diff --git a/templates/chrome-extension/wxt-src/entrypoints/popup/main.tsx b/templates/chrome-extension/wxt-src/entrypoints/popup/main.tsx new file mode 100644 index 00000000..0a810097 --- /dev/null +++ b/templates/chrome-extension/wxt-src/entrypoints/popup/main.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; +import './style.css'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +); diff --git a/templates/chrome-extension/wxt-src/entrypoints/popup/style.css b/templates/chrome-extension/wxt-src/entrypoints/popup/style.css new file mode 100644 index 00000000..526d3c8e --- /dev/null +++ b/templates/chrome-extension/wxt-src/entrypoints/popup/style.css @@ -0,0 +1,21 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + margin: 0; + padding: 0; + min-width: 400px; + max-width: 400px; + min-height: 500px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +#root { + width: 100%; + height: 100%; +} diff --git a/templates/chrome-extension/wxt-src/lib/base44Client.ts.ejs b/templates/chrome-extension/wxt-src/lib/base44Client.ts.ejs new file mode 100644 index 00000000..7a65e0d3 --- /dev/null +++ b/templates/chrome-extension/wxt-src/lib/base44Client.ts.ejs @@ -0,0 +1,5 @@ +import { Base44 } from '@base44/sdk'; + +export const base44 = new Base44({ + projectId: '<%= projectId %>', +}); diff --git a/templates/chrome-extension/wxt.config.ts b/templates/chrome-extension/wxt.config.ts new file mode 100644 index 00000000..c1bf5120 --- /dev/null +++ b/templates/chrome-extension/wxt.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'wxt'; + +export default defineConfig({ + extensionApi: 'chrome', + modules: ['@wxt-dev/module-react'], + srcDir: 'wxt-src', +}); diff --git a/templates/templates.json b/templates/templates.json index 852592e6..8d4e946a 100644 --- a/templates/templates.json +++ b/templates/templates.json @@ -11,6 +11,12 @@ "name": "Create a basic project", "description": "Minimal Base44 backend for defining your data models and logic", "path": "backend-only" + }, + { + "id": "chrome-extension", + "name": "Chrome Extension", + "description": "Chrome extension with WXT framework and Base44 backend for bookmarking with AI search", + "path": "chrome-extension" } ] }