Vercel/app/sitemap.ts
Sam Becker 70f6f48044
Exclude photo from feeds (#280)
* Add tooltip to 'hidden' checkbox

* Refine checkbox UI

* Allow photos to be excluded from main feeds

* Fix footer grid in photos excluded from feed

* Apply feed exclusion from batch upload

* Scrub final hidden/private language

* Add visibility icons to admin photo menu
2025-07-05 23:40:58 -05:00

141 lines
3.8 KiB
TypeScript

import type { MetadataRoute } from 'next';
import { getDataForCategoriesCached } from '@/category/cache';
import {
ABSOLUTE_PATH_FULL,
ABSOLUTE_PATH_GRID,
absolutePathForCamera,
absolutePathForFilm,
absolutePathForFocalLength,
absolutePathForLens,
absolutePathForPhoto,
absolutePathForRecents,
absolutePathForRecipe,
absolutePathForTag,
absolutePathForYear,
} from '@/app/paths';
import { isTagFavs } from '@/tag';
import { BASE_URL, GRID_HOMEPAGE_ENABLED } from '@/app/config';
import { getPhotoIdsAndUpdatedAt } from '@/photo/db/query';
// Cache for 24 hours
export const revalidate = 86_400;
const PRIORITY_HOME = 1;
const PRIORITY_HOME_VIEW = 0.9;
const PRIORITY_CATEGORY_SPECIAL = 0.8;
const PRIORITY_CATEGORY = 0.7;
const PRIORITY_PHOTO = 0.5;
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const [
{
recents,
years,
cameras,
lenses,
tags,
recipes,
films,
focalLengths,
},
photos,
] = await Promise.all([
getDataForCategoriesCached().catch(() => ({
recents: [],
years: [],
cameras: [],
lenses: [],
tags: [],
recipes: [],
films: [],
focalLengths: [],
})),
getPhotoIdsAndUpdatedAt().catch(() => []),
]);
const lastModifiedSite = [
...recents.map(({ lastModified }) => lastModified),
...years.map(({ lastModified }) => lastModified),
...cameras.map(({ lastModified }) => lastModified),
...lenses.map(({ lastModified }) => lastModified),
...tags.map(({ lastModified }) => lastModified),
...recipes.map(({ lastModified }) => lastModified),
...films.map(({ lastModified }) => lastModified),
...focalLengths.map(({ lastModified }) => lastModified),
...photos.map(({ updatedAt }) => updatedAt),
]
.filter(date => date instanceof Date)
.sort((a, b) => b.getTime() - a.getTime())[0];
return [
// Homepage
{
url: BASE_URL!,
priority: PRIORITY_HOME,
lastModified: lastModifiedSite,
},
// Grid or full
{
url: GRID_HOMEPAGE_ENABLED ? ABSOLUTE_PATH_FULL : ABSOLUTE_PATH_GRID,
priority: PRIORITY_HOME_VIEW,
lastModified: lastModifiedSite,
},
// Recents
...recents.map(({ lastModified }) => ({
url: absolutePathForRecents(),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Years
...years.map(({ year, lastModified }) => ({
url: absolutePathForYear(year),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Cameras
...cameras.map(({ camera, lastModified }) => ({
url: absolutePathForCamera(camera),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Lenses
...lenses.map(({ lens, lastModified }) => ({
url: absolutePathForLens(lens),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Tags
...tags.map(({ tag, lastModified }) => ({
url: absolutePathForTag(tag),
priority: isTagFavs(tag)
? PRIORITY_CATEGORY_SPECIAL
: PRIORITY_CATEGORY,
lastModified,
})),
// Recipes
...recipes.map(({ recipe, lastModified }) => ({
url: absolutePathForRecipe(recipe),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Films
...films.map(({ film, lastModified }) => ({
url: absolutePathForFilm(film),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Focal Lengths
...focalLengths.map(({ focal, lastModified }) => ({
url: absolutePathForFocalLength(focal),
priority: PRIORITY_CATEGORY,
lastModified,
})),
// Photos
...photos.map(({ id, updatedAt }) => ({
url: absolutePathForPhoto({ photo: id }),
priority: PRIORITY_PHOTO,
lastModified: updatedAt,
})),
];
}