From 33f63d91ad928c55acd789c927a29eb88e835441 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Mon, 4 Aug 2025 11:52:27 +0200 Subject: [PATCH] feat: useQwikRouter this makes it possible to put the routerhead in root as well --- .changeset/every-badgers-bake.md | 5 + .../components/router-head/router-head.tsx | 24 ---- e2e/adapters-e2e/src/root.tsx | 24 ++-- packages/docs/src/root.tsx | 105 +++++++++++++++++- .../docs/src/routes/api/qwik-router/api.json | 22 +++- .../docs/src/routes/api/qwik-router/index.mdx | 51 ++++++++- .../routes/docs/(qwikrouter)/api/index.mdx | 30 +++-- .../docs/integrations/partytown/index.mdx | 12 +- .../src/routes/docs/labs/insights/index.mdx | 6 +- .../components/router-head/router-head.tsx | 30 ----- packages/insights/src/root.tsx | 27 ++++- packages/qwik-router/src/runtime/src/index.ts | 1 + .../src/runtime/src/qwik-router-component.tsx | 41 ++++--- .../runtime/src/qwik-router.runtime.api.md | 5 +- starters/apps/empty/public/manifest.json | 9 -- .../components/router-head/router-head.tsx | 18 --- starters/apps/empty/src/root.tsx | 30 +++-- .../components/router-head/router-head.tsx | 18 --- starters/apps/playground/src/root.tsx | 30 +++-- .../apps/qwikrouter-test.prod/src/root.tsx | 7 +- starters/apps/qwikrouter-test/src/root.tsx | 25 +++-- 21 files changed, 301 insertions(+), 219 deletions(-) create mode 100644 .changeset/every-badgers-bake.md delete mode 100644 e2e/adapters-e2e/src/components/router-head/router-head.tsx delete mode 100644 packages/insights/src/components/router-head/router-head.tsx delete mode 100644 starters/apps/empty/public/manifest.json delete mode 100644 starters/apps/empty/src/components/router-head/router-head.tsx delete mode 100644 starters/apps/playground/src/components/router-head/router-head.tsx diff --git a/.changeset/every-badgers-bake.md b/.changeset/every-badgers-bake.md new file mode 100644 index 00000000000..40b216079f5 --- /dev/null +++ b/.changeset/every-badgers-bake.md @@ -0,0 +1,5 @@ +--- +'@qwik.dev/router': minor +--- + +FEAT: useQwikRouter() hook replaces QwikRouterProvider. This gives access to the context immediately and is slightly more efficient. diff --git a/e2e/adapters-e2e/src/components/router-head/router-head.tsx b/e2e/adapters-e2e/src/components/router-head/router-head.tsx deleted file mode 100644 index 849545cf345..00000000000 --- a/e2e/adapters-e2e/src/components/router-head/router-head.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { component$ } from '@qwik.dev/core'; -import { useDocumentHead, useLocation } from '@qwik.dev/router'; - -export const RouterHead = component$(() => { - const head = useDocumentHead(); - const loc = useLocation(); - - return ( - <> - {head.title} - - - - - {head.meta.map((m) => ( - - ))} - - {head.links.map((l) => ( - - ))} - - ); -}); diff --git a/e2e/adapters-e2e/src/root.tsx b/e2e/adapters-e2e/src/root.tsx index 505af2e5942..80f7927bb24 100644 --- a/e2e/adapters-e2e/src/root.tsx +++ b/e2e/adapters-e2e/src/root.tsx @@ -1,24 +1,24 @@ import { component$ } from '@qwik.dev/core'; -import { QwikRouterProvider, RouterOutlet } from '@qwik.dev/router'; -import { RouterHead } from './components/router-head/router-head'; +import { DocumentHeadTags, RouterOutlet, useLocation, useQwikRouter } from '@qwik.dev/router'; export default component$(() => { - /** - * The root of a QwikCity site always start with the component, immediately - * followed by the document's and . - * - * Don't remove the `` and `` elements. - */ + useQwikRouter(); + + const loc = useLocation(); return ( - + <> - + + + + + - + - + ); }); diff --git a/packages/docs/src/root.tsx b/packages/docs/src/root.tsx index 85f1643124c..a93c1d9ec97 100644 --- a/packages/docs/src/root.tsx +++ b/packages/docs/src/root.tsx @@ -1,11 +1,19 @@ import { component$, useContextProvider, useStore } from '@qwik.dev/core'; import { Insights } from '@qwik.dev/core/insights'; -import { QwikRouterProvider, RouterOutlet, ServiceWorkerRegister } from '@qwik.dev/router'; +import { + RouterOutlet, + ServiceWorkerRegister, + useDocumentHead, + useLocation, + useQwikRouter, +} from '@qwik.dev/router'; import RealMetricsOptimization from './components/real-metrics-optimization/real-metrics-optimization'; -import { RouterHead } from './components/router-head/router-head'; import { BUILDER_PUBLIC_API_KEY } from './constants'; import { GlobalStore, type SiteStore } from './context'; import './global.css'; +import { ThemeScript } from './components/router-head/theme-script'; +import { Social } from './components/router-head/social'; +import { Vendor } from './components/router-head/vendor'; export const uwu = /*javascript*/ ` ;(function () { @@ -41,6 +49,10 @@ export const uwu = /*javascript*/ ` `; export default component$(() => { + useQwikRouter(); + const head = useDocumentHead(); + const { url } = useLocation(); + const store = useStore({ headerMenuOpen: false, sideMenuOpen: false, @@ -48,12 +60,94 @@ export default component$(() => { useContextProvider(GlobalStore, store); + const title = head.title + ? `${head.title} 📚 Qwik Documentation` + : `Qwik - Framework reimagined for the edge`; + const description = + head.meta.find((m) => m.name === 'description')?.content || + `No hydration, auto lazy-loading, edge-optimized, and fun 🎉!`; + + const OGImage = { + imageURL: '', + ogImgTitle: '', + ogImgSubTitle: '' as string | undefined, + + get URL() { + //turn the title into array with [0] -> Title [1] -> subTitle + const arrayedTitle = title.split(' | '); + const ogImageUrl = new URL('https://opengraphqwik.vercel.app/api/og?level=1'); + + // biggerTitle + this.ogImgTitle = arrayedTitle[0]; + //smallerTitle + this.ogImgSubTitle = arrayedTitle[1] + ? arrayedTitle[1].replace(' 📚 Qwik Documentation', '') + : undefined; + + //decide whether or not to show dynamic OGimage or use docs default social card + if (this.ogImgSubTitle == undefined || this.ogImgTitle == undefined) { + this.imageURL = new URL(`/logos/social-card.jpg`, url).href; + + return this.imageURL; + } else { + ogImageUrl.searchParams.set('title', this.ogImgTitle); + ogImageUrl.searchParams.set('subtitle', this.ogImgSubTitle); + // ogImageUrl.searchParams.set('level', this.routeLevel.toString()); + + this.imageURL = ogImageUrl.toString(); + + return this.imageURL; + } + }, + }; + return ( - + <> + + {title} + + + + + + + + + + + + + {import.meta.env.PROD && ( + <> + + + + )} + + {/* The below are tags that were collected from all the `head` exports in the current route. */} + {head.meta + // Skip description because that was already added at the top + .filter((s) => s.name !== 'description') + .map((m, key) => ( + + ))} + + {head.links.map((l, key) => ( + + ))} + + {head.styles.map((s, key) => ( +