···77 // We need to specify which pages need to be dynamic
88 // to prevent build errors with pages that use client-side features
99 output: 'standalone',
1010+1111+ // Configure static generation behavior
1212+ experimental: {
1313+ // This ensures packages with browser APIs are treated properly
1414+ serverComponentsExternalPackages: ['@supabase/supabase-js', '@atproto/api'],
1515+ },
1616+1717+ // Make sure all API routes are generated with server-side functionality
1818+ serverActions: {
1919+ bodySizeLimit: '2mb',
2020+ }
1021};
11221223module.exports = nextConfig;
+3
app/src/app/api/auth/nonce/route.ts
···11import { NextRequest, NextResponse } from 'next/server';
2233+// Configure this route as dynamic to fix static generation issues
44+export const dynamic = 'force-dynamic';
55+36const DEFAULT_AUTH_SERVER = 'https://bsky.social';
4758export async function POST(request: NextRequest) {
+3
app/src/app/api/auth/token/route.ts
···11import { NextRequest, NextResponse } from 'next/server';
2233+// Configure this route as dynamic to fix static generation issues
44+export const dynamic = 'force-dynamic';
55+36const DEFAULT_AUTH_SERVER = 'https://bsky.social';
47const REDIRECT_URI = 'https://flushing.im/auth/callback';
58const CLIENT_ID = 'https://flushing.im/client-metadata.json';
+3
app/src/app/api/bluesky/feed/route.ts
···33import { BskyAgent } from '@atproto/api';
44import { containsBannedWords, sanitizeText } from '@/lib/content-filter';
5566+// Configure this route as dynamic to fix static generation issues
77+export const dynamic = 'force-dynamic';
88+69// Define type for our database entry
710interface FlushingRecord {
811 id: string | number;
+3
app/src/app/api/bluesky/flushing/route.ts
···11import { NextRequest, NextResponse } from 'next/server';
22import { containsBannedWords, sanitizeText } from '@/lib/content-filter';
3344+// Configure this route as dynamic to fix static generation issues
55+export const dynamic = 'force-dynamic';
66+47// This is the default API URL, but we'll use the user's PDS endpoint instead if available
58const DEFAULT_API_URL = 'https://bsky.social/xrpc';
69const FLUSHING_STATUS_NSID = 'im.flushing.right.now';
+3
app/src/app/api/bluesky/profile/route.ts
···11import { NextRequest, NextResponse } from 'next/server';
22import { createClient } from '@supabase/supabase-js';
33+44+// Configure this route as dynamic to fix static generation issues
55+export const dynamic = 'force-dynamic';
36import { containsBannedWords, sanitizeText } from '@/lib/content-filter';
4758// Define interfaces for type safety
+3
app/src/app/api/bluesky/stats/route.ts
···11import { NextRequest, NextResponse } from 'next/server';
22import { createClient } from '@supabase/supabase-js';
3344+// Configure this route as dynamic to fix static generation issues
55+export const dynamic = 'force-dynamic';
66+47// Supabase client - using environment variables
58const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || '';
69const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY || '';
+7-1
app/src/app/layout.tsx
···33import { AuthProvider } from '@/lib/auth-context';
44import { ThemeProvider } from '@/lib/theme-context';
55import ThemeToggle from '@/components/ThemeToggle';
66+import ClientOnly from '@/components/ClientOnly';
77+88+// Configure this layout as having dynamic runtime to fix SSR issues with theme
99+export const dynamic = 'force-dynamic';
610711export const metadata: Metadata = {
812 title: "im.flushing",
···4852 backgroundColor: 'var(--card-background)',
4953 borderBottom: '1px solid var(--tile-border)'
5054 }}>
5151- <ThemeToggle />
5555+ <ClientOnly>
5656+ <ThemeToggle />
5757+ </ClientOnly>
5258 </header>
5359 <main>{children}</main>
5460 </ThemeProvider>
+26
app/src/components/ClientOnly.tsx
···11+'use client';
22+33+import React, { useState, useEffect, ReactNode } from 'react';
44+55+interface ClientOnlyProps {
66+ children: ReactNode;
77+ fallback?: ReactNode;
88+}
99+1010+/**
1111+ * A wrapper component that only renders its children on the client side.
1212+ * This helps prevent hydration errors when components use browser-only APIs.
1313+ */
1414+export default function ClientOnly({ children, fallback = null }: ClientOnlyProps) {
1515+ const [mounted, setMounted] = useState(false);
1616+1717+ useEffect(() => {
1818+ setMounted(true);
1919+ }, []);
2020+2121+ if (!mounted) {
2222+ return <>{fallback}</>;
2323+ }
2424+2525+ return <>{children}</>;
2626+}