-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nextjs // Micro Service Social Previews #198
Changes from 18 commits
3675458
0fb44f8
8c6e0cf
4510532
7ed9a3d
efe8aca
e865642
8e523b2
e3f2b5f
d0cecbd
2d9def1
1823fc4
6caa7cc
c9a5d08
afc33da
240d85a
be98d4c
c133956
0258007
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/basic-features/typescript for more information. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = {}; | ||
|
||
export default nextConfig; |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
'use client'; | ||
import React from 'react'; | ||
import * as Sentry from '@sentry/react'; | ||
import { FeatureFeed } from '@apollosproject/web-shared/embeds'; | ||
import { AppProvider } from '@apollosproject/web-shared/providers'; | ||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'; | ||
import { | ||
AppProvider, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re-importing these avoids potential "different version of |
||
createBrowserRouter, | ||
RouterProvider, | ||
} from '@apollosproject/web-shared/providers'; | ||
|
||
import { Button, Box, BodyText } from '@apollosproject/web-shared/ui-kit'; | ||
import { Logo } from '@apollosproject/web-shared/components'; | ||
|
@@ -11,6 +15,7 @@ import Styled from './App.styles'; | |
|
||
import ErrorPage from './error-page'; | ||
import { parseSlugToIdAndType } from '@apollosproject/web-shared/utils'; | ||
import { getChurchSlug } from './utils'; | ||
|
||
Sentry.init({ | ||
dsn: process.env.REACT_APP_SENTRY_DSN, | ||
|
@@ -21,54 +26,55 @@ Sentry.init({ | |
|
||
function ChurchLogo(props) { | ||
const { currentChurch } = useCurrentChurch(); | ||
const favicon = document.getElementById('favicon'); | ||
if (currentChurch?.logo) { | ||
favicon.href = currentChurch.logo; | ||
|
||
//Can't set favicon in SSR | ||
if (typeof document !== 'undefined') { | ||
const favicon = document.querySelector('link[rel="icon"]'); | ||
if (currentChurch?.logo) { | ||
favicon.href = currentChurch.logo; | ||
} | ||
} | ||
|
||
return <Logo source={currentChurch?.logo} {...props} />; | ||
} | ||
|
||
function App(props) { | ||
let subdomain = | ||
process.env.NODE_ENV === 'production' | ||
? window.location.hostname.split('.').slice(0, -2).join('.') | ||
: window.location.hostname.split('.').slice(0, -1).join('.'); | ||
|
||
if (process.env.NODE_ENV !== 'production' && !subdomain) { | ||
subdomain = 'apollos-demo'; | ||
} | ||
const churchSlug = subdomain.replace(/-/g, '_'); | ||
const searchParams = new URLSearchParams(window.location.search); | ||
const _root = searchParams.get('root'); | ||
function App({ searchParams, url }) { | ||
const churchSlug = getChurchSlug(url); | ||
const _root = searchParams?.root; | ||
|
||
const { type, randomId } = parseSlugToIdAndType(_root) ?? {}; | ||
|
||
const router = createBrowserRouter([ | ||
const ssr = typeof document === 'undefined'; | ||
|
||
const mainRoute = ( | ||
<Styled.FeedWrapper> | ||
<FeatureFeed featureFeed={`${type}:${randomId}`} church={churchSlug} /> | ||
</Styled.FeedWrapper> | ||
); | ||
|
||
const routerConfig = [ | ||
{ | ||
path: '/', | ||
element: ( | ||
<Styled.FeedWrapper> | ||
<FeatureFeed featureFeed={`${type}:${randomId}`} church={churchSlug} /> | ||
</Styled.FeedWrapper> | ||
), | ||
element: mainRoute, | ||
errorElement: <ErrorPage />, | ||
}, | ||
]); | ||
]; | ||
|
||
const router = ssr ? null : createBrowserRouter(routerConfig); | ||
|
||
// Widgets require a church slug to get the correct data | ||
if (churchSlug) { | ||
return ( | ||
<AppProvider church={churchSlug} modal="true"> | ||
<ChurchLogo display="flex" alignItems="center" justifyContent="center" marginTop="40px" /> | ||
<RouterProvider router={router} /> | ||
{/** When using SSR, avoid the router. it crashes */} | ||
{ssr ? mainRoute : <RouterProvider router={router} />} | ||
</AppProvider> | ||
); | ||
} | ||
|
||
// eslint-disable-next-line no-console | ||
console.log( | ||
`⚠️ Feature Feed could not render feed of id "FeatureFeed:5aae43e6-3526-4cd2-8dfe-771d2ce8a333"` | ||
); | ||
console.log(`⚠️ Feature Feed could not render feed of id ${searchParams?.root}`); | ||
|
||
return ( | ||
<AppProvider> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
import { withTheme } from 'styled-components'; | ||
import styled, { css } from 'styled-components'; | ||
import { themeGet } from '@styled-system/theme-get'; | ||
import { H1, TypeStyles } from '@apollosproject/web-shared/ui-kit'; | ||
import { H1, TypeStyles, withTheme, styled } from '@apollosproject/web-shared/ui-kit'; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was seeing issues because |
||
import { system } from '@apollosproject/web-shared/ui-kit/_lib/system'; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import React from 'react'; | ||
import dynamic from 'next/dynamic'; | ||
|
||
const App = dynamic(() => import('../../App'), { ssr: true }); | ||
|
||
export function ClientOnly(props) { | ||
return <App {...props} />; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import '../../index.css'; | ||
import { ClientOnly } from './client'; | ||
import { headers } from 'next/headers'; | ||
import { getChurchSlug } from '../../utils/index'; | ||
import parseSlugToIdAndType from '@apollosproject/web-shared/utils/parseSlugToIdAndType'; | ||
import Head from 'next/head'; | ||
|
||
export const dynamic = 'force-dynamic'; | ||
|
||
export async function generateMetadata({ params, searchParams }, parent) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the magic sauce for fixing meta tags. |
||
const id = searchParams?.id; | ||
|
||
if (!id) return parent; | ||
|
||
const route = headers().get('referer'); | ||
|
||
const churchSlug = getChurchSlug(route); | ||
|
||
const { type, randomId } = parseSlugToIdAndType(id) ?? []; | ||
|
||
// fetch data | ||
const response = await fetch('https://cdn.apollos.app/', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A little bummed that we couldn't use apollo query here, but overall I'm not too bothered 🤷 |
||
headers: { | ||
'content-type': 'application/json', | ||
'x-church': churchSlug, | ||
}, | ||
body: JSON.stringify({ | ||
query: | ||
'query getItemMetadata($itemId:ID!){\n node(id:$itemId){\n ... on ContentItem {\n coverImage {\n sources {uri(refresh:true) }\n }\n title\n summary\n }\n }\n}', | ||
variables: { itemId: `${type}:${randomId}` }, | ||
operationName: 'getItemMetadata', | ||
}), | ||
method: 'POST', | ||
}).then((res) => res.json()); | ||
|
||
const title = response?.data?.node?.title; | ||
const description = response?.data?.node?.summary; | ||
const image = response?.data?.node?.coverImage?.sources[0]?.uri; | ||
|
||
return { | ||
title: title, | ||
openGraph: { | ||
title: title, | ||
description: description, | ||
images: [image], | ||
}, | ||
twitter: { | ||
card: 'summary_large_image', | ||
title: title, | ||
description, | ||
images: [image], // Must be an absolute URL | ||
}, | ||
}; | ||
} | ||
|
||
export default function Page(props) { | ||
const headersList = headers(); | ||
return ( | ||
<> | ||
<Head> | ||
<link rel="icon" type="image/x-icon" href="../../file.svg" /> | ||
</Head> | ||
<ClientOnly {...props} url={headersList.get('referer')} /> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { Metadata } from 'next'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'Apollos Embeds', | ||
description: 'Apollos Web Embeds', | ||
}; | ||
|
||
export default function RootLayout({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<html lang="en"> | ||
<head></head> | ||
|
||
<body> | ||
<div id="root">{children}</div> | ||
</body> | ||
</html> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved these deps to where they belong - the package that uses them.