diff --git a/pages/outfits/[id].js b/pages/outfits/[id].js
new file mode 100644
index 0000000..82dbfa8
--- /dev/null
+++ b/pages/outfits/[id].js
@@ -0,0 +1,85 @@
+// This is a copy of our higher-level catch-all page, but with some
+// extra SSR for outfit sharing meta tags!
+
+import Head from "next/head";
+import connectToDb from "../../src/server/db";
+import { normalizeRow } from "../../src/server/util";
+
+// import NextIndexWrapper from '../../src'
+
+// next/dynamic is used to prevent breaking incompatibilities
+// with SSR from window.SOME_VAR usage, if this is not used
+// next/dynamic can be removed to take advantage of SSR/prerendering
+import dynamic from "next/dynamic";
+
+// try changing "ssr" to true below to test for incompatibilities, if
+// no errors occur the above static import can be used instead and the
+// below removed
+const NextIndexWrapper = dynamic(() => import("../../src"), { ssr: false });
+
+export default function Page({ outfit, ...props }) {
+ return (
+ <>
+
+ {outfit.name || "Untitled outfit"} | Dress to Impress
+
+
+
+ >
+ );
+}
+
+function OutfitMetaTags({ outfit }) {
+ const updatedAtTimestamp = Math.floor(
+ new Date(outfit.updatedAt).getTime() / 1000
+ );
+ const outfitUrl =
+ `https://impress-2020.openneo.net/outfits` +
+ `/${encodeURIComponent(outfit.id)}`;
+ const imageUrl =
+ `https://impress-outfit-images.openneo.net/outfits` +
+ `/${encodeURIComponent(outfit.id)}` +
+ `/v/${encodeURIComponent(updatedAtTimestamp)}` +
+ `/600.png`;
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
+
+export async function getServerSideProps({ params }) {
+ const outfit = await loadOutfitData(params.id);
+ if (outfit == null) {
+ return { notFound: true };
+ }
+
+ return {
+ props: {
+ outfit: {
+ id: outfit.id,
+ name: outfit.name,
+ updatedAt: outfit.updatedAt.toISOString(),
+ },
+ },
+ };
+}
+
+async function loadOutfitData(id) {
+ const db = await connectToDb();
+ const [rows] = await db.query(`SELECT * FROM outfits WHERE id = ?;`, [id]);
+ if (rows.length === 0) {
+ return null;
+ }
+
+ return normalizeRow(rows[0]);
+}
diff --git a/pages/outfits/new.js b/pages/outfits/new.js
new file mode 100644
index 0000000..ca1c079
--- /dev/null
+++ b/pages/outfits/new.js
@@ -0,0 +1,19 @@
+// This is just a copy of our higher-level catch-all page.
+// That way, /outfits/new renders as normal, but /outfits/:slug
+// does the SSR thing!
+
+// import NextIndexWrapper from '../../src'
+
+// next/dynamic is used to prevent breaking incompatibilities
+// with SSR from window.SOME_VAR usage, if this is not used
+// next/dynamic can be removed to take advantage of SSR/prerendering
+import dynamic from "next/dynamic";
+
+// try changing "ssr" to true below to test for incompatibilities, if
+// no errors occur the above static import can be used instead and the
+// below removed
+const NextIndexWrapper = dynamic(() => import("../../src"), { ssr: false });
+
+export default function Page(props) {
+ return ;
+}
diff --git a/vercel.json b/vercel.json
index 8f26f76..969803f 100644
--- a/vercel.json
+++ b/vercel.json
@@ -1,7 +1,5 @@
{
"routes": [
- { "src": "/outfits/new(\\?|$)", "dest": "/index.html" },
- { "src": "/outfits/(?[^/]+)", "dest": "/api/outfitPageSSR.js?id=$id" },
{
"handle": "filesystem"
},