feat: Complete Google Search Console integration with Clerk authentication

- Add GSC API service with OAuth2 authentication
- Implement Clerk authentication for frontend and backend
- Add GSC login button and OAuth callback handling
- Create comprehensive GSC data fetching and caching
- Add authentication middleware for backend API protection
- Implement real-time GSC data integration in SEO dashboard
- Add user-specific GSC site management
- Include comprehensive logging and error handling
- Add TypeScript support and proper type definitions
- Create environment templates and setup documentation
- Update gitignore to exclude sensitive credential files

Features added:
- GSC OAuth2 authentication flow
- Real-time search analytics data
- Site list management
- Sitemap analysis
- User-specific data isolation
- Comprehensive error handling
- Authentication token management
- Popup-based OAuth flow
- Data caching and refresh mechanisms

Note: gsc_credentials.json should be created locally with your Google OAuth credentials
This commit is contained in:
Om-Singh1808
2025-09-06 02:43:50 +05:30
committed by ي
parent aeb7751d48
commit 0a7d9bfd21
19 changed files with 1912 additions and 87 deletions

View File

@@ -11,6 +11,7 @@ import {
Button
} from '@mui/material';
import { motion, AnimatePresence } from 'framer-motion';
import { useAuth, useUser, SignInButton, SignOutButton } from '@clerk/clerk-react';
// Shared components
import { DashboardContainer, GlassCard } from '../shared/styled';
@@ -19,6 +20,9 @@ import { SEOCopilotKitProvider, SEOCopilotSuggestions } from './index';
// Removed SEOCopilotTest
import useSEOCopilotStore from '../../stores/seoCopilotStore';
// GSC Components
import GSCLoginButton from './components/GSCLoginButton';
// Zustand store
import { useSEODashboardStore } from '../../stores/seoDashboardStore';
@@ -29,6 +33,10 @@ import { userDataAPI } from '../../api/userData';
const SEODashboard: React.FC = () => {
const theme = useTheme();
// Clerk authentication hooks
const { isSignedIn, isLoaded } = useAuth();
const { user } = useUser();
// Zustand store hooks
const {
loading,
@@ -141,6 +149,52 @@ const SEODashboard: React.FC = () => {
return <Alert severity="error">Failed to load dashboard data</Alert>;
}
// Show sign-in prompt if not authenticated
if (!isLoaded) {
return <Skeleton variant="rectangular" height={200} />;
}
if (!isSignedIn) {
return (
<DashboardContainer>
<Container maxWidth="md">
<Box sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: '60vh',
textAlign: 'center',
gap: 3
}}>
<Typography variant="h4" sx={{ color: 'white', fontWeight: 700 }}>
🔍 SEO Dashboard
</Typography>
<Typography variant="h6" sx={{ color: 'rgba(255, 255, 255, 0.7)' }}>
Sign in to access your SEO analytics and Google Search Console data
</Typography>
<SignInButton mode="modal">
<Button
variant="contained"
size="large"
sx={{
bgcolor: '#4285f4',
'&:hover': { bgcolor: '#3367d6' },
px: 4,
py: 1.5,
fontSize: '1.1rem',
fontWeight: 600
}}
>
Sign In to Continue
</Button>
</SignInButton>
</Box>
</Container>
</DashboardContainer>
);
}
return (
<SEOCopilotKitProvider enableDebugMode={false}>
<DashboardContainer>
@@ -161,7 +215,38 @@ const SEODashboard: React.FC = () => {
AI-powered insights and actionable recommendations
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
{/* User Info */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Chip
label={`Signed in as ${user?.primaryEmailAddress?.emailAddress || 'User'}`}
size="small"
sx={{
bgcolor: 'rgba(76, 175, 80, 0.25)',
border: '1px solid rgba(76, 175, 80, 0.45)',
color: 'white',
fontWeight: 600
}}
/>
<SignOutButton>
<Button
variant="outlined"
size="small"
sx={{
borderColor: 'rgba(255, 255, 255, 0.3)',
color: 'white',
'&:hover': {
borderColor: 'rgba(255, 255, 255, 0.5)',
bgcolor: 'rgba(255, 255, 255, 0.1)'
}
}}
>
Sign Out
</Button>
</SignOutButton>
</Box>
{/* Freshness Indicator */}
{(() => {
const freshness = getAnalysisFreshness();
const chipColor = freshness.isStale ? 'rgba(255, 193, 7, 0.25)' : 'rgba(76, 175, 80, 0.25)';
@@ -195,6 +280,11 @@ const SEODashboard: React.FC = () => {
</Box>
</Box>
{/* GSC Connection Section */}
<Box sx={{ mb: 3 }}>
<GSCLoginButton />
</Box>
{/* CopilotKit Test Panel removed */}
{/* Executive Summary */}