mirror of
https://github.com/immich-app/static-pages.git
synced 2026-09-30 13:23:05 +08:00
feat: blog feed (#221)
This commit is contained in:
@@ -5,6 +5,9 @@
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="currentColor" />
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/blog/feed.xml" />
|
||||
<link rel="alternate" type="application/atom+xml" title="Atom Feed" href="/blog/atom.xml" />
|
||||
<link rel="alternate" type="application/json" title="JSON Feed" href="/blog/feed.json" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover" class="dark bg-light text-dark">
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { feed } from '$lib/server';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
export const GET = () => new Response(feed.atom1(), { headers: { 'Content-Type': 'application/atom+xml' } });
|
||||
@@ -0,0 +1,5 @@
|
||||
import { feed } from '$lib/server';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
export const GET = () => new Response(feed.json1(), { headers: { 'Content-Type': 'application/json' } });
|
||||
@@ -0,0 +1,5 @@
|
||||
import { feed } from '$lib/server';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
export const GET = () => new Response(feed.rss2(), { headers: { 'Content-Type': 'application/rss+xml' } });
|
||||
Generated
+37
-4
@@ -11,12 +11,13 @@
|
||||
"@mdi/js": "^7.4.47",
|
||||
"bits-ui": "^2.9.6",
|
||||
"exifreader": "^4.31.2",
|
||||
"feed": "^5.1.0",
|
||||
"luxon": "^3.7.2",
|
||||
"p-limit": "^7.1.1",
|
||||
"simple-icons": "^15.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@immich/ui": "^0.33.0",
|
||||
"@immich/ui": "^0.34.1",
|
||||
"@sveltejs/adapter-static": "^3.0.9",
|
||||
"@sveltejs/kit": "^2.37.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.4",
|
||||
@@ -698,14 +699,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@immich/ui": {
|
||||
"version": "0.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.33.0.tgz",
|
||||
"integrity": "sha512-zLshH4XbHP/wsOkmf7Q8PcrCJVQ2ZhBhhYXFP5vB+xw2lmekdblnJUje/UM/y/9D/HMJ9ptF2iXNKmWy0zX4dw==",
|
||||
"version": "0.34.1",
|
||||
"resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.34.1.tgz",
|
||||
"integrity": "sha512-40VahJ1JRGsmTYh388Rxb37XXELJNHPkNbc/VkLS1yJKCohfqsoxe8tiTBaIv+uunz4jo6yY6/Airg00Eks91A==",
|
||||
"dev": true,
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"dependencies": {
|
||||
"@mdi/js": "^7.4.47",
|
||||
"bits-ui": "^2.9.8",
|
||||
"luxon": "^3.7.2",
|
||||
"simple-icons": "^15.14.0",
|
||||
"tailwind-merge": "^3.0.0",
|
||||
"tailwind-variants": "^3.0.0"
|
||||
@@ -2815,6 +2817,19 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/feed": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/feed/-/feed-5.1.0.tgz",
|
||||
"integrity": "sha512-qGNhgYygnefSkAHHrNHqC7p3R8J0/xQDS/cYUud8er/qD9EFGWyCdUDfULHTJQN1d3H3WprzVwMc9MfB4J50Wg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20",
|
||||
"pnpm": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
@@ -4035,6 +4050,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
@@ -4977,6 +4998,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xml-js": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"xml-js": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||
|
||||
+2
-1
@@ -15,7 +15,7 @@
|
||||
"format:fix": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@immich/ui": "^0.33.0",
|
||||
"@immich/ui": "^0.34.1",
|
||||
"@sveltejs/adapter-static": "^3.0.9",
|
||||
"@sveltejs/kit": "^2.37.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.1.4",
|
||||
@@ -47,6 +47,7 @@
|
||||
"@mdi/js": "^7.4.47",
|
||||
"bits-ui": "^2.9.6",
|
||||
"exifreader": "^4.31.2",
|
||||
"feed": "^5.1.0",
|
||||
"luxon": "^3.7.2",
|
||||
"p-limit": "^7.1.1",
|
||||
"simple-icons": "^15.9.0"
|
||||
|
||||
@@ -2,9 +2,12 @@ import { DateTime } from 'luxon';
|
||||
import { PUBLIC_IMMICH_ENV } from '$env/static/public';
|
||||
|
||||
export type BlogPost = {
|
||||
/** uuid-v7, which can be generated with `npx -y uuid v7` */
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
publishedAt: DateTime;
|
||||
modifiedAt?: DateTime;
|
||||
authors: string[];
|
||||
url: string;
|
||||
isDraft?: boolean;
|
||||
@@ -12,6 +15,7 @@ export type BlogPost = {
|
||||
|
||||
export const Posts = {
|
||||
ImmichUi: {
|
||||
id: '0199bf43-cfec-769c-95a8-2ff1c9774fb0',
|
||||
title: 'New Svelte component library',
|
||||
description: 'Learn more about the Svelte component library that is powering this and other Immich websites.',
|
||||
publishedAt: DateTime.fromObject({ year: 2025, month: 9, day: 25 }),
|
||||
@@ -19,6 +23,7 @@ export const Posts = {
|
||||
url: '/blog/immich-ui',
|
||||
},
|
||||
NewSyncImplementation: {
|
||||
id: '0199bf43-a42d-75e8-9cab-06041f89ed14',
|
||||
title: 'Sync v2',
|
||||
description: 'Learn how Immich developed a better way to synchronize data with the mobile app.',
|
||||
publishedAt: DateTime.fromObject({ year: 2025, month: 9, day: 24 }),
|
||||
@@ -26,6 +31,7 @@ export const Posts = {
|
||||
url: '/blog/sync-v2',
|
||||
},
|
||||
CursedKnowledge: {
|
||||
id: '0199bf43-7a22-7778-a514-2db731e3c99d',
|
||||
title: 'Cursed knowledge',
|
||||
description:
|
||||
"The story behind the Cursed Knowledge page and how we gained the knowledge we have that we wish we didn't.",
|
||||
@@ -34,6 +40,7 @@ export const Posts = {
|
||||
url: '/blog/cursed-knowledge',
|
||||
},
|
||||
ImmichApi: {
|
||||
id: '0199bf43-5985-714c-8e5c-aa94e65a0176',
|
||||
title: 'New API documentation',
|
||||
description: 'The Immich API documentation has been moved to a new home.',
|
||||
publishedAt: DateTime.fromObject({ year: 2025, month: 9, day: 23 }),
|
||||
@@ -41,6 +48,7 @@ export const Posts = {
|
||||
url: '/blog/immich-api-documentation',
|
||||
},
|
||||
ImmichStore: {
|
||||
id: '0199bf43-3627-71fe-9747-35d71cb778eb',
|
||||
title: 'Immich launches merch',
|
||||
description: 'The Immich merch store is now live! Get your swag today, and learn about our new mascot, Mich.',
|
||||
publishedAt: DateTime.fromObject({ year: 2025, month: 2, day: 27 }),
|
||||
@@ -48,6 +56,7 @@ export const Posts = {
|
||||
url: '/blog/immich-merch',
|
||||
},
|
||||
YearInReview2024: {
|
||||
id: '0199bf43-0a6d-720b-ba24-cb6e8277693e',
|
||||
title: '2024 - A year in review',
|
||||
description: 'A review of the major milestones and accomplishments in 2024.',
|
||||
publishedAt: DateTime.fromObject({ year: 2024, month: 12, day: 30 }),
|
||||
@@ -55,6 +64,7 @@ export const Posts = {
|
||||
url: '/blog/2024-year-in-review',
|
||||
},
|
||||
PurchaseImmich: {
|
||||
id: '0199bf42-e615-76ad-8bf5-351584cc59c1',
|
||||
title: 'Immich introduces product keys',
|
||||
description: 'Purchase a product key to support Immich development, FUTO, and open source software.',
|
||||
publishedAt: DateTime.fromObject({ year: 2024, month: 7, day: 18 }),
|
||||
@@ -62,6 +72,7 @@ export const Posts = {
|
||||
url: '/blog/immich-product-keys',
|
||||
},
|
||||
ImmichJoinsFuto: {
|
||||
id: '0199bf42-bd9c-7461-86a7-2487f13b6e8b',
|
||||
title: 'Immich joins FUTO',
|
||||
description: 'The core team goes full-time on Immich as part of FUTO.',
|
||||
publishedAt: DateTime.fromObject({ year: 2024, month: 5, day: 1 }),
|
||||
@@ -69,6 +80,7 @@ export const Posts = {
|
||||
url: '/blog/immich-joins-futo',
|
||||
},
|
||||
YearInReview2023: {
|
||||
id: '0199bf42-8ee2-70cd-b6ad-02222625932b',
|
||||
title: '2023 - A year in review',
|
||||
description: 'A review of the major milestones and accomplishments in 2023.',
|
||||
publishedAt: DateTime.fromObject({ year: 2023, month: 12, day: 30 }),
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { blogMetadata } from '$lib';
|
||||
import { posts } from '$lib/blog';
|
||||
import { Feed } from 'feed';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export const feed = new Feed({
|
||||
title: blogMetadata.title,
|
||||
description: blogMetadata.description,
|
||||
id: 'https://immich.app/blog',
|
||||
link: 'https://immich.app/blog',
|
||||
language: 'en',
|
||||
copyright: `Copyright © ${DateTime.now().year} FUTO. All rights reserved.`,
|
||||
favicon: 'https://immich.app/favicon.ico',
|
||||
});
|
||||
|
||||
for (const post of posts) {
|
||||
feed.addItem({
|
||||
title: post.title,
|
||||
id: post.id,
|
||||
link: 'https://immich.app' + post.url,
|
||||
description: post.description,
|
||||
author: post.authors.map((author) => ({ name: author })),
|
||||
date: (post.modifiedAt ?? post.publishedAt).toJSDate(),
|
||||
published: post.publishedAt.toJSDate(),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user