mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
* fix(sidebar): show icon-sized skeletons in collapsed settings sidebar * fix(sidebar): hide expanded skeletons during pre-hydration in collapsed settings * fix(sidebar): align collapsed settings skeletons with actual icon positions * fix(sidebar): match collapsed skeleton section grouping with loaded layout * fix(sidebar): hoist skeleton section counts to module constant * improvement(ui): align all public pages with dark landing theme and improve whitelabeling * fix(ui): address PR review comments - restore StatusPageLayout wrapper, improve whitelabel detection * fix(ui): add missing dark class to 404 page, add relative positioning to invite layout * fix(ui): fallback to white button when whitelabeled without primary color * improvement(seo): add x-default hreflang, speakable schema to landing and blog posts * fix(ui): fix OTP/input light-mode styles and add missing header classes on standalone auth pages * undo hardcoded ff config * update old components/ui usage to emcn * fix(ui): add SupportFooter to InviteLayout, remove duplicates from unsubscribe page * fix(ui): fix invite layout flex centering, use BrandedButton on 404 page * fix(ui): fix OTP group styling, props spread order in BrandedButton, invite header shrink-0 * fix: enterprise hydration error --------- Co-authored-by: Emir Karabeg <emirkarabeg@berkeley.edu>
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import Link from 'next/link'
|
|
import { getAllPostMeta } from '@/lib/blog/registry'
|
|
import { PostGrid } from '@/app/(landing)/studio/post-grid'
|
|
|
|
export const metadata: Metadata = {
|
|
title: 'Studio',
|
|
description: 'Announcements, insights, and guides from the Sim team.',
|
|
}
|
|
|
|
export const revalidate = 3600
|
|
|
|
export default async function StudioIndex({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ page?: string; tag?: string }>
|
|
}) {
|
|
const { page, tag } = await searchParams
|
|
const pageNum = Math.max(1, Number(page || 1))
|
|
const perPage = 20
|
|
|
|
const all = await getAllPostMeta()
|
|
const filtered = tag ? all.filter((p) => p.tags.includes(tag)) : all
|
|
|
|
const sorted =
|
|
pageNum === 1
|
|
? filtered.sort((a, b) => {
|
|
if (a.featured && !b.featured) return -1
|
|
if (!a.featured && b.featured) return 1
|
|
return new Date(b.date).getTime() - new Date(a.date).getTime()
|
|
})
|
|
: filtered
|
|
|
|
const totalPages = Math.max(1, Math.ceil(sorted.length / perPage))
|
|
const start = (pageNum - 1) * perPage
|
|
const posts = sorted.slice(start, start + perPage)
|
|
// Tag filter chips are intentionally disabled for now.
|
|
// const tags = await getAllTags()
|
|
const studioJsonLd = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Blog',
|
|
name: 'Sim Studio',
|
|
url: 'https://sim.ai/studio',
|
|
description: 'Announcements, insights, and guides for building AI agent workflows.',
|
|
}
|
|
|
|
return (
|
|
<main className='mx-auto max-w-[1200px] px-6 py-12 sm:px-8 md:px-12'>
|
|
<script
|
|
type='application/ld+json'
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(studioJsonLd) }}
|
|
/>
|
|
<h1 className='mb-3 font-[500] text-[#ECECEC] text-[40px] leading-tight sm:text-[56px]'>
|
|
Sim Studio
|
|
</h1>
|
|
<p className='mb-10 text-[#999] text-[18px]'>
|
|
Announcements, insights, and guides for building AI agent workflows.
|
|
</p>
|
|
|
|
{/* Tag filter chips hidden until we have more posts */}
|
|
{/* <div className='mb-10 flex flex-wrap gap-3'>
|
|
<Link href='/studio' className={`rounded-full border px-3 py-1 text-sm ${!tag ? 'border-black bg-black text-white' : 'border-gray-300'}`}>All</Link>
|
|
{tags.map((t) => (
|
|
<Link key={t.tag} href={`/studio?tag=${encodeURIComponent(t.tag)}`} className={`rounded-full border px-3 py-1 text-sm ${tag === t.tag ? 'border-black bg-black text-white' : 'border-gray-300'}`}>
|
|
{t.tag} ({t.count})
|
|
</Link>
|
|
))}
|
|
</div> */}
|
|
|
|
{/* Grid layout for consistent rows */}
|
|
<PostGrid posts={posts} />
|
|
|
|
{totalPages > 1 && (
|
|
<div className='mt-10 flex items-center justify-center gap-3'>
|
|
{pageNum > 1 && (
|
|
<Link
|
|
href={`/studio?page=${pageNum - 1}${tag ? `&tag=${encodeURIComponent(tag)}` : ''}`}
|
|
className='rounded-[5px] border border-[#3d3d3d] px-3 py-1 text-[#ECECEC] text-sm transition-colors hover:bg-[#2A2A2A]'
|
|
>
|
|
Previous
|
|
</Link>
|
|
)}
|
|
<span className='text-[#999] text-sm'>
|
|
Page {pageNum} of {totalPages}
|
|
</span>
|
|
{pageNum < totalPages && (
|
|
<Link
|
|
href={`/studio?page=${pageNum + 1}${tag ? `&tag=${encodeURIComponent(tag)}` : ''}`}
|
|
className='rounded-[5px] border border-[#3d3d3d] px-3 py-1 text-[#ECECEC] text-sm transition-colors hover:bg-[#2A2A2A]'
|
|
>
|
|
Next
|
|
</Link>
|
|
)}
|
|
</div>
|
|
)}
|
|
</main>
|
|
)
|
|
}
|