mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
About 95% of the 404s served on supabase.com are App Router RSC prefetches (`?_rsc=`) that www `<Link>`s fire at paths another zone serves: `/docs`, `/dashboard`, `/library`, and the footer's `humans.txt`, `lawyers.txt` and `security.txt`. Next.js can't prefetch or client-navigate across multi-zone boundaries, so each prefetch 404s even though the link itself works. I turned every www link into another zone into a plain `<a>` and added a lint rule so new ones stay that way. **Changed:** - **Cross-zone links are plain anchors**: links that always leave www (literal `/docs`, `/dashboard` and `.txt` hrefs, absolute `https://supabase.com/dashboard` URLs, the `getDashboardCtaHref` CTAs) render `<a>`. Renderers whose href comes from data (nav, footer, plan and add-on CTAs, product cards) branch on `isCrossZoneHref`, which reads the zone list from `lib/rewrites.js`. In-zone links stay `<Link>` and keep prefetching. - **New literal links can't regress**: `www/no-cross-zone-link` errors on a `next/link` `<Link>` whose literal or template href points at another zone. It evaluates `lib/rewrites.js` as production, so `/docs` counts in every environment. - **Click tracking survives the full navigation**: `sign_in_button_clicked`, `start_project_button_clicked` and `www_pricing_plan_cta_clicked` now send with `keepalive`, like `sign_in_submitted` already did, so an immediate page load can't cancel them. The mobile nav Sign in and Start your project buttons used `legacyBehavior`, which never called their `onClick`: PostHog has no `Mobile Nav` location for either event in the last 30 days. Those clicks report from this PR on. - **Typecheck no longer crashes**: the functions page's default export inferred a type through `RealtimeLogs`'s unexported `Props`, which makes the native TypeScript compiler panic during `tsc --noEmit`. I exported `Props`. **Note:** the lint rule only sees literal hrefs. A new renderer whose href comes from data needs its own `isCrossZoneHref` branch, and review is the only check on that. ## To test `/docs` is only rewritten on production and absolute `https://supabase.com/...` links are cross-origin on a preview, so the preview proves the relative non-docs cases (`/dashboard*`, `/library`, the footer .txt files). `/docs/...` prefetches still appear on the preview because it has no docs rewrite. Tested on Vercel preview: - [x] Open `/` with the network tab filtered to `_rsc` and scroll to the footer: no requests for `/dashboard*`, `/library`, `/design-system`, `/kb`, `/evals`, `/humans.txt`, `/lawyers.txt` or `/.well-known/security.txt`, while in-zone ones such as `/pricing`, `/features` and `/blog` still appear - [x] Same check on `/pricing`, `/auth`, `/database`, `/storage`, `/realtime`, `/edge-functions`, `/blog` and a blog post: no `_rsc` requests to `/dashboard*`, `/library` or the footer .txt files - [x] Open the Developers dropdown on desktop and the mobile menu at 390px: no new `_rsc` requests to `/dashboard*` or `/library` - [x] Click header Docs, footer Humans.txt, the hero Start your project button and the pricing Free plan button: each lands where it did before (`/docs`, `/humans.txt` text, `https://supabase.com/dashboard/sign-up`, `https://supabase.com/dashboard/new?plan=free`). Signed out, the Free plan button lands on the dashboard sign-in with `plan=free&returnTo=%2Fnew` - [x] Click the hero Start your project button: the `/platform/telemetry/event` POST with `start_project_button_clicked` completes with a 2xx after the page starts navigating. 201 with the navigation held; on the real navigation the event still reached staging PostHog - [x] At 390px, open the mobile menu and click Sign in: a `/platform/telemetry/event` POST with `sign_in_button_clicked` and `buttonLocation: "Mobile Nav"` fires. Start your project in the same menu also sends `start_project_button_clicked` with `buttonLocation: "Mobile Nav"` - [ ] Signed in, load `/`: no `/dashboard/projects?_rsc=` request (not run: the preview origin has no signed-in session) - [x] Open the desktop Product dropdown and the Product section of the 390px mobile menu: Compute shows its Private Alpha badge and the other products show none (checks the master merge into `MenuItem`) After deploy, `/` and `/pricing` on supabase.com show no `_rsc` requests to `/docs*`, `/dashboard*` or `/library`. After a full day, the share of supabase.com 404s carrying `_rsc=` should drop from about 95% to under 10%, and `sign_in_button_clicked` and `start_project_button_clicked` should start showing a `Mobile Nav` location in PostHog. ## Linear - fixes GROWTH-1294
107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
import Examples from '~/data/Examples'
|
|
import { ArrowLeft, ArrowRight, BookOpen, Github } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import { useRef } from 'react'
|
|
// import Swiper core and required modules
|
|
import SwiperCore from 'swiper'
|
|
import { Navigation, Pagination } from 'swiper/modules'
|
|
import { Swiper, SwiperSlide } from 'swiper/react'
|
|
import { Button } from 'ui'
|
|
|
|
import ExampleCard from '../ExampleCard'
|
|
|
|
// install Swiper modules
|
|
SwiperCore.use([Navigation, Pagination])
|
|
|
|
function GithubExamples() {
|
|
const prevRef = useRef(null)
|
|
const nextRef = useRef(null)
|
|
|
|
return (
|
|
<>
|
|
<div className="grid grid-cols-12">
|
|
<div className="col-span-12 text-center">
|
|
<h2 className="h3">Community driven examples, libraries and guides</h2>
|
|
<p className="p ">
|
|
Supported by a network of early advocates, contributors, and champions.
|
|
</p>
|
|
<div className="flex items-center justify-center gap-2 py-4">
|
|
<Button asChild size="small" icon={<BookOpen size={12} />}>
|
|
<a href="/docs/guides/resources/examples">View guides</a>
|
|
</Button>
|
|
<Button asChild size="small" icon={<Github size={12} />}>
|
|
<Link
|
|
href="https://github.com/supabase/supabase/tree/master/examples"
|
|
as="https://github.com/supabase/supabase/tree/master/examples"
|
|
>
|
|
Official GitHub library
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4">
|
|
<div className={'lg:-mr-32 lg:-ml-32'}>
|
|
<Swiper
|
|
style={{ overflow: 'visible' }}
|
|
loop={true}
|
|
initialSlide={3}
|
|
spaceBetween={0}
|
|
slidesPerView={4}
|
|
autoplay={{
|
|
delay: 2400,
|
|
}}
|
|
speed={300}
|
|
navigation={{
|
|
prevEl: prevRef.current,
|
|
nextEl: nextRef.current,
|
|
// prevEl: prevRef.current ? prevRef.current : undefined,
|
|
// nextEl: nextRef.current ? nextRef.current : undefined,
|
|
}}
|
|
onInit={(swiper: any) => {
|
|
swiper.params.navigation.prevEl = prevRef.current
|
|
swiper.params.navigation.nextEl = nextRef.current
|
|
swiper.navigation.update()
|
|
}}
|
|
breakpoints={{
|
|
320: {
|
|
slidesPerView: 1,
|
|
},
|
|
720: {
|
|
slidesPerView: 2,
|
|
},
|
|
920: {
|
|
slidesPerView: 3,
|
|
},
|
|
1024: {
|
|
slidesPerView: 4,
|
|
},
|
|
}}
|
|
>
|
|
{Object.values(Examples).map((example: any, i: number) => {
|
|
return (
|
|
<SwiperSlide key={i}>
|
|
<div className="my-8 mr-3 ml-3">
|
|
<ExampleCard i={i} {...example} />
|
|
</div>
|
|
</SwiperSlide>
|
|
)
|
|
})}
|
|
<div className="container mx-auto mt-3 hidden flex-row justify-between md:flex">
|
|
<div ref={prevRef} className="p ml-4 cursor-pointer">
|
|
<ArrowLeft />
|
|
</div>
|
|
<div ref={nextRef} className="p mr-4 cursor-pointer">
|
|
<ArrowRight />
|
|
</div>
|
|
</div>
|
|
</Swiper>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default GithubExamples
|