Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,7 @@ import {
faDownload,
faCaretRight,
} from "@fortawesome/free-solid-svg-icons";
import {
memo,
type ReactElement,
Suspense,
useEffect,
useRef,
useState,
} from "react";
import { useHydrated } from "remix-utils/use-hydrated";
import { memo, Suspense } from "react";
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";
import { faArrowUpRight } from "@fortawesome/pro-solid-svg-icons";
import { RelativeTime } from "@thunderstore/cyberstorm/src/components/RelativeTime/RelativeTime";
Expand Down Expand Up @@ -79,7 +71,6 @@ export async function loader({ params }: LoaderFunctionArgs) {
});

return {
community: await dapper.getCommunity(communityId),
listing,
packageVersion,
team: await dapper.getTeamDetails(namespaceId),
Expand Down Expand Up @@ -108,7 +99,6 @@ export async function clientLoader({ params }: LoaderFunctionArgs) {
});

return {
community: dapper.getCommunity(communityId),
listing,
packageVersion,
team: dapper.getTeamDetails(namespaceId),
Expand All @@ -132,41 +122,13 @@ export function shouldRevalidate(arg: ShouldRevalidateFunctionArgs) {
return arg.defaultShouldRevalidate;
}

export default function PackageVersion() {
const { community, listing, packageVersion, team } = useLoaderData<
export default function PackageListingVersion() {
const { listing, packageVersion, team } = useLoaderData<
typeof loader | typeof clientLoader
>();

const location = useLocation();

const outletContext = useOutletContext() as OutletContextShape;

const isHydrated = useHydrated();
const startsHydrated = useRef(isHydrated);

// START: For sidebar meta dates
const [firstUploaded, setFirstUploaded] = useState<
ReactElement | undefined
>();

// This will be loaded 2 times in development because of:
// https://react.dev/reference/react/StrictMode
// If strict mode is removed from the entry.client.tsx, this should only run once
useEffect(() => {
if (!startsHydrated.current && isHydrated) {
return;
}

if (!listing) {
return;
}

setFirstUploaded(
<RelativeTime time={listing.datetime_created} suppressHydrationWarning />
);
}, []);
// END: For sidebar meta dates

const currentTab = location.pathname.split("/")[8] || "details";

if (!listing) {
Expand All @@ -175,42 +137,31 @@ export default function PackageVersion() {

return (
<>
<Suspense>
<Await resolve={community}>
{(resolvedCommunity) => (
<>
<meta
title={`${formatToDisplayName(
listing.full_version_name
)} | Thunderstore - The ${resolvedCommunity.name} Mod Database`}
/>
<meta name="description" content={listing.description} />
<meta property="og:type" content="website" />
<meta
property="og:url"
content={`${
getPublicEnvVariables(["VITE_BETA_SITE_URL"])
.VITE_BETA_SITE_URL
}${location.pathname}`}
/>
<meta
property="og:title"
content={`${formatToDisplayName(
listing.full_version_name
)} by ${listing.namespace}`}
/>
<meta property="og:description" content={listing.description} />
<meta property="og:image:width" content="256" />
<meta property="og:image:height" content="256" />
<meta
property="og:image"
content={listing.icon_url ?? undefined}
/>
<meta property="og:site_name" content="Thunderstore" />
</>
)}
</Await>
</Suspense>
<meta
title={`${formatToDisplayName(
listing.full_version_name
)} | Thunderstore - The ${listing.community_name} Mod Database`}
/>
Comment on lines +140 to +144
Copy link

@coderabbitai coderabbitai bot Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix invalid title attribute on <meta> tag.

Line 140 uses <meta title={...}> which is invalid HTML. For setting the document title in React 19, use <title>{...}</title> instead.

🔎 Apply this diff to fix the title tag:
-      <meta
-        title={`${formatToDisplayName(
-          listing.full_version_name
-        )} | Thunderstore - The ${listing.community_name} Mod Database`}
-      />
+      <title>
+        {`${formatToDisplayName(
+          listing.full_version_name
+        )} | Thunderstore - The ${listing.community_name} Mod Database`}
+      </title>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<meta
title={`${formatToDisplayName(
listing.full_version_name
)} | Thunderstore - The ${listing.community_name} Mod Database`}
/>
<title>
{`${formatToDisplayName(
listing.full_version_name
)} | Thunderstore - The ${listing.community_name} Mod Database`}
</title>
🤖 Prompt for AI Agents
In apps/cyberstorm-remix/app/p/packageListingVersion.tsx around lines 140 to
144, the JSX uses an invalid <meta title={...}> attribute; replace that meta tag
with a proper <title>{...}</title> element (rendered inside the document head or
the component that controls the page head) so the document title is set
correctly in React 19, keeping the same formatted string
`${formatToDisplayName(listing.full_version_name)} | Thunderstore - The
${listing.community_name} Mod Database`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Oksamies do you reckon this is a valid issue? Would affect other pages as well if it is.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

<meta name="description" content={listing.description} />
<meta property="og:type" content="website" />
<meta
property="og:url"
content={`${
getPublicEnvVariables(["VITE_BETA_SITE_URL"]).VITE_BETA_SITE_URL
}${location.pathname}`}
/>
<meta
property="og:title"
content={`${formatToDisplayName(listing.full_version_name)} by ${
listing.namespace
}`}
/>
<meta property="og:description" content={listing.description} />
<meta property="og:image:width" content="256" />
<meta property="og:image:height" content="256" />
<meta property="og:image" content={listing.icon_url ?? undefined} />
<meta property="og:site_name" content="Thunderstore" />

<div className="container container--y container--full">
<section className="package-listing__package-section">
<div className="package-listing__main">
Expand Down Expand Up @@ -289,7 +240,7 @@ export default function PackageVersion() {
}
rootClasses="package-listing__drawer"
>
{packageMeta(firstUploaded, listing)}
{packageMeta(listing)}
</Drawer>
<Suspense fallback={<p>Loading...</p>}>
<Await resolve={team}>
Expand Down Expand Up @@ -379,7 +330,7 @@ export default function PackageVersion() {
</Await>
</Suspense>

{packageMeta(firstUploaded, listing)}
{packageMeta(listing)}
</div>
</aside>
</div>
Expand Down Expand Up @@ -424,15 +375,17 @@ const Actions = memo(function Actions(props: {
);
});

function packageMeta(
firstUploaded: ReactElement | undefined,
listing: PackageListingDetails
) {
function packageMeta(listing: PackageListingDetails) {
return (
<div className="package-listing-sidebar__meta">
<div className="package-listing-sidebar__item">
<div className="package-listing-sidebar__label">Date Uploaded</div>
<div className="package-listing-sidebar__content">{firstUploaded}</div>
<div className="package-listing-sidebar__content">
<RelativeTime
time={listing.datetime_created}
suppressHydrationWarning
/>
</div>
</div>
<div className="package-listing-sidebar__item">
<div className="package-listing-sidebar__label">Downloads</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/cyberstorm-remix/app/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default [
]),
route(
":namespaceId/:packageId/v/:packageVersion",
"p/packageVersion.tsx",
"p/packageListingVersion.tsx",
[
route(
"/c/:communityId/p/:namespaceId/:packageId/v/:packageVersion/",
Expand Down
Loading