diff --git a/README.md b/README.md
index 162846e8..ed98ff26 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,9 @@
-
-
-
+
+
+
diff --git a/next.config.ts b/next.config.ts
index 2c23b68a..85f78eb8 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -2,7 +2,6 @@ import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
/* config options here */
- output: 'export',
devIndicators: {
// @ts-ignore - buildActivity is valid but missing in type definition
buildActivity: false,
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index 0f8810f8..63ec86e3 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -28,7 +28,7 @@ import AdminKeyModal from '@/components/auth/AdminKeyModal';
import { useAuth } from '@/context/AuthContext';
import { useNotificationActions } from '@/stores/ui-store';
import { useMaintenance } from '@/hooks/useMaintenance';
-import { auth, db } from '@/lib/firebase';
+import { auth, db, isFirebaseConfigured } from '@/lib/firebase';
export default function LoginPage() {
const [email, setEmail] = useState('');
@@ -113,6 +113,15 @@ export default function LoginPage() {
setIsCheckingAdmin(true);
try {
+ if (!isFirebaseConfigured) {
+ const message =
+ 'Login is temporarily unavailable because Firebase is not configured.';
+ setError(message);
+ showError(message);
+ setIsCheckingAdmin(false);
+ return;
+ }
+
await login(normalizedEmail, password);
const adminDoc = await getDoc(doc(db, 'admins', normalizedEmail));
@@ -168,6 +177,15 @@ export default function LoginPage() {
setIsCheckingAdmin(true);
try {
+ if (!isFirebaseConfigured) {
+ const message =
+ 'Sign-in is temporarily unavailable because Firebase is not configured.';
+ setError(message);
+ showError(message);
+ setIsCheckingAdmin(false);
+ return;
+ }
+
const provider =
providerName === 'google'
? new GoogleAuthProvider()
diff --git a/src/app/profile/[username]/page.tsx b/src/app/profile/[username]/page.tsx
index ec4b3ee9..689cd30f 100644
--- a/src/app/profile/[username]/page.tsx
+++ b/src/app/profile/[username]/page.tsx
@@ -3,7 +3,9 @@
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
+import { collection, getDocs, query, where } from 'firebase/firestore';
import { getPublicProfileByUsername } from '@/lib/portfolio-service';
+import { db, isFirebaseConfigured } from '@/lib/firebase';
import { ProfileHeader } from '@/components/profile/ProfileHeader';
import { PathProgressSection } from '@/components/profile/PathProgressSection';
import { SkillBadgesSection } from '@/components/profile/SkillBadgesSection';
@@ -14,9 +16,35 @@ interface Props {
params: { username: string };
}
+export const dynamicParams = false;
+
+export async function generateStaticParams() {
+ if (!isFirebaseConfigured) return [];
+
+ try {
+ const profilesQuery = query(
+ collection(db, 'portfolios'),
+ where('isPublic', '==', true)
+ );
+ const snapshot = await getDocs(profilesQuery);
+
+ return snapshot.docs
+ .map((profileDoc) => profileDoc.data().username)
+ .filter((username): username is string => Boolean(username))
+ .map((username) => ({ username }));
+ } catch {
+ return [];
+ }
+}
+
// Generate OpenGraph metadata dynamically
-export async function generateMetadata({ params }: Props): Promise {
- const profile = await getPublicProfileByUsername(params.username);
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ username: string }>;
+}): Promise {
+ const { username } = await params;
+ const profile = await getPublicProfileByUsername(username);
if (!profile) return { title: 'Profile not found' };
return {
@@ -30,8 +58,13 @@ export async function generateMetadata({ params }: Props): Promise {
};
}
-export default async function PublicProfilePage({ params }: Props) {
- const profile = await getPublicProfileByUsername(params.username);
+export default async function PublicProfilePage({
+ params,
+}: {
+ params: Promise<{ username: string }>;
+}) {
+ const { username } = await params;
+ const profile = await getPublicProfileByUsername(username);
if (!profile) notFound();
diff --git a/src/lib/firebase.ts b/src/lib/firebase.ts
index 146c99c9..6801dc78 100644
--- a/src/lib/firebase.ts
+++ b/src/lib/firebase.ts
@@ -3,67 +3,53 @@ import { getAnalytics, isSupported } from 'firebase/analytics';
import { getFirestore, Firestore } from 'firebase/firestore';
import { getAuth, Auth } from 'firebase/auth';
-const isProduction = process.env.NODE_ENV === 'production';
-
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
+ appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
+ measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
-// Production Safety Guard
-if (isProduction) {
- const missingKeys = Object.entries(firebaseConfig)
- .filter(([_, value]) => !value)
- .map(([key]) => key);
-
- if (missingKeys.length > 0) {
- throw new Error(
- `Production Deployment Error: Missing required Firebase environment variables: ${missingKeys.join(', ')}`
- );
- }
-} else {
- // Safe Mock Fallbacks strictly for local development/testing only
- firebaseConfig.apiKey =
- firebaseConfig.apiKey || 'mock-api-key-for-local-testing-only-123456';
- firebaseConfig.authDomain =
- firebaseConfig.authDomain || 'mock-app.firebaseapp.com';
- firebaseConfig.projectId = firebaseConfig.projectId || 'mock-app-id';
- firebaseConfig.storageBucket =
- firebaseConfig.storageBucket || 'mock-app.appspot.com';
- firebaseConfig.messagingSenderId =
- firebaseConfig.messagingSenderId || '1234567890';
-}
-
-const isFirebaseConfigValid = Boolean(
+const isFirebaseConfigured = Boolean(
firebaseConfig.apiKey &&
firebaseConfig.authDomain &&
firebaseConfig.projectId &&
firebaseConfig.storageBucket &&
- firebaseConfig.messagingSenderId
+ firebaseConfig.messagingSenderId &&
+ firebaseConfig.appId
);
-const app: FirebaseApp | null = isFirebaseConfigValid
+const app: FirebaseApp | null = isFirebaseConfigured
? !getApps().length
? initializeApp(firebaseConfig)
: getApp()
: null;
-if (!app) {
- console.warn(
- 'Firebase is not configured. Running in local UI-only mode without Firebase auth or Firestore.'
- );
-}
-
-// For build-time typing we export `db` as a Firestore instance. At runtime
-// `app` may be null when Firebase isn't configured; in that case we provide
-// a minimal cast to satisfy TypeScript while keeping runtime behavior safe.
const db: Firestore = app
? (getFirestore(app) as Firestore)
: (null as unknown as Firestore);
const auth: Auth = app ? (getAuth(app) as Auth) : ({} as Auth);
const firebaseAvailable = Boolean(app);
-export { db, auth, firebaseAvailable, firebaseConfig };
+let analytics;
+
+if (app && typeof window !== 'undefined') {
+ isSupported().then((supported) => {
+ if (supported) {
+ analytics = getAnalytics(app);
+ }
+ });
+}
+
+export {
+ app,
+ analytics,
+ db,
+ auth,
+ firebaseAvailable,
+ firebaseConfig,
+ isFirebaseConfigured,
+};