diff --git a/index.html b/index.html
index 11ec774..2c102fc 100644
--- a/index.html
+++ b/index.html
@@ -6,6 +6,7 @@
+
diff --git a/src/automerge/useAutomergeStoreV2.ts b/src/automerge/useAutomergeStoreV2.ts
index 61cc14f..33a1182 100644
--- a/src/automerge/useAutomergeStoreV2.ts
+++ b/src/automerge/useAutomergeStoreV2.ts
@@ -134,8 +134,14 @@ import { MycelialIntelligenceShape } from "@/shapes/MycelialIntelligenceShapeUti
import { MapShape } from "@/shapes/MapShapeUtil"
// Calendar shape for calendar functionality
import { CalendarShape } from "@/shapes/CalendarShapeUtil"
+import { CalendarEventShape } from "@/shapes/CalendarEventShapeUtil"
// Drawfast shape for quick drawing/sketching
import { DrawfastShape } from "@/shapes/DrawfastShapeUtil"
+// Additional shapes from Board.tsx
+import { HolonBrowserShape } from "@/shapes/HolonBrowserShapeUtil"
+import { PrivateWorkspaceShape } from "@/shapes/PrivateWorkspaceShapeUtil"
+import { GoogleItemShape } from "@/shapes/GoogleItemShapeUtil"
+import { WorkflowBlockShape } from "@/shapes/WorkflowBlockShapeUtil"
export function useAutomergeStoreV2({
handle,
@@ -174,7 +180,12 @@ export function useAutomergeStoreV2({
MycelialIntelligenceShape, // Deprecated - kept for backwards compatibility
MapShape, // Open Mapping - OSM map shape
CalendarShape, // Calendar with view switching
+ CalendarEventShape, // Calendar individual events
DrawfastShape, // Drawfast quick sketching
+ HolonBrowserShape, // Holon browser
+ PrivateWorkspaceShape, // Private workspace for Google Export
+ GoogleItemShape, // Individual Google items
+ WorkflowBlockShape, // Workflow builder blocks
]
// CRITICAL: Explicitly list ALL custom shape types to ensure they're registered
@@ -200,7 +211,12 @@ export function useAutomergeStoreV2({
'MycelialIntelligence', // Deprecated - kept for backwards compatibility
'Map', // Open Mapping - OSM map shape
'Calendar', // Calendar with view switching
+ 'CalendarEvent', // Calendar individual events
'Drawfast', // Drawfast quick sketching
+ 'HolonBrowser', // Holon browser
+ 'PrivateWorkspace', // Private workspace for Google Export
+ 'GoogleItem', // Individual Google items
+ 'WorkflowBlock', // Workflow builder blocks
]
// Build schema with explicit entries for all custom shapes
diff --git a/src/components/auth/CryptIDDropdown.tsx b/src/components/auth/CryptIDDropdown.tsx
index b717943..3b76de5 100644
--- a/src/components/auth/CryptIDDropdown.tsx
+++ b/src/components/auth/CryptIDDropdown.tsx
@@ -124,7 +124,10 @@ const CryptIDDropdown: React.FC = ({ isDarkMode = false })
const myConnections = await getMyConnections();
setConnections(myConnections as UserConnectionWithProfile[]);
} catch (error) {
- console.error('Failed to load connections:', error);
+ // Don't log as error - this is expected when worker isn't running
+ if (import.meta.env.DEV) {
+ console.warn('Connections API unavailable (worker may not be running)');
+ }
setConnections([]); // Clear on error too
} finally {
setConnectionsLoading(false);
diff --git a/src/lib/networking/connectionService.ts b/src/lib/networking/connectionService.ts
index 9b03a29..bca7568 100644
--- a/src/lib/networking/connectionService.ts
+++ b/src/lib/networking/connectionService.ts
@@ -68,9 +68,22 @@ async function fetchJson(url: string, options?: RequestInit): Promise {
headers,
});
+ // Check content type to ensure we're getting JSON
+ const contentType = response.headers.get('content-type') || '';
+ const isJson = contentType.includes('application/json');
+
if (!response.ok) {
- const errorData = await response.json().catch(() => ({ message: response.statusText })) as { message?: string };
- throw new Error(errorData.message || `HTTP ${response.status}`);
+ if (isJson) {
+ const errorData = await response.json().catch(() => ({ message: response.statusText })) as { message?: string };
+ throw new Error(errorData.message || `HTTP ${response.status}`);
+ }
+ // If we got HTML (like a 404 page), throw a more descriptive error
+ throw new Error(`API unavailable (HTTP ${response.status}). Is the worker running?`);
+ }
+
+ // Ensure we're getting JSON before parsing
+ if (!isJson) {
+ throw new Error('API returned non-JSON response. Is the worker running on port 5172?');
}
return response.json();
diff --git a/src/public/manifest.webmanifest b/src/public/manifest.webmanifest
new file mode 100644
index 0000000..d690898
--- /dev/null
+++ b/src/public/manifest.webmanifest
@@ -0,0 +1,29 @@
+{
+ "name": "Jeff Emmett Canvas",
+ "short_name": "Canvas",
+ "description": "Collaborative canvas for research and creativity",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#1a1a2e",
+ "theme_color": "#1a1a2e",
+ "lang": "en",
+ "scope": "/",
+ "icons": [
+ {
+ "src": "/pwa-192x192.svg",
+ "sizes": "192x192",
+ "type": "image/svg+xml"
+ },
+ {
+ "src": "/pwa-512x512.svg",
+ "sizes": "512x512",
+ "type": "image/svg+xml"
+ },
+ {
+ "src": "/pwa-512x512.svg",
+ "sizes": "512x512",
+ "type": "image/svg+xml",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/vite.config.ts b/vite.config.ts
index 0d94e02..dc42f59 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,21 +8,9 @@ export default defineConfig(({ mode }) => {
// Load env file based on `mode` in the current working directory.
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
const env = loadEnv(mode, process.cwd(), '')
-
- // Debug: Log what we're getting
- console.log('🔧 Vite config - Environment variables:')
- console.log('Mode:', mode)
- console.log('WSL2_IP from env:', process.env.WSL2_IP)
- console.log('process.env.VITE_TLDRAW_WORKER_URL:', process.env.VITE_TLDRAW_WORKER_URL)
- console.log('env.VITE_TLDRAW_WORKER_URL:', env.VITE_TLDRAW_WORKER_URL)
- // Get the WSL2 IP for HMR configuration
- const wslIp = process.env.WSL2_IP || '172.22.168.84'
-
// Set the worker URL to localhost for local development
- const workerUrl = 'http://localhost:5172'
- process.env.VITE_TLDRAW_WORKER_URL = workerUrl
- console.log('🌐 Setting worker URL to:', workerUrl)
+ process.env.VITE_TLDRAW_WORKER_URL = 'http://localhost:5172'
return {
envPrefix: ["VITE_"],