-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d059298
commit 4aecadb
Showing
183 changed files
with
13,445 additions
and
12,367 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,28 @@ | ||
# Rename to .env | ||
# DON'T FORGET TO RENAME TO .env OR .env.local BEFORE PUSHING TO GIT | ||
|
||
### DEVELOPMENT ONLY VARIABLES | ||
# These variables need to be set | ||
# for local development only | ||
# These variables need to be set for local development only | ||
|
||
# Mandatory next-auth URL for localhost | ||
NEXTAUTH_URL=http://app.localhost:3000 | ||
|
||
### PRODUCTION & DEVELOPMENT VARIABLES | ||
# These variables need to be set | ||
# for local development and when deployed on Vercel | ||
# These variables need to be set for local development and when deployed on Vercel | ||
|
||
# MySQL database URL for Prisma | ||
DATABASE_URL=mysql://[email protected]:3309/platforms | ||
# Change this to your own domain | ||
NEXT_PUBLIC_ROOT_DOMAIN=vercel.pub | ||
|
||
# GitHub OAuth https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app | ||
# PostgreSQL database URL – get one here: https://vercel.com/docs/storage/vercel-postgres/quickstart | ||
POSTGRES_PRISMA_URL= | ||
|
||
# Vercel Blob Storage for image uploads – get one here: https://vercel.com/docs/storage/blob/quickstart | ||
BLOB_READ_WRITE_TOKEN= | ||
|
||
# GitHub OAuth for auth & login – get one here: https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app | ||
GITHUB_ID= | ||
GITHUB_SECRET= | ||
|
||
# Twitter Auth Bearer token (for static tweets) | ||
TWITTER_AUTH_TOKEN= | ||
|
||
# Secret key (generate one here: https://generate-secret.vercel.app/32) | ||
# Secret key for NextAuth (generate one here: https://generate-secret.vercel.app/32) | ||
NEXTAUTH_SECRET= | ||
|
||
# https://vercel.com/account/tokens | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,5 +3,6 @@ | |
**.env | ||
**.DS_Store | ||
**.vercel | ||
.vscode | ||
**.git | ||
.vercel |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* eslint-disable @next/next/no-img-element */ | ||
|
||
import { truncate } from "@/lib/utils"; | ||
import { ImageResponse } from "next/server"; | ||
import { sql } from "@vercel/postgres"; | ||
|
||
export const runtime = "edge"; | ||
|
||
export default async function PostOG({ | ||
params, | ||
}: { | ||
params: { domain: string; slug: string }; | ||
}) { | ||
const { domain, slug } = params; | ||
|
||
const subdomain = domain.endsWith(`.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`) | ||
? domain.replace(`.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`, "") | ||
: null; | ||
|
||
const response = await sql` | ||
SELECT post.title, post.description, post.image, "user".name as "authorName", "user".image as "authorImage" | ||
FROM "Post" AS post | ||
INNER JOIN "Site" AS site ON post."siteId" = site.id | ||
INNER JOIN "User" AS "user" ON site."userId" = "user".id | ||
WHERE | ||
( | ||
site.subdomain = ${subdomain} | ||
OR site."customDomain" = ${domain} | ||
) | ||
AND post.slug = ${slug} | ||
LIMIT 1; | ||
`; | ||
|
||
const data = response.rows[0]; | ||
|
||
if (!data) { | ||
return new Response("Not found", { status: 404 }); | ||
} | ||
|
||
const clashData = await fetch( | ||
new URL("@/styles/CalSans-SemiBold.otf", import.meta.url) | ||
).then((res) => res.arrayBuffer()); | ||
|
||
return new ImageResponse( | ||
( | ||
<div tw="flex flex-col items-center w-full h-full bg-white"> | ||
<div tw="flex flex-col items-center justify-center mt-8"> | ||
<h1 tw="text-6xl font-bold text-gray-900 leading-none tracking-tight"> | ||
{data.title} | ||
</h1> | ||
<p tw="mt-4 text-xl text-gray-600 max-w-xl text-center"> | ||
{truncate(data.description, 120)} | ||
</p> | ||
<div tw="flex items-center justify-center"> | ||
<img | ||
tw="w-12 h-12 rounded-full mr-4" | ||
src={data.authorImage} | ||
alt={data.authorName} | ||
/> | ||
<p tw="text-xl font-medium text-gray-900">by {data.authorName}</p> | ||
</div> | ||
<img | ||
tw="mt-4 w-5/6 rounded-2xl border border-gray-200 shadow-md" | ||
src={data.image} | ||
alt={data.title} | ||
/> | ||
</div> | ||
</div> | ||
), | ||
{ | ||
width: 1200, | ||
height: 600, | ||
fonts: [ | ||
{ | ||
name: "Clash", | ||
data: clashData, | ||
}, | ||
], | ||
emoji: "blobmoji", | ||
} | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import { notFound } from "next/navigation"; | ||
import { getPostData } from "@/lib/fetchers"; | ||
import BlogCard from "@/components/blog-card"; | ||
import BlurImage from "@/components/blur-image"; | ||
import MDX from "@/components/mdx"; | ||
import { placeholderBlurhash, toDateString } from "@/lib/utils"; | ||
|
||
export async function generateMetadata({ | ||
params, | ||
}: { | ||
params: { domain: string; slug: string }; | ||
}) { | ||
const { domain, slug } = params; | ||
const data = await getPostData(domain, slug); | ||
if (!data) { | ||
notFound(); | ||
} | ||
const { title, description } = data; | ||
|
||
return { | ||
title, | ||
description, | ||
openGraph: { | ||
title, | ||
description, | ||
}, | ||
twitter: { | ||
card: "summary_large_image", | ||
title, | ||
description, | ||
creator: "@vercel", | ||
}, | ||
}; | ||
} | ||
|
||
export default async function SitePostPage({ | ||
params, | ||
}: { | ||
params: { domain: string; slug: string }; | ||
}) { | ||
const { domain, slug } = params; | ||
const data = await getPostData(domain, slug); | ||
|
||
if (!data) { | ||
notFound(); | ||
} | ||
|
||
return ( | ||
<> | ||
<div className="flex flex-col justify-center items-center"> | ||
<div className="text-center w-full md:w-7/12 m-auto"> | ||
<p className="text-sm md:text-base font-light text-gray-500 w-10/12 m-auto my-5"> | ||
{toDateString(data.createdAt)} | ||
</p> | ||
<h1 className="font-bold text-3xl font-title md:text-6xl mb-10 text-gray-800"> | ||
{data.title} | ||
</h1> | ||
<p className="text-md md:text-lg text-gray-600 w-10/12 m-auto"> | ||
{data.description} | ||
</p> | ||
</div> | ||
<a | ||
// if you are using Github OAuth, you can get rid of the Twitter option | ||
href={ | ||
data.site?.user?.username | ||
? `https://twitter.com/${data.site.user.username}` | ||
: `https://github.com/${data.site?.user?.gh_username}` | ||
} | ||
rel="noreferrer" | ||
target="_blank" | ||
> | ||
<div className="my-8"> | ||
<div className="relative w-8 h-8 md:w-12 md:h-12 rounded-full overflow-hidden inline-block align-middle"> | ||
{data.site?.user?.image ? ( | ||
<BlurImage | ||
alt={data.site?.user?.name ?? "User Avatar"} | ||
height={80} | ||
src={data.site.user.image} | ||
width={80} | ||
/> | ||
) : ( | ||
<div className="absolute flex items-center justify-center w-full h-full bg-gray-100 text-gray-500 text-4xl select-none"> | ||
? | ||
</div> | ||
)} | ||
</div> | ||
<div className="inline-block text-md md:text-lg align-middle ml-3"> | ||
by <span className="font-semibold">{data.site?.user?.name}</span> | ||
</div> | ||
</div> | ||
</a> | ||
</div> | ||
<div className="relative h-80 md:h-150 w-full max-w-screen-lg lg:w-2/3 md:w-5/6 m-auto mb-10 md:mb-20 md:rounded-2xl overflow-hidden"> | ||
<BlurImage | ||
alt={data.title ?? "Post image"} | ||
width={1200} | ||
height={630} | ||
className="w-full h-full object-cover" | ||
placeholder="blur" | ||
blurDataURL={data.imageBlurhash ?? placeholderBlurhash} | ||
src={data.image ?? "/placeholder.png"} | ||
/> | ||
</div> | ||
|
||
<MDX source={data.mdxSource} /> | ||
|
||
{data.adjacentPosts.length > 0 && ( | ||
<div className="relative mt-10 sm:mt-20 mb-20"> | ||
<div | ||
className="absolute inset-0 flex items-center" | ||
aria-hidden="true" | ||
> | ||
<div className="w-full border-t border-gray-300" /> | ||
</div> | ||
<div className="relative flex justify-center"> | ||
<span className="px-2 bg-white text-sm text-gray-500"> | ||
Continue Reading | ||
</span> | ||
</div> | ||
</div> | ||
)} | ||
{data.adjacentPosts && ( | ||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-x-4 gap-y-8 mx-5 lg:mx-12 2xl:mx-auto mb-20 max-w-screen-xl"> | ||
{data.adjacentPosts.map((data, index) => ( | ||
<BlogCard key={index} data={data} /> | ||
))} | ||
</div> | ||
)} | ||
</> | ||
); | ||
} |
Oops, something went wrong.