Skip to content
Closed
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
2 changes: 0 additions & 2 deletions app/api/link-preview/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { LinkPreviewService, InvalidUrlError } from '@/services/linkPreview.service';

export const runtime = 'edge';

// 24h CDN cache for full previews. 1h for host-only fallbacks (so a failing
// upstream gets a retry chance sooner) and for invalid-URL errors (so a
// caller spamming `?url=garbage` hits the CDN instead of re-invoking the
Expand Down
218 changes: 107 additions & 111 deletions app/api/og/route.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { ImageResponse } from 'next/og';
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const title = searchParams.get('title');
Expand All @@ -11,140 +9,138 @@ export async function GET(request: NextRequest) {
const type = searchParams.get('type') || 'article';

return new ImageResponse(
(
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
padding: '60px',
fontFamily: 'Inter, system-ui, sans-serif',
}}
>
{/* Background pattern */}
<div
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)',
opacity: 0.1,
}}
/>

{/* Logo and brand */}
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ffffff',
padding: '60px',
fontFamily: 'Inter, system-ui, sans-serif',
marginBottom: '40px',
position: 'relative',
zIndex: 1,
}}
>
{/* Background pattern */}
<div
<img
src="https://researchhub.com/logo_blue.png"
alt="ResearchHub"
width={480}
height={120}
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)',
opacity: 0.1,
display: 'block',
background: '#fff',
objectFit: 'contain',
}}
/>
</div>

{/* Logo and brand */}
{/* Content type badge */}
{type && (
<div
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '40px',
position: 'relative',
zIndex: 1,
backgroundColor: '#3b82f6',
color: 'white',
padding: '8px 16px',
borderRadius: '20px',
fontSize: '14px',
fontWeight: '500',
marginBottom: '30px',
textTransform: 'uppercase',
letterSpacing: '0.5px',
}}
>
<img
src="https://researchhub.com/logo_blue.png"
alt="ResearchHub"
width={480}
height={120}
style={{
display: 'block',
background: '#fff',
objectFit: 'contain',
}}
/>
{type}
</div>
)}

{/* Content type badge */}
{type && (
<div
style={{
backgroundColor: '#3b82f6',
color: 'white',
padding: '8px 16px',
borderRadius: '20px',
fontSize: '14px',
fontWeight: '500',
marginBottom: '30px',
textTransform: 'uppercase',
letterSpacing: '0.5px',
}}
>
{type}
</div>
)}

{/* Title */}
{title && (
<h1
style={{
fontSize: '48px',
fontWeight: 'bold',
textAlign: 'center',
color: '#1f2937',
margin: '0 0 20px 0',
lineHeight: 1.2,
maxWidth: '900px',
}}
>
{title}
</h1>
)}
{/* Title */}
{title && (
<h1
style={{
fontSize: '48px',
fontWeight: 'bold',
textAlign: 'center',
color: '#1f2937',
margin: '0 0 20px 0',
lineHeight: 1.2,
maxWidth: '900px',
}}
>
{title}
</h1>
)}

{/* Description */}
{description && (
<p
style={{
fontSize: '24px',
textAlign: 'center',
color: '#6b7280',
margin: '0 0 30px 0',
lineHeight: 1.4,
maxWidth: '800px',
}}
>
{description}
</p>
)}
{/* Description */}
{description && (
<p
style={{
fontSize: '24px',
textAlign: 'center',
color: '#6b7280',
margin: '0 0 30px 0',
lineHeight: 1.4,
maxWidth: '800px',
}}
>
{description}
</p>
)}

{/* Author */}
{author && (
{/* Author */}
{author && (
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '12px',
fontSize: '18px',
color: '#9ca3af',
}}
>
<div
style={{
width: '32px',
height: '32px',
backgroundColor: '#e5e7eb',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
gap: '12px',
fontSize: '18px',
color: '#9ca3af',
justifyContent: 'center',
fontSize: '14px',
fontWeight: '600',
color: '#6b7280',
}}
>
<div
style={{
width: '32px',
height: '32px',
backgroundColor: '#e5e7eb',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '14px',
fontWeight: '600',
color: '#6b7280',
}}
>
{author.charAt(0).toUpperCase()}
</div>
<span>By {author}</span>
{author.charAt(0).toUpperCase()}
</div>
)}
</div>
),
<span>By {author}</span>
</div>
)}
</div>,
{
width: 1200,
height: 630,
Expand Down
3 changes: 3 additions & 0 deletions app/changelog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PostService } from '@/services/post.service';
import { Work } from '@/types/work';
import { ChangelogEntry } from '@/components/changelog/ChangelogEntry';
import { notFound } from 'next/navigation';
import { connection } from 'next/server';
import { buildOpenGraphMetadata } from '@/lib/metadata';
import { PageLayout } from '@/app/layouts/PageLayout';
import { CHANGELOG_POST_IDS } from '@/constants/changelog';
Expand Down Expand Up @@ -38,6 +39,8 @@ async function fetchPostWithContent(postId: string): Promise<PostWithContent | n
}

export default async function ChangelogPage() {
await connection(); // stop build-time prerender for this page

const postsWithContent = await Promise.all(
CHANGELOG_POST_IDS.map((id) => fetchPostWithContent(id))
);
Expand Down
3 changes: 3 additions & 0 deletions app/moderators/editors/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { connection } from 'next/server';
import { UserService } from '@/services/user.service';
import EditorsDashboardContent from './components/EditorsDashboardContent';

export default async function EditorsPage() {
await connection(); // stop build-time prerender for this page

// Check if user has permissions for the PERMISSIONS_DASH application
const hasPermissionsAccess = await UserService.gatekeeper('PERMISSIONS_DASH');

Expand Down
Loading