Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions frontend/actions/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use server';

import { and,desc, eq } from 'drizzle-orm';
import { revalidatePath } from 'next/cache';

import { db } from '@/db';
import { notifications } from '@/db/schema/notifications';
Expand Down Expand Up @@ -39,7 +38,6 @@ export async function markAsRead(notificationId: string) {
)
);

revalidatePath('/', 'layout');
return { success: true };
} catch (error) {
console.error('Failed to mark notification as read:', error);
Expand All @@ -57,7 +55,6 @@ export async function markAllAsRead() {
.set({ isRead: true })
.where(and(eq(notifications.userId, session.id), eq(notifications.isRead, false)));

revalidatePath('/', 'layout');
return { success: true };
} catch (error) {
console.error('Failed to mark all notifications as read:', error);
Expand Down Expand Up @@ -86,7 +83,6 @@ export async function createNotification(data: {
})
.returning();

revalidatePath('/', 'layout');
return result;
} catch (error) {
console.error('Failed to create notification:', error);
Expand Down
22 changes: 8 additions & 14 deletions frontend/app/[locale]/blog/[slug]/PostDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { Link } from '@/i18n/routing';
import { formatBlogDate } from '@/lib/blog/date';
import { shouldBypassImageOptimization } from '@/lib/blog/image';

export const revalidate = 0;

type SocialLink = {
_key?: string;
platform?: string;
Expand Down Expand Up @@ -383,18 +381,14 @@ export default async function PostDetails({
const slugParam = String(slug || '').trim();
if (!slugParam) return notFound();

const post: Post | null = await client
.withConfig({ useCdn: false })
.fetch(query, {
slug: slugParam,
locale,
});
const recommendedAll: Post[] = await client
.withConfig({ useCdn: false })
.fetch(recommendedQuery, {
slug: slugParam,
locale,
});
const post: Post | null = await client.fetch(query, {
slug: slugParam,
locale,
});
const recommendedAll: Post[] = await client.fetch(recommendedQuery, {
slug: slugParam,
locale,
});
const recommendedPosts = seededShuffle(
recommendedAll,
hashString(slugParam)
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/[locale]/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { client } from '@/client';

import PostDetails from './PostDetails';

export const revalidate = 3600;

export async function generateStaticParams() {
const slugs = await client.fetch<string[]>(
groq`*[_type == "post" && defined(slug.current)][].slug.current`
Expand Down
8 changes: 3 additions & 5 deletions frontend/app/[locale]/blog/category/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Link } from '@/i18n/routing';
import { formatBlogDate } from '@/lib/blog/date';
import { shouldBypassImageOptimization } from '@/lib/blog/image';

export const revalidate = 0;
export const revalidate = 3600;

type Author = {
name?: string;
Expand Down Expand Up @@ -50,9 +50,7 @@ export default async function BlogCategoryPage({
const t = await getTranslations({ locale, namespace: 'blog' });
const tNav = await getTranslations({ locale, namespace: 'navigation' });
const categoryKey = String(category || '').toLowerCase();
const categories: Category[] = await client
.withConfig({ useCdn: false })
.fetch(categoriesQuery);
const categories: Category[] = await client.fetch(categoriesQuery);
const matchedCategory = categories.find(
item => slugify(item.title) === categoryKey
);
Expand All @@ -61,7 +59,7 @@ export default async function BlogCategoryPage({
const categoryTitle = matchedCategory.title;
const categoryDisplay = getCategoryLabel(categoryTitle, t);

const posts: Post[] = await client.withConfig({ useCdn: false }).fetch(
const posts: Post[] = await client.fetch(
groq`
*[_type == "post" && defined(slug.current) && $category in categories[]->title]
| order(coalesce(publishedAt, _createdAt) desc) {
Expand Down
17 changes: 4 additions & 13 deletions frontend/app/[locale]/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import groq from 'groq';
import { unstable_noStore as noStore } from 'next/cache';
import { getTranslations } from 'next-intl/server';

import { client } from '@/client';
import BlogFilters from '@/components/blog/BlogFilters';
import { BlogPageHeader } from '@/components/blog/BlogPageHeader';
import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground';

export const revalidate = 0;
export const revalidate = 3600;
Comment thread
ViktorSvertoka marked this conversation as resolved.

export async function generateMetadata({
params,
Expand All @@ -25,19 +24,13 @@ export async function generateMetadata({

export default async function BlogPage({
params,
searchParams,
}: {
params: Promise<{ locale: string }>;
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
noStore();
const { locale } = await params;
const t = await getTranslations({ locale, namespace: 'blog' });
const sp = searchParams ? await searchParams : undefined;
const authorParam = typeof sp?.author === 'string' ? sp.author.trim() : '';
const hasAuthorFilter = authorParam.length > 0;

const posts = await client.withConfig({ useCdn: false }).fetch(
const posts = await client.fetch(
groq`
*[_type == "post" && defined(slug.current)]
| order(coalesce(publishedAt, _createdAt) desc) {
Expand Down Expand Up @@ -74,7 +67,7 @@ export default async function BlogPage({
`,
{ locale }
);
const categories = await client.withConfig({ useCdn: false }).fetch(
const categories = await client.fetch(
groq`
*[_type == "category"] | order(orderRank asc) {
_id,
Expand All @@ -87,9 +80,7 @@ export default async function BlogPage({
return (
<DynamicGridBackground className="bg-gray-50 py-10 transition-colors duration-300 dark:bg-transparent">
<main className="relative z-10 mx-auto max-w-7xl px-4 pt-6 pb-12 sm:px-6 lg:px-8">
{!hasAuthorFilter && (
<BlogPageHeader title={t('title')} subtitle={t('subtitle')} />
)}
<BlogPageHeader title={t('title')} subtitle={t('subtitle')} />
<BlogFilters
posts={posts}
categories={categories}
Expand Down
24 changes: 14 additions & 10 deletions frontend/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import groq from 'groq';
import { unstable_cache } from 'next/cache';
import { notFound } from 'next/navigation';
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';
Expand All @@ -17,6 +18,18 @@ import { getCurrentUser } from '@/lib/auth';

export const dynamic = 'force-dynamic';

const getCachedBlogCategories = unstable_cache(
async () =>
client.fetch<Array<{ _id: string; title: string }>>(groq`
*[_type == "category"] | order(orderRank asc) {
_id,
title
}
`),
['blog-categories'],
{ revalidate: 3600, tags: ['blog-categories'] }
);

export default async function LocaleLayout({
children,
params,
Expand All @@ -30,16 +43,7 @@ export default async function LocaleLayout({

const messages = await getMessages({ locale });
const user = await getCurrentUser();
const blogCategories: Array<{ _id: string; title: string }> = await client
.withConfig({ useCdn: false })
.fetch(
groq`
*[_type == "category"] | order(orderRank asc) {
_id,
title
}
`
);
const blogCategories = await getCachedBlogCategories();

const userExists = Boolean(user);
const enableAdmin =
Expand Down
4 changes: 1 addition & 3 deletions frontend/app/api/blog-author/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ export async function GET(request: Request) {
return NextResponse.json(null, { status: 400 });
}

const author = await client
.withConfig({ useCdn: false })
.fetch(authorQuery, { name, locale });
const author = await client.fetch(authorQuery, { name, locale });

return NextResponse.json(author || null, {
headers: { 'Cache-Control': 'no-store' },
Expand Down
4 changes: 1 addition & 3 deletions frontend/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import './globals.css';

import { Analytics } from '@vercel/analytics/next';
import { SpeedInsights } from '@vercel/speed-insights/next';
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';

Expand Down Expand Up @@ -90,8 +89,7 @@ export default function RootLayout({
className={`${geistSans.variable} ${geistMono.variable} bg-gray-50 text-gray-900 antialiased transition-colors duration-300 dark:bg-neutral-950 dark:text-gray-100`}
>
{children}
<Analytics />
<SpeedInsights />
{process.env.NODE_ENV === 'production' && <Analytics />}
</body>
</html>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { createClient } from '@sanity/client';
export const client = createClient({
projectId: '6y9ive6v',
dataset: 'production',
useCdn: false,
useCdn: true,
apiVersion: '2025-11-29',
});
Loading