Skip to content

Commit b1f9dc7

Browse files
authored
Merge pull request #5 from knowall-ai/claude/add-social-preview-cKRAZ
feat: Add social media preview images and Open Graph meta tags
2 parents e87f4f7 + 700be6c commit b1f9dc7

6 files changed

Lines changed: 296 additions & 1 deletion

File tree

public/social-preview.svg

Lines changed: 69 additions & 0 deletions
Loading

src/app/layout.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,32 @@ const inter = Inter({ subsets: ['latin'] });
99
export const metadata: Metadata = {
1010
title: 'Thyme - Time Tracking for Business Central | KnowAll.ai',
1111
description:
12-
'Modern time tracking application that syncs with Microsoft Dynamics 365 Business Central. Built by KnowAll.ai.',
12+
'Modern time tracking application that syncs with Microsoft Dynamics 365 Business Central. Track time, manage projects, and keep your data in sync. Built by KnowAll.ai.',
1313
keywords: ['time tracking', 'business central', 'dynamics 365', 'timesheet', 'knowall'],
14+
authors: [{ name: 'KnowAll.ai', url: 'https://knowall.ai' }],
15+
creator: 'KnowAll.ai',
16+
publisher: 'KnowAll.ai',
17+
metadataBase: new URL('https://thyme.knowall.ai'),
18+
openGraph: {
19+
title: 'Thyme - Time Tracking for Business Central',
20+
description:
21+
'Modern time tracking application that syncs with Microsoft Dynamics 365 Business Central. Track time, manage projects, and keep your data in sync.',
22+
url: 'https://thyme.knowall.ai',
23+
siteName: 'Thyme by KnowAll.ai',
24+
locale: 'en_US',
25+
type: 'website',
26+
},
27+
twitter: {
28+
card: 'summary_large_image',
29+
title: 'Thyme - Time Tracking for Business Central',
30+
description:
31+
'Modern time tracking that syncs with Microsoft Dynamics 365 Business Central. Built by KnowAll.ai.',
32+
creator: '@knowall_ai',
33+
},
34+
robots: {
35+
index: true,
36+
follow: true,
37+
},
1438
};
1539

1640
export default function RootLayout({ children }: { children: React.ReactNode }) {

src/app/opengraph-image.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ImageResponse } from 'next/og';
2+
import { SocialImageContent } from '@/components/social';
3+
4+
export const runtime = 'edge';
5+
6+
export const alt = 'Thyme - Time Tracking for Business Central';
7+
export const size = {
8+
width: 1200,
9+
height: 630,
10+
};
11+
export const contentType = 'image/png';
12+
13+
export default async function Image() {
14+
return new ImageResponse(<SocialImageContent />, {
15+
...size,
16+
});
17+
}

src/app/twitter-image.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ImageResponse } from 'next/og';
2+
import { SocialImageContent } from '@/components/social';
3+
4+
export const runtime = 'edge';
5+
6+
export const alt = 'Thyme - Time Tracking for Business Central';
7+
export const size = {
8+
width: 1200,
9+
height: 630,
10+
};
11+
export const contentType = 'image/png';
12+
13+
export default async function Image() {
14+
return new ImageResponse(<SocialImageContent />, {
15+
...size,
16+
});
17+
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* Shared JSX content for Open Graph and Twitter social preview images.
3+
* Used by both opengraph-image.tsx and twitter-image.tsx to avoid duplication.
4+
*/
5+
export function SocialImageContent() {
6+
return (
7+
<div
8+
style={{
9+
background: 'linear-gradient(135deg, #020617 0%, #0f172a 50%, #020617 100%)',
10+
width: '100%',
11+
height: '100%',
12+
display: 'flex',
13+
flexDirection: 'column',
14+
alignItems: 'center',
15+
justifyContent: 'center',
16+
fontFamily: 'Inter, system-ui, sans-serif',
17+
position: 'relative',
18+
}}
19+
>
20+
{/* Grid pattern overlay */}
21+
<div
22+
style={{
23+
position: 'absolute',
24+
top: 0,
25+
left: 0,
26+
right: 0,
27+
bottom: 0,
28+
backgroundImage:
29+
'linear-gradient(to right, rgba(30, 41, 59, 0.3) 1px, transparent 1px), linear-gradient(to bottom, rgba(30, 41, 59, 0.3) 1px, transparent 1px)',
30+
backgroundSize: '60px 60px',
31+
}}
32+
/>
33+
34+
{/* Gradient glow effect */}
35+
<div
36+
style={{
37+
position: 'absolute',
38+
top: '50%',
39+
left: '50%',
40+
transform: 'translate(-50%, -50%)',
41+
width: '800px',
42+
height: '800px',
43+
background: 'radial-gradient(circle, rgba(0, 210, 106, 0.15) 0%, transparent 70%)',
44+
borderRadius: '50%',
45+
}}
46+
/>
47+
48+
{/* Logo and brand */}
49+
<div
50+
style={{
51+
display: 'flex',
52+
alignItems: 'center',
53+
gap: '20px',
54+
marginBottom: '40px',
55+
}}
56+
>
57+
{/* Clock icon in green box */}
58+
<div
59+
style={{
60+
width: '80px',
61+
height: '80px',
62+
borderRadius: '16px',
63+
background: '#00D26A',
64+
display: 'flex',
65+
alignItems: 'center',
66+
justifyContent: 'center',
67+
boxShadow: '0 0 40px rgba(0, 210, 106, 0.4)',
68+
}}
69+
>
70+
<svg
71+
width="48"
72+
height="48"
73+
viewBox="0 0 24 24"
74+
fill="none"
75+
stroke="#020617"
76+
strokeWidth="2.5"
77+
strokeLinecap="round"
78+
strokeLinejoin="round"
79+
>
80+
<circle cx="12" cy="12" r="10" />
81+
<polyline points="12,6 12,12 16,14" />
82+
</svg>
83+
</div>
84+
<div style={{ display: 'flex', flexDirection: 'column' }}>
85+
<span
86+
style={{
87+
fontSize: '64px',
88+
fontWeight: 700,
89+
color: 'white',
90+
letterSpacing: '-1px',
91+
}}
92+
>
93+
Thyme
94+
</span>
95+
<span
96+
style={{
97+
fontSize: '24px',
98+
color: '#94a3b8',
99+
marginTop: '-8px',
100+
}}
101+
>
102+
by KnowAll.ai
103+
</span>
104+
</div>
105+
</div>
106+
107+
{/* Tagline */}
108+
<div
109+
style={{
110+
display: 'flex',
111+
flexDirection: 'column',
112+
alignItems: 'center',
113+
gap: '8px',
114+
}}
115+
>
116+
<span
117+
style={{
118+
fontSize: '42px',
119+
fontWeight: 600,
120+
color: 'white',
121+
}}
122+
>
123+
Time Tracking,
124+
</span>
125+
<span
126+
style={{
127+
fontSize: '42px',
128+
fontWeight: 600,
129+
color: '#00D26A',
130+
}}
131+
>
132+
Perfectly Synced
133+
</span>
134+
</div>
135+
136+
{/* Subtitle */}
137+
<div
138+
style={{
139+
marginTop: '32px',
140+
display: 'flex',
141+
alignItems: 'center',
142+
gap: '12px',
143+
padding: '12px 24px',
144+
background: 'rgba(30, 41, 59, 0.6)',
145+
borderRadius: '100px',
146+
border: '1px solid rgba(51, 65, 85, 0.8)',
147+
}}
148+
>
149+
{/* Microsoft logo */}
150+
<svg width="24" height="24" viewBox="0 0 21 21" fill="none">
151+
<rect x="1" y="1" width="9" height="9" fill="#F25022" />
152+
<rect x="11" y="1" width="9" height="9" fill="#7FBA00" />
153+
<rect x="1" y="11" width="9" height="9" fill="#00A4EF" />
154+
<rect x="11" y="11" width="9" height="9" fill="#FFB900" />
155+
</svg>
156+
<span
157+
style={{
158+
fontSize: '20px',
159+
color: '#cbd5e1',
160+
}}
161+
>
162+
Powered by Microsoft Dynamics 365 Business Central
163+
</span>
164+
</div>
165+
</div>
166+
);
167+
}

src/components/social/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { SocialImageContent } from './SocialImageContent';

0 commit comments

Comments
 (0)