-
+
${question}
-
${probability}%
+
${probability}
chance
diff --git a/og-image/package.json b/og-image/package.json
index 6f7bf48a..563a7d45 100644
--- a/og-image/package.json
+++ b/og-image/package.json
@@ -2,7 +2,7 @@
"private": true,
"scripts": {
"build": "tsc -p api/tsconfig.json && tsc -p web/tsconfig.json",
- "start": "cd .. && vercel dev"
+ "start": "cd .. && vercel dev --listen 3001"
},
"dependencies": {
"chrome-aws-lambda": "7.0.0",
diff --git a/web/components/SEO.tsx b/web/components/SEO.tsx
index e8d6547f..697f4d33 100644
--- a/web/components/SEO.tsx
+++ b/web/components/SEO.tsx
@@ -1,12 +1,35 @@
import Head from 'next/head'
+export type OgCardProps = {
+ question: string
+ probability: string
+ metadata: string
+ creatorName: string
+ creatorUsername: string
+ // TODO: Store creator avatar url in each contract, then enable this
+ // creatorAvatarUrl: string
+}
+
+function buildCardUrl(props: OgCardProps) {
+ // URL encode each of the props, then add them as query params
+ return (
+ `https://manifold-og-image.vercel.app/m.png` +
+ `?question=${encodeURIComponent(props.question)}` +
+ `&probability=${encodeURIComponent(props.probability)}` +
+ `&metadata=${encodeURIComponent(props.metadata)}` +
+ `&creatorName=${encodeURIComponent(props.creatorName)}` +
+ `&creatorUsername=${encodeURIComponent(props.creatorUsername)}`
+ )
+}
+
export function SEO(props: {
title: string
description: string
url?: string
children?: any[]
+ ogCardProps?: OgCardProps
}) {
- const { title, description, url, children } = props
+ const { title, description, url, children, ogCardProps } = props
return (
@@ -34,6 +57,22 @@ export function SEO(props: {
/>
)}
+ {ogCardProps && (
+ <>
+
+
+
+ >
+ )}
+
{children}
)
diff --git a/web/components/contract-card.tsx b/web/components/contract-card.tsx
index c4c8c7fa..046e8914 100644
--- a/web/components/contract-card.tsx
+++ b/web/components/contract-card.tsx
@@ -165,3 +165,24 @@ export function ContractDetails(props: { contract: Contract }) {
)
}
+
+// String version of the above, to send to the OpenGraph image generator
+export function contractTextDetails(contract: Contract) {
+ const { question, description, closeTime } = contract
+ const { truePool, createdDate, resolvedDate } = compute(contract)
+
+ const tags = parseTags(`${question} ${description}`).map((tag) => `#${tag}`)
+
+ return (
+ `${contract.creatorUsername} • ${
+ resolvedDate ? `${createdDate} - ${resolvedDate}` : createdDate
+ }` +
+ (closeTime
+ ? ` • ${closeTime > Date.now() ? 'Closes' : 'Closed'} ${dayjs(
+ closeTime
+ ).format('MMM D, h:mma')}`
+ : '') +
+ ` • ${formatMoney(truePool)} pool` +
+ (tags.length > 0 ? ` • ${tags.join(' ')}` : '')
+ )
+}
diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx
index f467578a..7aabede2 100644
--- a/web/pages/[username]/[contractSlug].tsx
+++ b/web/pages/[username]/[contractSlug].tsx
@@ -18,6 +18,7 @@ import {
} from '../../lib/firebase/contracts'
import { SEO } from '../../components/SEO'
import { Page } from '../../components/page'
+import { contractTextDetails } from '../../components/contract-card'
export async function getStaticProps(props: { params: any }) {
const { username, contractSlug } = props.params
@@ -63,12 +64,21 @@ export default function ContractPage(props: {
? `Resolved ${resolution}. ${contract.description}`
: `${probPercent} chance. ${contract.description}`
+ const ogCardProps = {
+ question,
+ probability: probPercent,
+ metadata: contractTextDetails(contract),
+ creatorName: contract.creatorName,
+ creatorUsername: contract.creatorUsername,
+ }
+
return (
diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx
index f2f2619d..cfa65f04 100644
--- a/web/pages/_app.tsx
+++ b/web/pages/_app.tsx
@@ -26,15 +26,17 @@ function MyApp({ Component, pageProps }: AppProps) {
key="description2"
/>
-
+