diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 8a93f00..154a435 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -49,6 +49,7 @@ module.exports = {
'@typescript-eslint/prefer-for-of': 'error',
"no-sharp-comments": "off",
"markdown/no-sharp-comments": "off",
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_' }],
// todo: enable
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
diff --git a/.github/workflows/nextjs_bundle_analysis.yml b/.github/workflows/nextjs_bundle_analysis.yml
index d1676bb..c186e22 100644
--- a/.github/workflows/nextjs_bundle_analysis.yml
+++ b/.github/workflows/nextjs_bundle_analysis.yml
@@ -59,7 +59,7 @@ jobs:
path: .next/analyze/__bundle_analysis.json
- name: Download base branch bundle stats
- uses: dawidd6/action-download-artifact@v3
+ uses: dawidd6/action-download-artifact@v6
if: success() && github.event.number
with:
workflow: nextjs_bundle_analysis.yml
diff --git a/.gitignore b/.gitignore
index 817235c..1c49142 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
.source
node_modules
.vercel
-
+next-env.d.ts
.env.local
.env
.env*.local
diff --git a/LICENSE b/LICENSE
index 49a2249..5ee6463 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 LibreChat
+Copyright (c) 2026 LibreChat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx
index fc272cf..e5fb1d2 100644
--- a/app/blog/[slug]/page.tsx
+++ b/app/blog/[slug]/page.tsx
@@ -1,4 +1,5 @@
import { notFound } from 'next/navigation'
+import Image from 'next/image'
import Link from 'next/link'
import { InlineTOC } from 'fumadocs-ui/components/inline-toc'
import { mdxComponents } from '@/lib/mdx-components'
@@ -51,9 +52,23 @@ export default async function BlogPostPage(props: PageProps) {
{(post as any).author && by {(post as any).author}}
+ {post.ogImage && (
+
+ )}
- {post.toc && post.toc.length > 0 && }
+ {post.toc && post.toc.length > 0 && (
+
+
+
+ )}
diff --git a/app/blog/page.tsx b/app/blog/page.tsx
index 6f5efbb..174bc61 100644
--- a/app/blog/page.tsx
+++ b/app/blog/page.tsx
@@ -1,3 +1,4 @@
+import Image from 'next/image'
import Link from 'next/link'
import { blog } from '@/lib/source'
import type { Metadata } from 'next'
@@ -11,11 +12,20 @@ interface FeedEntry {
title: string
description?: string
date: string
+ dateFormatted: string
url: string
- category: string
author?: string
+ ogImage?: string
+ ogImagePosition?: string
}
+const dateFormatter = new Intl.DateTimeFormat('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ timeZone: 'UTC',
+})
+
function getSlug(path: string): string {
return path.replace(/\.mdx?$/, '')
}
@@ -24,14 +34,17 @@ export default function BlogPage() {
const entries: FeedEntry[] = []
for (const post of blog) {
+ const iso =
+ typeof post.date === 'string' ? post.date : new Date(post.date).toISOString().split('T')[0]
entries.push({
title: post.title,
description: post.description,
- date:
- typeof post.date === 'string' ? post.date : new Date(post.date).toISOString().split('T')[0],
+ date: iso,
+ dateFormatted: dateFormatter.format(new Date(iso + 'T00:00:00Z')),
url: `/blog/${getSlug(post._file.path)}`,
- category: (post as any).category ?? 'guide',
author: (post as any).author,
+ ogImage: post.ogImage,
+ ogImagePosition: (post as any).ogImagePosition,
})
}
@@ -46,32 +59,46 @@ export default function BlogPage() {
-
+
{entries.map((entry) => (
-