feat(ssr): add sitemap generator
This commit is contained in:
parent
4b966aaaae
commit
41d1d5f1d7
3
.gitignore
vendored
3
.gitignore
vendored
@ -42,3 +42,6 @@ next-env.d.ts
|
||||
|
||||
# Webpack bundle analyzer
|
||||
analyze
|
||||
|
||||
# Sitemap
|
||||
public/sitemap*
|
@ -38,6 +38,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/package.json ./package.json
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/next.config.js ./next.config.js
|
||||
|
||||
# Generate sitemap
|
||||
RUN npm run generate-sitemap
|
||||
|
||||
USER nextjs
|
||||
EXPOSE 80
|
||||
ENV HOSTNAME "0.0.0.0"
|
||||
|
54
next-sitemap.config.js
Normal file
54
next-sitemap.config.js
Normal file
@ -0,0 +1,54 @@
|
||||
const ssrSettings = require("./src/ssrSettings");
|
||||
const { getCodeList } = require("country-list");
|
||||
|
||||
const SS_API_URL = ssrSettings.proxy + "/https://scoresaber.com/api";
|
||||
const SS_GET_PLAYERS_URL = SS_API_URL + "/players?page={}";
|
||||
|
||||
async function getTopPlayers() {
|
||||
console.log("Fetching top players...");
|
||||
const players = [];
|
||||
const pagesToFetch = 25;
|
||||
for (let i = 0; i < pagesToFetch; i++) {
|
||||
console.log(`Fetching page ${i + 1} of ${pagesToFetch}...`);
|
||||
const response = await fetch(SS_GET_PLAYERS_URL.replace("{}", i));
|
||||
const data = await response.json();
|
||||
players.push(...data.players);
|
||||
}
|
||||
console.log("Done fetching top players.");
|
||||
return players;
|
||||
}
|
||||
|
||||
/** @type {import('next-sitemap').IConfig} */
|
||||
module.exports = {
|
||||
siteUrl: ssrSettings.siteUrl,
|
||||
generateRobotsTxt: true,
|
||||
additionalPaths: async (config) => {
|
||||
const paths = [];
|
||||
// Add the top 50 global ranking pages
|
||||
for (let i = 0; i < 50; i++) {
|
||||
paths.push({
|
||||
loc: `/ranking/global/${i + 1}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Add the top 50 pages for all countries
|
||||
const countries = Object.keys(getCodeList());
|
||||
for (const country of countries) {
|
||||
for (let i = 0; i < 50; i++) {
|
||||
paths.push({
|
||||
loc: `/ranking/country/${country}/${i + 1}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add top players
|
||||
const players = await getTopPlayers();
|
||||
for (const player of players) {
|
||||
paths.push({
|
||||
loc: `/player/${player.id}/top/1`,
|
||||
});
|
||||
}
|
||||
|
||||
return paths;
|
||||
},
|
||||
};
|
43
package-lock.json
generated
43
package-lock.json
generated
@ -23,12 +23,14 @@
|
||||
"chart.js": "^4.4.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"country-list": "^2.3.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"encoding": "^0.1.13",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lucide-react": "^0.292.0",
|
||||
"next": "14.0.1",
|
||||
"next-build-id": "^3.0.0",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"next-themes": "^0.2.1",
|
||||
"node-fetch-cache": "^3.1.3",
|
||||
"react": "^18",
|
||||
@ -95,6 +97,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@boiseitguru/cookie-cutter/-/cookie-cutter-0.2.1.tgz",
|
||||
"integrity": "sha512-MLYTqtyECvjq+Wjq2k++bXReIlClTrtpSWSXeamp868MWKggn6SanFBZRVhI61isf3ETuvmDJObexW36Ck4SCQ=="
|
||||
},
|
||||
"node_modules/@corex/deepmerge": {
|
||||
"version": "4.0.43",
|
||||
"resolved": "https://registry.npmjs.org/@corex/deepmerge/-/deepmerge-4.0.43.tgz",
|
||||
"integrity": "sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ=="
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
@ -2464,6 +2471,11 @@
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/country-list": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/country-list/-/country-list-2.3.0.tgz",
|
||||
"integrity": "sha512-qZk66RlmQm7fQjMYWku1AyjlKPogjPEorAZJG88owPExoPV8EsyCcuFLvO2afTXHEhi9liVOoyd+5A6ZS5QwaA=="
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
@ -4788,6 +4800,37 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/next-sitemap": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.2.3.tgz",
|
||||
"integrity": "sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/iamvishnusankar/next-sitemap.git"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@corex/deepmerge": "^4.0.43",
|
||||
"@next/env": "^13.4.3",
|
||||
"fast-glob": "^3.2.12",
|
||||
"minimist": "^1.2.8"
|
||||
},
|
||||
"bin": {
|
||||
"next-sitemap": "bin/next-sitemap.mjs",
|
||||
"next-sitemap-cjs": "bin/next-sitemap.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/next-sitemap/node_modules/@next/env": {
|
||||
"version": "13.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz",
|
||||
"integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw=="
|
||||
},
|
||||
"node_modules/next-themes": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
|
||||
|
@ -5,6 +5,7 @@
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"generate-sitemap": "next-sitemap",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
@ -24,12 +25,14 @@
|
||||
"chart.js": "^4.4.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"country-list": "^2.3.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"encoding": "^0.1.13",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"lucide-react": "^0.292.0",
|
||||
"next": "14.0.1",
|
||||
"next-build-id": "^3.0.0",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"next-themes": "^0.2.1",
|
||||
"node-fetch-cache": "^3.1.3",
|
||||
"react": "^18",
|
||||
|
@ -1,2 +1,9 @@
|
||||
# *
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Allow: /
|
||||
|
||||
# Host
|
||||
Host: https://ssr.fascinated.cc
|
||||
|
||||
# Sitemaps
|
||||
Sitemap: https://ssr.fascinated.cc/sitemap.xml
|
||||
|
@ -2,7 +2,7 @@ import AnalyticsChart from "@/components/AnalyticsChart";
|
||||
import Card from "@/components/Card";
|
||||
import Container from "@/components/Container";
|
||||
import { ScoresaberMetricsHistory } from "@/schemas/fascinated/scoresaberMetricsHistory";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { formatNumber } from "@/utils/numberUtils";
|
||||
import { isProduction } from "@/utils/utils";
|
||||
import { Metadata } from "next";
|
||||
|
@ -1,5 +1,5 @@
|
||||
import AppProvider from "@/components/AppProvider";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import clsx from "clsx";
|
||||
import { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
|
@ -1,5 +1,5 @@
|
||||
import PlayerPage from "@/components/player/PlayerPage";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { formatNumber } from "@/utils/numberUtils";
|
||||
import { ScoreSaberAPI } from "@/utils/scoresaber/api";
|
||||
import { normalizedRegionName } from "@/utils/utils";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { isProduction } from "@/utils/utils";
|
||||
import Link from "next/link";
|
||||
import Card from "./Card";
|
||||
|
@ -125,7 +125,8 @@ export default function GlobalRanking({ page, country }: GlobalRankingProps) {
|
||||
<p>
|
||||
You are viewing{" "}
|
||||
{country
|
||||
? "scores from " + normalizedRegionName(country)
|
||||
? "scores from " +
|
||||
normalizedRegionName(country.toUpperCase())
|
||||
: "Global scores"}
|
||||
</p>
|
||||
</div>
|
||||
|
6
src/ssrSettings.json
Normal file
6
src/ssrSettings.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"siteName": "ScoreSaber Reloaded",
|
||||
"description": "Scoresaber Reloaded is a new way to view your scores and get more stats about your and your plays",
|
||||
"siteUrl": "https://ssr.fascinated.cc",
|
||||
"proxy": "https://proxy.fascinated.cc"
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export const ssrSettings = {
|
||||
siteName: "ScoreSaber Reloaded",
|
||||
description:
|
||||
"Scoresaber Reloaded is a new way to view your scores and get more stats about your and your plays",
|
||||
siteUrl: "https://ssr.fascinated.cc",
|
||||
proxy: "https://proxy.fascinated.cc",
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { BeatLeaderPlayer } from "@/schemas/beatleader/player";
|
||||
import { BeatleaderScore } from "@/schemas/beatleader/score";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { FetchQueue } from "../fetchWithQueue";
|
||||
import { formatString } from "../string";
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BeatsaverMap } from "@/schemas/beatsaver/BeatsaverMap";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { FetchQueue } from "../fetchWithQueue";
|
||||
import { formatString } from "../string";
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { ScoresaberLeaderboardInfo } from "@/schemas/scoresaber/leaderboard";
|
||||
import { ScoresaberPlayer } from "@/schemas/scoresaber/player";
|
||||
import { ScoresaberPlayerScore } from "@/schemas/scoresaber/playerScore";
|
||||
import { ScoresaberScore } from "@/schemas/scoresaber/score";
|
||||
import { ssrSettings } from "@/ssrSettings";
|
||||
import ssrSettings from "@/ssrSettings.json";
|
||||
import { FetchQueue } from "../fetchWithQueue";
|
||||
import { formatString } from "../string";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user