user app publishing system — build, serve, and use personal apps in workspace panels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 17:23:24 +00:00
co-authored by Claude Opus 4.6
parent 4d30672adb
commit fd4d77a389
17 changed files with 873 additions and 48 deletions
+2
View File
@@ -14,3 +14,5 @@ export type { ResourceSummary, ResourceDetail, PingResult } from './useResources
export { useChatSessions } from './useChatSessions';
export type { UseChatSessionsType } from './useChatSessions';
export { useChatGroups } from './useChatGroups';
export { useUserApps } from './useUserApps';
export type { AppManifest } from './useUserApps';
+34
View File
@@ -0,0 +1,34 @@
import { useAuth } from 'hooks/useAuth';
import { useClient } from 'hooks/useClient';
import { useQuery, useQueryClient } from '@tanstack/react-query';
export type AppManifest = {
slug: string;
name: string;
version: string;
icon: string;
description: string;
sourceProject: string;
commitHash: string;
publishedAt: string;
buildDir: string;
};
const QUERY_KEY = ['USER_APPS'] as const;
export function useUserApps() {
const client = useClient();
const queryClient = useQueryClient();
const { user, isAuthenticated } = useAuth();
const { data: apps = [], isLoading } = useQuery<AppManifest[]>({
queryKey: QUERY_KEY,
enabled: isAuthenticated,
queryFn: () => client.get<{ apps: AppManifest[] }>('/apps').then((r) => r.apps),
staleTime: 30_000,
});
const refetch = () => queryClient.invalidateQueries({ queryKey: QUERY_KEY });
return { apps, isLoading, refetch, email: user?.email ?? '' };
}