diff --git a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx
index 2188ffeded..b784f689bb 100644
--- a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx
+++ b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx
@@ -4,7 +4,7 @@ import {
ProcessedDocument,
RelatedDocument,
} from '@nx/nx-dev/models-document';
-import { Breadcrumbs, Footer } from '@nx/nx-dev/ui-common';
+import { Breadcrumbs, Footer, GitHubStarWidget } from '@nx/nx-dev/ui-common';
import { renderMarkdown } from '@nx/nx-dev/ui-markdoc';
import { NextSeo } from 'next-seo';
import { useRouter } from 'next/router';
@@ -15,9 +15,11 @@ import { collectHeadings, TableOfContents } from './table-of-contents';
export function DocViewer({
document,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const hideTableOfContent =
@@ -109,7 +111,13 @@ export function DocViewer({
elementRef={ref}
path={router.basePath}
headings={vm.tableOfContent}
- />
+ >
+ {widgetData.githubStarsCount > 0 && (
+
+ )}
+
)}
diff --git a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx
index d7afc3a502..24bdabeb90 100644
--- a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx
+++ b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx
@@ -39,10 +39,12 @@ export function TableOfContents({
elementRef,
headings,
path,
+ children,
}: {
elementRef: any;
headings: Heading[];
path: string;
+ children: React.ReactNode;
}): JSX.Element {
const headingLevelTargets: number[] = [1, 2, 3]; // matching to: H1, H2, H3...
const items = headings.filter(
@@ -60,32 +62,35 @@ export function TableOfContents({
);
return (
-
+ <>
+
+
{children}
+ >
);
}
diff --git a/nx-dev/nx-dev/lib/githubStars.api.ts b/nx-dev/nx-dev/lib/githubStars.api.ts
new file mode 100644
index 0000000000..329709ad51
--- /dev/null
+++ b/nx-dev/nx-dev/lib/githubStars.api.ts
@@ -0,0 +1,33 @@
+import { Octokit } from 'octokit';
+
+let cachedGithubStarCountPromise: null | Promise = null;
+
+export async function fetchGithubStarCount() {
+ if (cachedGithubStarCountPromise !== null) {
+ // If the promise is in the cache, return it directly
+ return cachedGithubStarCountPromise;
+ }
+
+ cachedGithubStarCountPromise = (async () => {
+ try {
+ const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
+ const responseData = await octokit.request('GET /repos/{owner}/{repo}', {
+ owner: 'nrwl',
+ repo: 'nx',
+ headers: {
+ 'X-GitHub-Api-Version': '2022-11-28',
+ },
+ retry: { enabled: false },
+ throttle: {
+ enabled: true,
+ },
+ });
+
+ return responseData.data.stargazers_count;
+ } catch (e) {
+ return 0; // fallback, will hide GitHub star widget
+ }
+ })();
+
+ return cachedGithubStarCountPromise;
+}
diff --git a/nx-dev/nx-dev/pages/[...segments].tsx b/nx-dev/nx-dev/pages/[...segments].tsx
index 249ddce33c..236a10d22e 100644
--- a/nx-dev/nx-dev/pages/[...segments].tsx
+++ b/nx-dev/nx-dev/pages/[...segments].tsx
@@ -1,7 +1,7 @@
import { getBasicNxSection } from '@nx/nx-dev/data-access-menu';
import { DocViewer } from '@nx/nx-dev/feature-doc-viewer';
import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document';
-import { Menu, MenuItem } from '@nx/nx-dev/models-menu';
+import { MenuItem } from '@nx/nx-dev/models-menu';
import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common';
import { GetStaticPaths, GetStaticProps } from 'next';
import { useRouter } from 'next/router';
@@ -10,15 +10,18 @@ import { menusApi } from '../lib/menus.api';
import { useNavToggle } from '../lib/navigation-toggle.effect';
import { nxDocumentationApi } from '../lib/nx.api';
import { tagsApi } from '../lib/tags.api';
+import { fetchGithubStarCount } from '../lib/githubStars.api';
export default function NxDocumentation({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}) {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -40,16 +43,8 @@ export default function NxDocumentation({
return () => router.events.off('routeChangeComplete', handleRouteChange);
}, [router, wrapperElement]);
- const vm: {
- document: ProcessedDocument;
- menu: Menu;
- relatedDocuments: RelatedDocument[];
- } = {
- document,
- menu: {
- sections: [getBasicNxSection(menu)],
- },
- relatedDocuments,
+ const menuWithSections = {
+ sections: [getBasicNxSection(menu)],
};
return (
@@ -62,7 +57,7 @@ export default function NxDocumentation({
role="main"
className="flex h-full flex-1 overflow-y-hidden"
>
-
+
@@ -100,6 +96,9 @@ export const getStaticProps: GetStaticProps = async ({
return {
props: {
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: tagsApi
.getAssociatedItemsFromTags(document.tags)
.filter((item) => item.path !== '/' + params.segments.join('/')), // Remove currently displayed item
diff --git a/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx
index 3e9c375f69..6b7128517c 100644
--- a/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx
+++ b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx
@@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api';
import { useNavToggle } from '../../lib/navigation-toggle.effect';
import { nxPluginsApi } from '../../lib/plugins.api';
import { tagsApi } from '../../lib/tags.api';
+import { fetchGithubStarCount } from '../../lib/githubStars.api';
export default function Pages({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -72,6 +75,7 @@ export default function Pages({
@@ -98,6 +102,9 @@ export const getStaticProps: GetStaticProps = async ({
return {
props: {
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: tagsApi
.getAssociatedItemsFromTags(document.tags)
.filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item
diff --git a/nx-dev/nx-dev/pages/extending-nx/index.tsx b/nx-dev/nx-dev/pages/extending-nx/index.tsx
index 1ace8563b1..5d8f92214e 100644
--- a/nx-dev/nx-dev/pages/extending-nx/index.tsx
+++ b/nx-dev/nx-dev/pages/extending-nx/index.tsx
@@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api';
import { useNavToggle } from '../../lib/navigation-toggle.effect';
import { nxPluginsApi } from '../../lib/plugins.api';
import { tagsApi } from '../../lib/tags.api';
+import { fetchGithubStarCount } from '../../lib/githubStars.api';
export default function PluginsRoot({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}) {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -72,6 +75,7 @@ export default function PluginsRoot({
@@ -87,6 +91,9 @@ export const getStaticProps: GetStaticProps = async () => {
return {
props: {
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
menu: menusApi.getMenu('extending-nx', ''),
relatedDocuments: document.tags
.map((t) => tagsApi.getAssociatedItems(t))
diff --git a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx
index 1bf55d9b57..b4d9791d0a 100644
--- a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx
+++ b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx
@@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api';
import { menusApi } from '../../lib/menus.api';
import { useNavToggle } from '../../lib/navigation-toggle.effect';
import { tagsApi } from '../../lib/tags.api';
+import { fetchGithubStarCount } from '../../lib/githubStars.api';
export default function Pages({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}) {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -75,6 +78,7 @@ export default function Pages({
@@ -99,6 +103,9 @@ export const getStaticProps: GetStaticProps = async ({
return {
props: {
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: tagsApi
.getAssociatedItemsFromTags(document.tags)
.filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item
diff --git a/nx-dev/nx-dev/pages/nx-cloud/index.tsx b/nx-dev/nx-dev/pages/nx-cloud/index.tsx
index 4ae72535b8..9742328df4 100644
--- a/nx-dev/nx-dev/pages/nx-cloud/index.tsx
+++ b/nx-dev/nx-dev/pages/nx-cloud/index.tsx
@@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api';
import { menusApi } from '../../lib/menus.api';
import { useNavToggle } from '../../lib/navigation-toggle.effect';
import { tagsApi } from '../../lib/tags.api';
+import { fetchGithubStarCount } from '../../lib/githubStars.api';
export default function CloudRoot({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}) {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -75,6 +78,7 @@ export default function CloudRoot({
@@ -90,6 +94,9 @@ export const getStaticProps: GetStaticProps = async () => {
return {
props: {
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
menu: menusApi.getMenu('cloud', ''),
relatedDocuments: document.tags
.map((t) => tagsApi.getAssociatedItems(t))
diff --git a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx
index 5cb45d0b85..de802de867 100644
--- a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx
+++ b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx
@@ -13,16 +13,19 @@ import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { nxPackagesApi } from '../../../../lib/packages.api';
import { tagsApi } from '../../../../lib/tags.api';
+import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
export default function PackageDocument({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -79,6 +82,7 @@ export default function PackageDocument({
@@ -120,6 +124,9 @@ export async function getStaticProps({
props: {
pkg: nxPackagesApi.getPackage([params.name]),
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: tagsApi
.getAssociatedItemsFromTags(document.tags)
.filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item
diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx
index e4e5960e2b..badb401320 100644
--- a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx
+++ b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx
@@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { content } from '../../../../lib/rspack/content/overview';
import { pkg } from '../../../../lib/rspack/pkg';
+import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
export default function Overview({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -77,6 +80,7 @@ export default function Overview({
@@ -99,6 +103,9 @@ export async function getStaticProps() {
props: {
pkg,
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: [],
menu: menusApi.getMenu('packages', ''),
},
diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx
index 028f2bbb84..0ba2309bf3 100644
--- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx
+++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx
@@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { content } from '../../../../lib/rspack/content/rspack-config-setup';
import { pkg } from '../../../../lib/rspack/pkg';
+import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
export default function RspackConfigSetup({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -77,6 +80,7 @@ export default function RspackConfigSetup({
@@ -100,6 +104,9 @@ export async function getStaticProps() {
props: {
pkg,
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: [],
menu: menusApi.getMenu('packages', ''),
},
diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx
index 065c3d1834..6567ff04f5 100644
--- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx
+++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx
@@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api';
import { useNavToggle } from '../../../../lib/navigation-toggle.effect';
import { content } from '../../../../lib/rspack/content/rspack-plugin';
import { pkg } from '../../../../lib/rspack/pkg';
+import { fetchGithubStarCount } from '../../../../lib/githubStars.api';
export default function RspackPlugins({
document,
menu,
relatedDocuments,
+ widgetData,
}: {
document: ProcessedDocument;
menu: MenuItem[];
pkg: ProcessedPackageMetadata;
relatedDocuments: RelatedDocument[];
+ widgetData: { githubStarsCount: number };
}): JSX.Element {
const router = useRouter();
const { toggleNav, navIsOpen } = useNavToggle();
@@ -77,6 +80,7 @@ export default function RspackPlugins({
@@ -99,6 +103,9 @@ export async function getStaticProps() {
props: {
pkg,
document,
+ widgetData: {
+ githubStarsCount: await fetchGithubStarCount(),
+ },
relatedDocuments: [],
menu: menusApi.getMenu('packages', ''),
},
diff --git a/nx-dev/ui-common/src/index.ts b/nx-dev/ui-common/src/index.ts
index 1431e27616..0be0fe5c60 100644
--- a/nx-dev/ui-common/src/index.ts
+++ b/nx-dev/ui-common/src/index.ts
@@ -13,3 +13,4 @@ export * from './lib/nx-users-showcase';
export * from './lib/plugin-card';
export * from './lib/testimonial-card';
export * from './lib/typography';
+export * from './lib/github-star-widget';
diff --git a/nx-dev/ui-common/src/lib/github-star-widget.tsx b/nx-dev/ui-common/src/lib/github-star-widget.tsx
new file mode 100644
index 0000000000..f38e51ab79
--- /dev/null
+++ b/nx-dev/ui-common/src/lib/github-star-widget.tsx
@@ -0,0 +1,58 @@
+import { sendCustomEvent } from '@nx/nx-dev/feature-analytics';
+
+const GithubIcon = (props: any) => {
+ return (
+
+ );
+};
+
+export function GitHubStarWidget({ starsCount }: { starsCount: number }) {
+ const formatStars = (count: number) => {
+ if (count >= 1000) {
+ return (count / 1000).toFixed(1) + 'k';
+ } else {
+ return count;
+ }
+ };
+
+ const handleClick = (eventAction: string) => {
+ sendCustomEvent(
+ eventAction,
+ 'githubstars-toc-sidebar',
+ 'githubstarswidget'
+ );
+ };
+
+ return (
+
+ );
+}