Skip to content

Commit 5bf7c06

Browse files
committed
feat: enhance Open Graph image generation for homepage
- Added a new endpoint to render a homepage Open Graph image with site statistics and featured photos. - Introduced a new template for the homepage Open Graph image, including site name, description, author avatar, and featured photos. - Updated the Open Graph service to handle rendering of the new homepage image. - Implemented emoji loading functionality for enhanced visual representation in Open Graph images. Signed-off-by: Innei <[email protected]>
1 parent b5b4c9b commit 5bf7c06

File tree

21 files changed

+958
-299
lines changed

21 files changed

+958
-299
lines changed

apps/docs/contents/getting-started/quick-start.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Quick Start
33
description: Get your gallery running in about 5 minutes.
44
createdAt: 2025-11-14T22:20:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 2
77
---
88

@@ -109,3 +109,5 @@ Deploy to Vercel or any Node.js host. See [Vercel Deployment](/deployment/vercel
109109
- **Deploy**: Follow the [Deployment Guide](/deployment) for your platform
110110
- **Learn more**: Check out [Architecture](/architecture) and [Builder](/builder) documentation
111111

112+
113+

apps/docs/contents/storage/providers/b2.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: B2 (Backblaze B2)
33
description: Configure Backblaze B2 storage for cost-effective cloud storage.
44
createdAt: 2025-11-14T22:10:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 33
77
---
88

@@ -94,3 +94,5 @@ Compare with AWS S3 to see which fits your usage pattern better.
9494
- B2 has generous rate limits, but very high concurrency may still hit limits
9595
- Reduce concurrency if needed
9696

97+
98+

apps/docs/contents/storage/providers/eagle.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Eagle Storage
33
description: Publish directly from an Eagle 4 library with filtering support.
44
createdAt: 2025-11-14T22:10:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 36
77
---
88

@@ -163,3 +163,5 @@ This creates tags in the manifest based on folder structure, useful for organizi
163163
- Check that `baseUrl` matches your web server
164164
- Ensure the destination directory exists
165165

166+
167+

apps/docs/contents/storage/providers/github.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: GitHub Storage
33
description: Use a GitHub repository as photo storage for simple deployments.
44
createdAt: 2025-11-14T22:10:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 34
77
---
88

@@ -98,3 +98,5 @@ For private repositories:
9898
- Ensure no individual file exceeds ~100MB
9999
- Consider compressing large photos or using a different provider
100100

101+
102+

apps/docs/contents/storage/providers/index.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Storage Providers
33
description: Choose a storage provider for your photo collection.
44
createdAt: 2025-11-14T22:40:00+08:00
5-
lastModified: 2025-11-24T22:26:48+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 30
77
---
88

@@ -109,3 +109,5 @@ export default defineBuilderConfig(() => ({
109109
Credentials and sensitive information should be stored in `.env` and referenced via `process.env`.
110110

111111
See each provider's documentation for specific configuration options.
112+
113+

apps/docs/contents/storage/providers/local.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Local Storage
33
description: Use local file system paths for development and self-hosting.
44
createdAt: 2025-11-14T22:10:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 35
77
---
88

@@ -132,3 +132,5 @@ If you want to serve original photos:
132132
- Check that `baseUrl` matches your web server configuration
133133
- Ensure the destination directory exists
134134

135+
136+

apps/docs/contents/storage/providers/s3.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: S3 / S3-Compatible
33
description: Configure S3 or S3-compatible storage for your photo collection.
44
createdAt: 2025-11-14T22:10:00+08:00
5-
lastModified: 2025-11-23T19:40:52+08:00
5+
lastModified: 2025-11-25T17:23:59+08:00
66
order: 32
77
---
88

@@ -119,3 +119,5 @@ This prevents processing temporary or system files.
119119
- For non-AWS services, ensure `endpoint` is correctly configured
120120
- Check that the endpoint URL format matches your provider's requirements
121121

122+
123+

apps/landing/src/components/landing/NocturneSections.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const NocturneHero = () => {
4444
<div className="grid gap-6 lg:grid-cols-[1.35fr,1fr]">
4545
<div className="mt-4 aspect-4/3 w-full overflow-hidden rounded-2xl border border-white/10">
4646
<img
47-
src="https://github.com/Afilmory/assets/blob/main/afilmory-readme.webp?raw=true"
47+
src="https://cdn.jsdelivr.net/gh/Afilmory/assets/afilmory-readme.webp"
4848
alt={t('preview.imageAlt')}
4949
className="h-full w-full object-cover"
5050
/>

be/apps/core/src/modules/content/og/og.controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import { OgService } from './og.service'
77
export class OgController {
88
constructor(private readonly ogService: OgService) {}
99

10+
@Get('/')
11+
async getHomepageOgImage(@ContextParam() context: Context) {
12+
return await this.ogService.renderHomepage(context)
13+
}
14+
1015
@Get('/:photoId')
1116
async getOgImage(@ContextParam() context: Context, @Param('photoId') photoId: string) {
1217
return await this.ogService.render(context, photoId)

be/apps/core/src/modules/content/og/og.renderer.tsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { Resvg } from '@resvg/resvg-js'
55
import type { SatoriOptions } from 'satori'
66
import satori from 'satori'
77

8-
import type { OgTemplateProps } from './og.template'
9-
import { OgTemplate } from './og.template'
8+
import type { HomepageOgTemplateProps, OgTemplateProps } from './og.template'
9+
import { HomepageOgTemplate, OgTemplate } from './og.template'
10+
import { get_icon_code, load_emoji } from './tweemoji'
1011

1112
interface RenderOgImageOptions {
1213
template: OgTemplateProps
@@ -29,3 +30,31 @@ export async function renderOgImage({ template, fonts }: RenderOgImageOptions):
2930

3031
return renderer.render().asPng()
3132
}
33+
34+
interface RenderHomepageOgImageOptions {
35+
template: HomepageOgTemplateProps
36+
fonts: SatoriOptions['fonts']
37+
}
38+
39+
export async function renderHomepageOgImage({ template, fonts }: RenderHomepageOgImageOptions): Promise<Uint8Array> {
40+
const svg = await satori(<HomepageOgTemplate {...template} />, {
41+
width: 1200,
42+
height: 628,
43+
fonts,
44+
embedFont: true,
45+
async loadAdditionalAsset(code, segment) {
46+
if (code === 'emoji' && segment) {
47+
return `data:image/svg+xml;base64,${btoa(await load_emoji(get_icon_code(segment)))}`
48+
}
49+
return ''
50+
},
51+
})
52+
53+
const svgInput = typeof svg === 'string' ? svg : Buffer.from(svg)
54+
const renderer = new Resvg(svgInput, {
55+
fitTo: { mode: 'width', value: 1200 },
56+
background: 'rgba(0,0,0,0)',
57+
})
58+
59+
return renderer.render().asPng()
60+
}

0 commit comments

Comments
 (0)