Skip to content

Commit

Permalink
feat: update cache, and update UI a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
WomB0ComB0 committed Jan 20, 2025
1 parent d7dba8e commit 899b9da
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 34 deletions.
38 changes: 35 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ const config = {
value:
'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version',
},
{
key: 'Cache-Control',
value: 'no-cache, must-revalidate, max-age=0',
},
],
},
{
Expand Down Expand Up @@ -111,21 +115,25 @@ const withMillion = MillionLint.next({

const combinedConfig = withMillion(withBundleAnalyzerConfig(withPwa(config)));

export default withSentryConfig(combinedConfig, {
/** @type {import('@sentry/nextjs').SentryBuildOptions} */
const sentryConfig = {
org: 'womb0comb0',
project: 'portfolio',
authToken: process.env.SENTRY_AUTH_TOKEN,
silent: process.env.NODE_ENV === 'production',
release: {
name: process.env.VERCEL_GIT_COMMIT_SHA || 'local',
name: process.env.VERCEL_GIT_COMMIT_SHA || `local-${Date.now()}`,
create: true,
setCommits: {
auto: true,
ignoreMissing: true,
ignoreEmpty: true
},
},
sourcemaps: {
assets: './**/*.{js,map}',
ignore: ['node_modules/**/*'],
deleteSourcemapsAfterUpload: true
},
hideSourceMaps: true,
widenClientFileUpload: true,
Expand All @@ -138,4 +146,28 @@ export default withSentryConfig(combinedConfig, {
reactComponentAnnotation: {
enabled: true,
},
});
bundleSizeOptimizations: {
excludeDebugStatements: true,
excludeReplayShadowDom: true,
excludeReplayIframe: true,
excludeReplayWorker: true,
}
};

const withSentry =
process.env.NODE_ENV === 'production'
?
(
/** @type {import('next').NextConfig} */
config
) => withSentryConfig(
config,
sentryConfig
)
:
(
/** @type {import('next').NextConfig} */
config
) => config;

export default withSentry(combinedConfig);
9 changes: 9 additions & 0 deletions src/app/(routes)/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Layout from '@/components/layout/Layout';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Github, Linkedin, Mail } from 'lucide-react';
import { SiGooglescholar } from 'react-icons/si';
import Image from 'next/image';

export default function AboutPage() {
Expand Down Expand Up @@ -56,6 +57,14 @@ export default function AboutPage() {
>
<Mail className="h-5 w-5 text-purple-300" />
</Button>
<Button
variant="outline"
size="icon"
className="bg-purple-900 hover:bg-purple-800 border-purple-700"
onClick={() => window.open('https://scholar.google.com/citations?hl=en&authuser=1&user=P-wHEGsAAAAJ', '_blank')}
>
<SiGooglescholar className="h-5 w-5 text-purple-300" />
</Button>
</div>
</div>
</div>
Expand Down
51 changes: 33 additions & 18 deletions src/app/api/v1/google/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,54 @@ let cache: { data: any; timestamp: number } | null = null;

export async function GET() {
try {
// Check cache first
if (cache && Date.now() - cache.timestamp < CACHE_DURATION) {
return NextResponse.json(superjson.stringify(cache.data), {
headers: { 'Content-Type': 'application/json' },
});
}

const parsedResp = schema.safeParse(await getAnalytics());
// Add fallback data in case of errors
const fallbackData = {
analytics: {
total_pageviews: 0,
},
};

// console.log('api-google-analytics-parsedResp', parsedResp);
try {
const parsedResp = schema.safeParse(await getAnalytics());

if (!parsedResp.success) {
throw new Error(`
Umami API responded with status ${parsedResp.error}
`);
}
if (!parsedResp.success) {
console.warn('Failed to parse analytics response:', parsedResp.error);
return NextResponse.json(superjson.stringify(fallbackData.analytics), {
headers: { 'Content-Type': 'application/json' },
});
}

const analytics = parsedResp.data.analytics;
cache = { data: analytics, timestamp: Date.now() };
const analytics = parsedResp.data.analytics;
cache = { data: analytics, timestamp: Date.now() };

return NextResponse.json(superjson.stringify(analytics), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=1800',
},
});
return NextResponse.json(superjson.stringify(analytics), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=1800',
},
});
} catch (analyticsError) {
console.error('Error fetching analytics:', analyticsError);
return NextResponse.json(superjson.stringify(fallbackData.analytics), {
headers: { 'Content-Type': 'application/json' },
});
}
} catch (error) {
console.error('Error fetching Umami analytics:', error);
console.error('Error in Google Analytics route:', error);
return NextResponse.json(
superjson.stringify({
error: `${error instanceof Error ? error.message : ''}`,
total_pageviews: 0,
error: `${error instanceof Error ? error.message : 'Unknown error occurred'}`,
}),
{
status: 500,
status: 200,
headers: { 'Content-Type': 'application/json' },
},
);
Expand Down
15 changes: 13 additions & 2 deletions src/app/api/v1/now-playing/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ export async function GET() {
const response = await currentlyPlayingSong();

if (!response || !response.is_playing) {
return NextResponse.json({ isPlaying: false });
return NextResponse.json(
{ isPlaying: false },
{
headers: {
'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
}
);
}

const song = {
Expand All @@ -27,7 +34,11 @@ export async function GET() {
};

const validatedSong = schema.parse(song);
return NextResponse.json(validatedSong);
return NextResponse.json(validatedSong, {
headers: {
'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
});
} catch (error) {
console.error('Error in now-playing API route:', error);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
Expand Down
13 changes: 9 additions & 4 deletions src/app/api/v1/top-artists/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ let cache: { data: any; timestamp: number } | null = null;

export async function GET() {
try {
if (cache && Date.now() - cache.timestamp < CACHE_DURATION) {
const now = Date.now();
const shouldRevalidate = !cache || (now - cache.timestamp > CACHE_DURATION);

if (!shouldRevalidate && cache) {
return NextResponse.json(superjson.stringify(cache.data), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=43200',

'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
});
}
Expand All @@ -34,12 +38,13 @@ export async function GET() {
imageUrl: artist.images[0]?.url,
}));

cache = { data: topArtists, timestamp: Date.now() };
cache = { data: topArtists, timestamp: now };

return NextResponse.json(superjson.stringify(topArtists), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=43200',

'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
});
} catch (error) {
Expand Down
14 changes: 10 additions & 4 deletions src/app/api/v1/top-tracks/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ let cache: { data: any; timestamp: number } | null = null;

export async function GET() {
try {
if (cache && Date.now() - cache.timestamp < CACHE_DURATION) {
const now = Date.now();
const shouldRevalidate = !cache || (now - cache.timestamp > CACHE_DURATION);

if (!shouldRevalidate && cache) {
return NextResponse.json(superjson.stringify(cache.data), {
headers: { 'Content-Type': 'application/json' },
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
});
}

Expand All @@ -33,12 +39,12 @@ export async function GET() {
imageUrl: track.album.images?.[0]?.url,
}));

cache = { data: topTracks, timestamp: Date.now() };
cache = { data: topTracks, timestamp: now };

return NextResponse.json(superjson.stringify(topTracks), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=43200',
'Cache-Control': 'no-cache, must-revalidate, max-age=0',
},
});
} catch (error) {
Expand Down
5 changes: 5 additions & 0 deletions src/data/places.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export const places: RawPlace[] = [
['DivHacks - 2024', 'Mentor/Judge', 40.807537, -73.96257],
['MHacks - 2024', 'Mentor/Judge', 42.291160, -83.715830],
['Hack Dearborn 3: Rewind Reality - 2024', 'Volunteer', 42.317220, -83.230400],
['Googly DevFest NYC 2024', 'Attendee',40.743661, -74.009000],
['HackRU - Fall - 2024', 'Mentor/Hacker', 40.500820, -74.447395],
['HackPrinceton - Fall -2024', 'Hacker', 40.350292, -74.652831],
['IEEE LISAT 2024', 'Research presenter', 40.819012, -73.068539],
['Google and Palo Alto Networks Cloud Hero Event', 'Attendee', 40.727630, -74.009924],
];

export default places;
Expand Down
29 changes: 28 additions & 1 deletion src/lib/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,37 @@ export async function getAnalytics(): Promise<{
analytics: { total_pageviews: number };
response: GAResponse;
}> {
if (process.env.NODE_ENV === 'development' || process.env.FIREBASE_AUTH_EMULATOR_HOST) {
return {
analytics: { total_pageviews: 0 },
response: {
dimensionHeaders: [],
metricHeaders: [],
rows: [],
rowCount: 0,
kind: 'analyticsData#runReport',
totals: [],
maximums: [],
minimums: [],
metadata: {
samplingMetadatas: [],
dataLossFromOtherRow: false,
currencyCode: '',
_currencyCode: 'currencyCode',
timeZone: '',
_timeZone: 'timeZone',
},
propertyQuota: null,
} satisfies GAResponse,
};
}

const formattedPrivateKey = serviceAccount.private_key.replace(/\\n/g, '\n');

const client = new BetaAnalyticsDataClient({
credentials: {
client_email: serviceAccount.client_email,
private_key: serviceAccount.private_key,
private_key: formattedPrivateKey,
},
});

Expand Down
4 changes: 2 additions & 2 deletions src/lib/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
SiLeetcode,
SiLinkedin,
SiMedium,
SiMicrosoft,
SiSpotify,
SiX,
} from 'react-icons/si';
import { FaMicrosoft } from 'react-icons/fa';
import { SiSololearn } from 'react-icons/si';
import { SlGraph } from 'react-icons/sl';

Expand Down Expand Up @@ -107,7 +107,7 @@ export const links: Links = [
name: 'Microsoft Learn',
url: 'https://learn.microsoft.com/en-us/users/mikeodnis-1859/',
value: '@mikeodnis-1859',
icon: SiMicrosoft,
icon: FaMicrosoft,
},
{
name: 'SoloLearn',
Expand Down

0 comments on commit 899b9da

Please sign in to comment.