Skip to content
2 changes: 2 additions & 0 deletions apps/sim/app/(landing)/blog/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getNavBlogPosts } from '@/lib/blog/registry'
import { SITE_URL } from '@/lib/core/utils/urls'
import Footer from '@/app/(landing)/components/footer/footer'
import Navbar from '@/app/(landing)/components/navbar/navbar'
import { ScrollToTop } from '@/app/(landing)/components/scroll-to-top'

export default async function StudioLayout({ children }: { children: React.ReactNode }) {
const blogPosts = await getNavBlogPosts()
Expand Down Expand Up @@ -29,6 +30,7 @@ export default async function StudioLayout({ children }: { children: React.React

return (
<div className='flex min-h-screen flex-col bg-[var(--landing-bg)] font-[430] font-season text-[var(--landing-text)]'>
<ScrollToTop />
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(orgJsonLd) }}
Expand Down
22 changes: 22 additions & 0 deletions apps/sim/app/(landing)/components/scroll-to-top.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client'

import { useEffect } from 'react'
import { usePathname } from 'next/navigation'

/**
* Resets window scroll to the top on App Router pathname changes.
*
* Next.js's default scroll handling only brings the new Page element into view,
* which often resolves to "no scroll" inside shared layouts (see vercel/next.js#64435).
* Skipped when a hash anchor is targeted so the browser's native anchor scroll wins.
*/
export function ScrollToTop() {
const pathname = usePathname()

useEffect(() => {
if (window.location.hash) return
window.scrollTo(0, 0)
Comment thread
waleedlatif1 marked this conversation as resolved.
}, [pathname])
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.

return null
}
2 changes: 2 additions & 0 deletions apps/sim/app/(landing)/integrations/(shell)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getNavBlogPosts } from '@/lib/blog/registry'
import { SITE_URL } from '@/lib/core/utils/urls'
import Footer from '@/app/(landing)/components/footer/footer'
import Navbar from '@/app/(landing)/components/navbar/navbar'
import { ScrollToTop } from '@/app/(landing)/components/scroll-to-top'

export default async function IntegrationsLayout({ children }: { children: React.ReactNode }) {
const blogPosts = await getNavBlogPosts()
Expand Down Expand Up @@ -29,6 +30,7 @@ export default async function IntegrationsLayout({ children }: { children: React

return (
<div className='dark flex min-h-screen flex-col bg-[var(--landing-bg)] font-[430] font-season text-[var(--landing-text)]'>
<ScrollToTop />
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(orgJsonLd) }}
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/app/(landing)/models/(shell)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getNavBlogPosts } from '@/lib/blog/registry'
import { SITE_URL } from '@/lib/core/utils/urls'
import Footer from '@/app/(landing)/components/footer/footer'
import Navbar from '@/app/(landing)/components/navbar/navbar'
import { ScrollToTop } from '@/app/(landing)/components/scroll-to-top'

export default async function ModelsLayout({ children }: { children: React.ReactNode }) {
const blogPosts = await getNavBlogPosts()
Expand All @@ -24,6 +25,7 @@ export default async function ModelsLayout({ children }: { children: React.React

return (
<div className='dark flex min-h-screen flex-col bg-[var(--landing-bg)] font-[430] font-season text-[var(--landing-text)]'>
<ScrollToTop />
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(orgJsonLd) }}
Expand Down
Loading