mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-06 08:16:03 +00:00
Web Extension with WXT
This commit is contained in:
parent
6341d483a7
commit
c9f0dcf969
18 changed files with 1268 additions and 410 deletions
26
apps/browser-extension/.gitignore
vendored
Normal file
26
apps/browser-extension/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.output
|
||||
stats.html
|
||||
stats-*.json
|
||||
.wxt
|
||||
web-ext.config.ts
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
1
apps/browser-extension/README.md
Normal file
1
apps/browser-extension/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
## Supermemory Browser Extension
|
||||
84
apps/browser-extension/entrypoints/background.ts
Normal file
84
apps/browser-extension/entrypoints/background.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
export default defineBackground(() => {
|
||||
browser.runtime.onInstalled.addListener(() => {
|
||||
browser.contextMenus.create({
|
||||
id: 'save-to-supermemory',
|
||||
title: 'Save to Supermemory',
|
||||
contexts: ['selection', 'page', 'link'],
|
||||
});
|
||||
});
|
||||
|
||||
browser.contextMenus.onClicked.addListener(async (info, tab) => {
|
||||
if (info.menuItemId === 'save-to-supermemory') {
|
||||
if (tab?.id) {
|
||||
try {
|
||||
await browser.tabs.sendMessage(tab.id, {
|
||||
action: 'saveMemory',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to send message to content script:', error);
|
||||
console.log('Content script may not be injected on this page');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === 'saveMemory') {
|
||||
(async () => {
|
||||
try {
|
||||
const result = await browser.storage.local.get(['bearerToken']);
|
||||
const bearerToken = result.bearerToken;
|
||||
//const backendURL = 'http://localhost:8787';
|
||||
const backendURL = 'https://api.supermemory.ai';
|
||||
|
||||
if (!bearerToken) {
|
||||
console.error('No bearer token found');
|
||||
sendResponse({ success: false, error: 'No authentication token found' });
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(`${backendURL}/v3/memories`, {
|
||||
method: 'POST',
|
||||
credentials: 'omit',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${bearerToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
containerTags: ['sm_project_default'],
|
||||
content:
|
||||
message.data.highlightedText +
|
||||
'\n\n' +
|
||||
message.data.html +
|
||||
'\n\n' +
|
||||
message.data.url,
|
||||
metadata: { sm_source: 'consumer' },
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.text();
|
||||
console.error('API call failed:', response.status, errorData);
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: `API call failed: ${response.status}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Memory saved successfully:', data);
|
||||
sendResponse({ success: true, data });
|
||||
} catch (error) {
|
||||
console.error('Error saving memory:', error);
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
212
apps/browser-extension/entrypoints/content.ts
Normal file
212
apps/browser-extension/entrypoints/content.ts
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
main() {
|
||||
let currentToast: HTMLElement | null = null;
|
||||
|
||||
browser.runtime.onMessage.addListener(async (message) => {
|
||||
if (message.action === 'showToast') {
|
||||
showToast(message.state);
|
||||
} else if (message.action === 'saveMemory') {
|
||||
await saveMemory();
|
||||
}
|
||||
});
|
||||
|
||||
async function saveMemory() {
|
||||
try {
|
||||
showToast('loading');
|
||||
|
||||
const highlightedText = window.getSelection()?.toString() || '';
|
||||
|
||||
const url = window.location.href;
|
||||
|
||||
const html = document.documentElement.outerHTML;
|
||||
|
||||
const response = await browser.runtime.sendMessage({
|
||||
action: 'saveMemory',
|
||||
data: {
|
||||
html,
|
||||
highlightedText,
|
||||
url,
|
||||
},
|
||||
});
|
||||
|
||||
console.log('Response from enxtension:', response);
|
||||
if (response.success) {
|
||||
showToast('success');
|
||||
} else {
|
||||
showToast('error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving memory:', error);
|
||||
showToast('error');
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(state: 'loading' | 'success' | 'error') {
|
||||
if (currentToast) {
|
||||
currentToast.remove();
|
||||
}
|
||||
|
||||
const toast = document.createElement('div');
|
||||
toast.id = 'supermemory-toast';
|
||||
|
||||
toast.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 2147483647;
|
||||
background: #ffffff;
|
||||
border-radius: 9999px;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
font-size: 14px;
|
||||
color: #374151;
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
animation: slideIn 0.3s ease-out;
|
||||
`;
|
||||
|
||||
if (!document.getElementById('supermemory-toast-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'supermemory-toast-styles';
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
const icon = document.createElement('div');
|
||||
icon.style.cssText = `
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
`;
|
||||
|
||||
const text = document.createElement('span');
|
||||
text.style.cssText = `
|
||||
font-weight: 500;
|
||||
`;
|
||||
|
||||
if (state === 'loading') {
|
||||
icon.innerHTML = `
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 6V2" stroke="#6366f1" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M12 22V18" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
|
||||
<path d="M20.49 8.51L18.36 6.38" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.7"/>
|
||||
<path d="M5.64 17.64L3.51 15.51" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
|
||||
<path d="M22 12H18" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.8"/>
|
||||
<path d="M6 12H2" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.4"/>
|
||||
<path d="M20.49 15.49L18.36 17.62" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.9"/>
|
||||
<path d="M5.64 6.36L3.51 8.49" stroke="#6366f1" stroke-width="2" stroke-linecap="round" opacity="0.6"/>
|
||||
</svg>
|
||||
`;
|
||||
icon.style.animation = 'spin 1s linear infinite';
|
||||
if (!document.getElementById('supermemory-spinner-styles')) {
|
||||
const spinStyle = document.createElement('style');
|
||||
spinStyle.id = 'supermemory-spinner-styles';
|
||||
spinStyle.textContent = `
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(spinStyle);
|
||||
}
|
||||
text.textContent = 'Adding to Memory...';
|
||||
} else if (state === 'success') {
|
||||
const iconUrl = browser.runtime.getURL('/icon-16.png');
|
||||
icon.innerHTML = `
|
||||
<img src="${iconUrl}" width="20" height="20" alt="Success" style="border-radius: 2px;" />
|
||||
`;
|
||||
text.textContent = 'Added to Memory';
|
||||
} else if (state === 'error') {
|
||||
icon.innerHTML = `
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="#ef4444"/>
|
||||
<path d="M15 9L9 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9 9L15 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
`;
|
||||
text.textContent = 'Failed to save memory / Make sure you are logged in';
|
||||
}
|
||||
|
||||
toast.appendChild(icon);
|
||||
toast.appendChild(text);
|
||||
document.body.appendChild(toast);
|
||||
currentToast = toast;
|
||||
|
||||
if (state === 'success' || state === 'error') {
|
||||
setTimeout(() => {
|
||||
if (currentToast === toast) {
|
||||
toast.style.animation = 'fadeOut 0.3s ease-out';
|
||||
setTimeout(() => {
|
||||
if (toast.parentNode) {
|
||||
toast.remove();
|
||||
}
|
||||
if (currentToast === toast) {
|
||||
currentToast = null;
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', async (event) => {
|
||||
if (
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
event.shiftKey &&
|
||||
event.key === 'm'
|
||||
) {
|
||||
event.preventDefault();
|
||||
await saveMemory();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.source !== window) {
|
||||
return;
|
||||
}
|
||||
const bearerToken = event.data.token;
|
||||
|
||||
if (bearerToken) {
|
||||
if (
|
||||
!(
|
||||
window.location.hostname === 'localhost' ||
|
||||
window.location.hostname === 'supermemory.ai' ||
|
||||
window.location.hostname === 'app.supermemory.ai'
|
||||
)
|
||||
) {
|
||||
console.log(
|
||||
'Bearer token is only allowed to be used on localhost or supermemory.ai'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.storage.local.set({ bearerToken }, () => {});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
83
apps/browser-extension/entrypoints/popup/App.css
Normal file
83
apps/browser-extension/entrypoints/popup/App.css
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
.popup-container {
|
||||
width: 320px;
|
||||
padding: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.header .logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-indicator.signed-in {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.status-indicator.signed-out {
|
||||
background-color: #666666;
|
||||
}
|
||||
|
||||
.sign-out-btn {
|
||||
width: 100%;
|
||||
padding: 8px 16px;
|
||||
background-color: #000000;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sign-out-btn:hover {
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.instruction {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: #666666;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.authenticated, .unauthenticated {
|
||||
text-align: left;
|
||||
}
|
||||
89
apps/browser-extension/entrypoints/popup/App.tsx
Normal file
89
apps/browser-extension/entrypoints/popup/App.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
const [userSignedIn, setUserSignedIn] = useState<boolean>(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
useEffect(() => {
|
||||
const checkAuthStatus = async () => {
|
||||
try {
|
||||
const result = await chrome.storage.local.get(['bearerToken']);
|
||||
setUserSignedIn(!!result.bearerToken);
|
||||
} catch (error) {
|
||||
console.error('Error checking auth status:', error);
|
||||
setUserSignedIn(false);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkAuthStatus();
|
||||
}, []);
|
||||
|
||||
const handleSignOut = async () => {
|
||||
try {
|
||||
await chrome.storage.local.remove(['bearerToken']);
|
||||
setUserSignedIn(false);
|
||||
} catch (error) {
|
||||
console.error('Error signing out:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="popup-container">
|
||||
<div className="header">
|
||||
<img src="/icon-48.png" alt="Supermemory" className="logo" />
|
||||
<h1>Supermemory</h1>
|
||||
</div>
|
||||
<div className="content">
|
||||
<div>Loading...</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="popup-container">
|
||||
<div className="header">
|
||||
<img src="/icon-48.png" alt="Supermemory" className="logo" />
|
||||
<h1>Supermemory</h1>
|
||||
</div>
|
||||
<div className="content">
|
||||
{userSignedIn ? (
|
||||
<div className="authenticated">
|
||||
<div className="status">
|
||||
<span className="status-indicator signed-in"></span>
|
||||
<span>Signed in</span>
|
||||
</div>
|
||||
<button className="sign-out-btn" onClick={handleSignOut}>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="unauthenticated">
|
||||
<div className="status">
|
||||
<span className="status-indicator signed-out"></span>
|
||||
<span>Not signed in</span>
|
||||
</div>
|
||||
<p className="instruction">
|
||||
<a
|
||||
onClick={() => {
|
||||
chrome.tabs.create({
|
||||
url: 'https://app.supermemory.ai/login',
|
||||
});
|
||||
}}
|
||||
>
|
||||
Login to Supermemory
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
13
apps/browser-extension/entrypoints/popup/index.html
Normal file
13
apps/browser-extension/entrypoints/popup/index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Default Popup Title</title>
|
||||
<meta name="manifest.type" content="browser_action" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="./main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
10
apps/browser-extension/entrypoints/popup/main.tsx
Normal file
10
apps/browser-extension/entrypoints/popup/main.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App.js';
|
||||
import './style.css';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
69
apps/browser-extension/entrypoints/popup/style.css
Normal file
69
apps/browser-extension/entrypoints/popup/style.css
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
29
apps/browser-extension/package.json
Normal file
29
apps/browser-extension/package.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "Supermemory",
|
||||
"description": "supermemory",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "wxt --port 3001",
|
||||
"dev:firefox": "wxt -b firefox",
|
||||
"build": "wxt build",
|
||||
"build:firefox": "wxt build -b firefox",
|
||||
"zip": "wxt zip",
|
||||
"zip:firefox": "wxt zip -b firefox",
|
||||
"compile": "tsc --noEmit",
|
||||
"postinstall": "wxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chrome": "^0.1.4",
|
||||
"@types/react": "^19.1.2",
|
||||
"@types/react-dom": "^19.1.3",
|
||||
"@wxt-dev/module-react": "^1.1.3",
|
||||
"typescript": "^5.8.3",
|
||||
"wxt": "^0.20.6"
|
||||
}
|
||||
}
|
||||
BIN
apps/browser-extension/public/icon-128.png
Normal file
BIN
apps/browser-extension/public/icon-128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
apps/browser-extension/public/icon-16.png
Normal file
BIN
apps/browser-extension/public/icon-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
apps/browser-extension/public/icon-48.png
Normal file
BIN
apps/browser-extension/public/icon-48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
8
apps/browser-extension/tsconfig.json
Normal file
8
apps/browser-extension/tsconfig.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "./.wxt/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": true,
|
||||
"jsx": "react-jsx",
|
||||
"types": ["chrome"]
|
||||
}
|
||||
}
|
||||
18
apps/browser-extension/wxt.config.ts
Normal file
18
apps/browser-extension/wxt.config.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { defineConfig } from 'wxt';
|
||||
|
||||
// See https://wxt.dev/api/config.html
|
||||
export default defineConfig({
|
||||
modules: ['@wxt-dev/module-react'],
|
||||
manifest: {
|
||||
permissions: ['contextMenus', 'storage', 'scripting', 'activeTab'],
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ['icon-16.png'],
|
||||
matches: ['<all_urls>']
|
||||
}
|
||||
],
|
||||
},
|
||||
webExt: {
|
||||
chromiumArgs: ['--user-data-dir=./.wxt/chrome-data'],
|
||||
},
|
||||
});
|
||||
File diff suppressed because it is too large
Load diff
BIN
bun.lockb
Executable file
BIN
bun.lockb
Executable file
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "supermemory",
|
||||
"name": "supermemory-app",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue