Skip to content

Commit 8efb29f

Browse files
committed
Init
1 parent 8c91979 commit 8efb29f

14 files changed

+252
-490
lines changed

README.md

+1-36
Original file line numberDiff line numberDiff line change
@@ -1,36 +1 @@
1-
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2-
3-
## Getting Started
4-
5-
First, run the development server:
6-
7-
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
# or
12-
pnpm dev
13-
# or
14-
bun dev
15-
```
16-
17-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18-
19-
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
20-
21-
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
22-
23-
## Learn More
24-
25-
To learn more about Next.js, take a look at the following resources:
26-
27-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29-
30-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31-
32-
## Deploy on Vercel
33-
34-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35-
36-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
1+
# gist-og

app/[id]/opengraph-image.jsx

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { highlight } from "@code-hike/lighter";
2+
import { ImageResponse } from "next/server";
3+
4+
// Route segment config
5+
export const runtime = "edge";
6+
7+
// Image metadata
8+
export const alt = "About Acme";
9+
export const size = {
10+
width: 1200,
11+
height: 630,
12+
};
13+
14+
export const contentType = "image/png";
15+
16+
// Image generation
17+
export default async function Image({ params }) {
18+
const gist = await fetchGist(params.id);
19+
const avatar = gist.owner.avatar_url;
20+
const owner = gist.owner.login;
21+
const filenames = Object.keys(gist.files);
22+
const file = gist.files[filenames[0]];
23+
const content = file.content;
24+
25+
const { lines, style } = await highlight(content, "jsx", "github-dark");
26+
27+
return new ImageResponse(
28+
(
29+
// ImageResponse JSX element
30+
<div
31+
style={{
32+
background: "white",
33+
width: "100%",
34+
maxWidth: "100%",
35+
height: "100%",
36+
display: "flex",
37+
alignItems: "center",
38+
justifyContent: "center",
39+
background: style.background,
40+
color: style.color,
41+
fontSize: "1.5em",
42+
display: "flex",
43+
flexDirection: "column",
44+
}}
45+
>
46+
<pre
47+
style={{
48+
display: "flex",
49+
flexDirection: "column",
50+
fontFamily: "monospace",
51+
background: style.background,
52+
color: style.color,
53+
whiteSpace: "pre",
54+
padding: "1em",
55+
maxHeight: "75%",
56+
maxWidth: "100%",
57+
}}
58+
>
59+
{lines.map((line, i) => (
60+
<>
61+
<div
62+
style={{
63+
display: "flex",
64+
flexDirection: "row",
65+
}}
66+
key={i}
67+
>
68+
{line.map((token, j) => (
69+
<span style={token.style} key={j}>
70+
{token.content}
71+
</span>
72+
))}
73+
</div>
74+
</>
75+
))}
76+
</pre>
77+
<div
78+
style={{
79+
minHeight: 0,
80+
borderTop: "1px solid #444",
81+
flexDirection: "row",
82+
display: "flex",
83+
gap: 24,
84+
background: style.background,
85+
width: "100%",
86+
padding: "0 12px",
87+
alignItems: "center",
88+
// justifyContent: "center",
89+
}}
90+
>
91+
<img
92+
src={avatar}
93+
width={90}
94+
height={90}
95+
style={{ borderRadius: 100, margin: "12px 0" }}
96+
/>
97+
<h1 style={{ fontSize: "1.5em", padding: 0, margin: 0 }}>
98+
{gist.description || file.filename}
99+
</h1>
100+
</div>
101+
</div>
102+
),
103+
// ImageResponse options
104+
{
105+
// For convenience, we can re-use the exported opengraph-image
106+
// size config to also set the ImageResponse's width and height.
107+
...size,
108+
}
109+
);
110+
}
111+
async function fetchGist(id) {
112+
const res = await fetch(`https://api.github.com/gists/${id}`);
113+
return await res.json();
114+
}

app/[id]/page.js

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { redirect } from "next/navigation";
2+
import { highlight } from "@code-hike/lighter";
3+
4+
export async function generateMetadata({ params, searchParams }) {
5+
const gist = await fetchGist(params.id);
6+
7+
return {
8+
title: gist.description,
9+
};
10+
}
11+
12+
export default async function Page({ params }) {
13+
redirect(`https://gist.github.com/${params.id}`);
14+
const gist = await fetchGist(params.id);
15+
const avatar = gist.owner?.avatar_url;
16+
const owner = gist.owner?.login;
17+
const filenames = Object.keys(gist.files);
18+
const file = gist.files[filenames[0]];
19+
const content = file.content;
20+
21+
const { lines, style } = await highlight(
22+
JSON.stringify(gist, null, 2),
23+
"json",
24+
"github-dark"
25+
);
26+
return (
27+
<div
28+
style={{
29+
background: "white",
30+
width: "100%",
31+
maxWidth: "100%",
32+
display: "flex",
33+
alignItems: "center",
34+
justifyContent: "center",
35+
background: style.background,
36+
color: style.color,
37+
fontSize: "1.5em",
38+
display: "flex",
39+
flexDirection: "column",
40+
height: 630,
41+
maxHeight: 630,
42+
}}
43+
>
44+
<pre
45+
style={{
46+
display: "flex",
47+
flexDirection: "column",
48+
fontFamily: "monospace",
49+
background: style.background,
50+
color: style.color,
51+
whiteSpace: "pre",
52+
padding: "1em",
53+
maxHeight: "70%",
54+
maxWidth: "100%",
55+
}}
56+
>
57+
{lines.map((line, i) => (
58+
<>
59+
<div
60+
style={{
61+
display: "flex",
62+
flexDirection: "row",
63+
}}
64+
key={i}
65+
>
66+
{line.map((token, j) => (
67+
<span style={token.style} key={j}>
68+
{token.content}
69+
</span>
70+
))}
71+
</div>
72+
</>
73+
))}
74+
</pre>
75+
<div
76+
style={{
77+
height: "25%",
78+
maxHeight: "25%",
79+
minHeight: 0,
80+
borderTop: "1px solid #444",
81+
flexDirection: "row",
82+
display: "flex",
83+
gap: 12,
84+
background: style.background,
85+
width: "100%",
86+
padding: 12,
87+
alignItems: "center",
88+
// justifyContent: "center",
89+
}}
90+
>
91+
<img
92+
src={avatar}
93+
width={90}
94+
height={90}
95+
style={{ borderRadius: 100 }}
96+
/>
97+
<h1 style={{ fontSize: "1.5em" }}>
98+
{gist.description || file.filename}
99+
</h1>
100+
</div>
101+
</div>
102+
);
103+
}
104+
105+
async function fetchGist(id) {
106+
const res = await fetch(`https://api.github.com/gists/${id}`);
107+
return await res.json();
108+
}

app/favicon.ico

-25.3 KB
Binary file not shown.

app/globals.css

-107
This file was deleted.

app/layout.js

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
import './globals.css'
2-
import { Inter } from 'next/font/google'
3-
4-
const inter = Inter({ subsets: ['latin'] })
5-
61
export const metadata = {
7-
title: 'Create Next App',
8-
description: 'Generated by create next app',
9-
}
2+
title: "Gist",
3+
};
104

115
export default function RootLayout({ children }) {
126
return (
137
<html lang="en">
14-
<body className={inter.className}>{children}</body>
8+
<body>{children}</body>
159
</html>
16-
)
10+
);
1711
}

0 commit comments

Comments
 (0)