diff --git a/packages/web/src/components/ProfileSidebar.tsx b/packages/web/src/components/ProfileSidebar.tsx
index 687a3458..c64e2653 100644
--- a/packages/web/src/components/ProfileSidebar.tsx
+++ b/packages/web/src/components/ProfileSidebar.tsx
@@ -1,4 +1,4 @@
-import { ExternalLink, MapPin, Calendar, Users } from "lucide-react"
+import { ExternalLink, MapPin, Calendar } from "lucide-react"
interface ProfileSidebarProps {
user: {
@@ -12,11 +12,10 @@ interface ProfileSidebarProps {
joinedAt?: string | null
}
isLive?: boolean
- viewerCount?: number
children?: React.ReactNode
}
-export function ProfileSidebar({ user, isLive, viewerCount, children }: ProfileSidebarProps) {
+export function ProfileSidebar({ user, isLive, children }: ProfileSidebarProps) {
const displayName = user.name || user.username
return (
@@ -70,15 +69,6 @@ export function ProfileSidebar({ user, isLive, viewerCount, children }: ProfileS
)}
- {/* Stats */}
- {isLive && viewerCount !== undefined && (
-
-
-
- {viewerCount} watching
-
-
- )}
{/* Children (Chat, etc.) */}
diff --git a/packages/web/src/lib/jazz/schema.ts b/packages/web/src/lib/jazz/schema.ts
index 108c6a1d..c31ad742 100644
--- a/packages/web/src/lib/jazz/schema.ts
+++ b/packages/web/src/lib/jazz/schema.ts
@@ -166,6 +166,23 @@ export const CloudflareStreamConfig = co.map({
})
export type CloudflareStreamConfig = co.loaded
+/**
+ * Stream filter configuration - dynamically controls what apps are captured
+ */
+export const StreamFilterConfig = co.map({
+ /** Apps allowed to appear in stream (empty = all allowed) */
+ allowedApps: z.array(z.string()),
+ /** Apps blocked from stream (takes precedence over allowed) */
+ blockedApps: z.array(z.string()),
+ /** Apps to capture audio from */
+ audioApps: z.array(z.string()),
+ /** Last updated timestamp */
+ updatedAt: z.number(),
+ /** Version number for change tracking */
+ version: z.number(),
+})
+export type StreamFilterConfig = co.loaded
+
/**
* Viewer account root - stores any viewer-specific data
*/
@@ -180,6 +197,8 @@ export const ViewerRoot = co.map({
streamRecordings: StreamRecordingList,
/** Cloudflare Stream configuration */
cloudflareConfig: co.optional(CloudflareStreamConfig),
+ /** Stream filter configuration (allowed/blocked apps) */
+ streamFilter: co.optional(StreamFilterConfig),
})
/**
diff --git a/packages/web/src/routes/$username.tsx b/packages/web/src/routes/$username.tsx
index d2a7524d..c938f66b 100644
--- a/packages/web/src/routes/$username.tsx
+++ b/packages/web/src/routes/$username.tsx
@@ -265,7 +265,6 @@ function StreamPage() {
@@ -336,7 +335,6 @@ function StreamPage() {
diff --git a/packages/web/src/routes/api/stream-filter.ts b/packages/web/src/routes/api/stream-filter.ts
new file mode 100644
index 00000000..e919df02
--- /dev/null
+++ b/packages/web/src/routes/api/stream-filter.ts
@@ -0,0 +1,47 @@
+import { json } from "@tanstack/react-start"
+import type { APIContext } from "@tanstack/react-router"
+
+/**
+ * Get or update stream filter configuration (allowed/blocked apps)
+ *
+ * GET: Returns current filter config from Jazz (or hardcoded default)
+ * PUT: Updates filter config in Jazz
+ */
+
+// Hardcoded default for nikiv (will be in Jazz later)
+const DEFAULT_FILTER = {
+ allowedApps: ["zed", "cursor", "xcode", "safari", "warp", "warpPreview"],
+ blockedApps: ["1password", "keychain", "telegram"],
+ audioApps: ["spotify", "arc"],
+ version: 1,
+ updatedAt: Date.now(),
+}
+
+export async function GET({ request }: APIContext) {
+ try {
+ // TODO: Read from Jazz when worker is set up
+ return json(DEFAULT_FILTER)
+ } catch (error) {
+ return json({ error: "Failed to fetch filter config" }, { status: 500 })
+ }
+}
+
+export async function PUT({ request }: APIContext) {
+ try {
+ const body = await request.json()
+ const { allowedApps, blockedApps, audioApps } = body
+
+ // TODO: Write to Jazz when worker is set up
+ // For now, return the updated config
+ return json({
+ success: true,
+ allowedApps: allowedApps || [],
+ blockedApps: blockedApps || [],
+ audioApps: audioApps || [],
+ version: DEFAULT_FILTER.version + 1,
+ updatedAt: Date.now(),
+ })
+ } catch (error) {
+ return json({ error: "Failed to update filter config" }, { status: 500 })
+ }
+}