[website] Add head, links and meta tags (#411)
* add assets * add head, links and meta tags * add url origin * rebase * update head * comment out placeholder og images * add scrollRestoration * fix related posts * rm browserconfig.xml * remove icons * u * u * lint * Update error-page.tsx * rm twitter meta
This commit is contained in:
parent
ceb1f60605
commit
9d2b3e9cea
|
@ -30,6 +30,7 @@ let config = {
|
||||||
experimental: {
|
experimental: {
|
||||||
legacyBrowsers: false,
|
legacyBrowsers: false,
|
||||||
// esmExternals: 'loose',
|
// esmExternals: 'loose',
|
||||||
|
scrollRestoration: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.0 KiB |
|
@ -1,53 +0,0 @@
|
||||||
import Head from 'next/head'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
index?: boolean
|
|
||||||
children?: React.ReactElement
|
|
||||||
imageUrl?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function _Head(props: Props) {
|
|
||||||
const { index = true, children, imageUrl } = props
|
|
||||||
return (
|
|
||||||
<Head>
|
|
||||||
<title>Status</title>
|
|
||||||
<meta name="description" content="Generated by create next app" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
{/* todo: app stores banners/redirects */}
|
|
||||||
{/* todo: eval following meta tags */}
|
|
||||||
<meta property="og:site_name" content="Join Status" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta
|
|
||||||
property="og:description"
|
|
||||||
content="Status — A secure messaging app, crypto wallet, and Web3 browser"
|
|
||||||
/>
|
|
||||||
<meta property="og:title" content="Join [@|#]<name> in Status" />
|
|
||||||
<meta property="og:url" content="<url>" />
|
|
||||||
|
|
||||||
{imageUrl && <meta property="og:image" content={imageUrl} />}
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary" />
|
|
||||||
<meta name="twitter:site" content="@ethstatus" />
|
|
||||||
{/* <meta property="twitter:image" content="<logo>" /> */}
|
|
||||||
<meta property="twitter:image:alt" content="Status logo" />
|
|
||||||
<meta property="status-im:target" content="<displayName>" />
|
|
||||||
<meta property="al:ios:url" content="status-im:/<url>" />
|
|
||||||
<meta property="al:ios:app_store_id" content="1178893006" />
|
|
||||||
<meta property="al:ios:app_name" content="Status — Ethereum. Anywhere" />
|
|
||||||
<meta property="al:android:url" content="status-im:/<url>" />
|
|
||||||
<meta property="al:android:package" content="im.status.ethereum" />
|
|
||||||
<meta
|
|
||||||
property="al:android:app_name"
|
|
||||||
content="Status — Ethereum. Anywhere"
|
|
||||||
/>
|
|
||||||
{/* todo?: except communities; ask product */}
|
|
||||||
{!index && <meta name="robots" content="noindex" />}
|
|
||||||
{/* todo?: entity QR */}
|
|
||||||
{/* todo?: fallback OG */}
|
|
||||||
{children}
|
|
||||||
</Head>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export { _Head as Head }
|
|
|
@ -2,6 +2,7 @@ import Image from 'next/image'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { match, P } from 'ts-pattern'
|
import { match, P } from 'ts-pattern'
|
||||||
|
|
||||||
|
import logoBlogSrc from '../../public/images/logo/blog.svg'
|
||||||
import logoSrc from '../../public/images/logo/default.svg'
|
import logoSrc from '../../public/images/logo/default.svg'
|
||||||
import logoDevSrc from '../../public/images/logo/dev.svg'
|
import logoDevSrc from '../../public/images/logo/dev.svg'
|
||||||
import logoLearnSrc from '../../public/images/logo/learn.svg'
|
import logoLearnSrc from '../../public/images/logo/learn.svg'
|
||||||
|
@ -29,7 +30,7 @@ export const Logo = (props: Props) => {
|
||||||
)
|
)
|
||||||
.with(
|
.with(
|
||||||
P.when(p => p.startsWith('/blog')),
|
P.when(p => p.startsWith('/blog')),
|
||||||
() => <Image src={logoSrc} alt="Status logo" />
|
() => <Image src={logoBlogSrc} alt="Status logo" />
|
||||||
)
|
)
|
||||||
.otherwise(() => (
|
.otherwise(() => (
|
||||||
<Image src={logoSrc} alt="Status logo" />
|
<Image src={logoSrc} alt="Status logo" />
|
||||||
|
|
|
@ -21,9 +21,9 @@ import {
|
||||||
QrCodeIcon,
|
QrCodeIcon,
|
||||||
} from '@status-im/icons'
|
} from '@status-im/icons'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import Head from 'next/head'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import { Head } from '@/components/head'
|
|
||||||
import { ERROR_CODES } from '@/consts/error-codes'
|
import { ERROR_CODES } from '@/consts/error-codes'
|
||||||
import { useURLData } from '@/hooks/use-url-data'
|
import { useURLData } from '@/hooks/use-url-data'
|
||||||
import { getRequestClient } from '@/lib/request-client'
|
import { getRequestClient } from '@/lib/request-client'
|
||||||
|
@ -80,6 +80,12 @@ export type Data =
|
||||||
info: UserInfo
|
info: UserInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ACTION_VERB: Record<Type, string> = {
|
||||||
|
community: 'Join',
|
||||||
|
channel: 'View',
|
||||||
|
profile: 'Open',
|
||||||
|
}
|
||||||
|
|
||||||
const INSTRUCTIONS_HEADING: Record<Type, string> = {
|
const INSTRUCTIONS_HEADING: Record<Type, string> = {
|
||||||
community: 'How to join this community:',
|
community: 'How to join this community:',
|
||||||
channel: 'How to join this channel:',
|
channel: 'How to join this channel:',
|
||||||
|
@ -93,7 +99,7 @@ const JOIN_BUTTON_LABEL: Record<Type, string> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PreviewPage(props: PreviewPageProps) {
|
export function PreviewPage(props: PreviewPageProps) {
|
||||||
const { type, decodedData, encodedData } = props
|
const { type, decodedData, encodedData, index } = props
|
||||||
|
|
||||||
const { asPath } = useRouter()
|
const { asPath } = useRouter()
|
||||||
|
|
||||||
|
@ -216,9 +222,34 @@ export function PreviewPage(props: PreviewPageProps) {
|
||||||
return <ErrorPage errorCode={ERROR_CODES.NOT_FOUND} />
|
return <ErrorPage errorCode={ERROR_CODES.NOT_FOUND} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const urlOrigin = process.env.VERCEL_URL
|
||||||
|
// ? 'https://' + process.env.VERCEL_URL
|
||||||
|
// : ''
|
||||||
|
|
||||||
if ((loading && !data) || !data || !publicKey) {
|
if ((loading && !data) || !data || !publicKey) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Head>
|
||||||
|
<meta property="og:url" content={`https://status.app${asPath}`} />
|
||||||
|
{/* todo: test if server-rendered version with which a (social) card would be
|
||||||
|
generated would not effectively override actual shared link on clicking */}
|
||||||
|
{/* <meta
|
||||||
|
property="og:image"
|
||||||
|
content={`${urlOrigin}/assets/preview/entity.png`}
|
||||||
|
key="og:image"
|
||||||
|
/> */}
|
||||||
|
<meta
|
||||||
|
property="al:ios:url"
|
||||||
|
content={`https://status.app${asPath}`}
|
||||||
|
key="al:ios:url"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="al:android:url"
|
||||||
|
content={`https://status.app${asPath}`}
|
||||||
|
key="al:android:url"
|
||||||
|
/>
|
||||||
|
{!index && <meta name="robots" content="noindex" />}
|
||||||
|
</Head>
|
||||||
<div className="h-full xl:grid xl:grid-cols-[560px,auto]">
|
<div className="h-full xl:grid xl:grid-cols-[560px,auto]">
|
||||||
<div className="pb-10">
|
<div className="pb-10">
|
||||||
<div className="mx-auto px-5 pt-20 xl:px-20">
|
<div className="mx-auto px-5 pt-20 xl:px-20">
|
||||||
|
@ -326,10 +357,33 @@ export function PreviewPage(props: PreviewPageProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head index={props.index} />
|
<Head>
|
||||||
|
<title>
|
||||||
|
{`${ACTION_VERB[type]} ${data.info.displayName} in Status`}
|
||||||
|
</title>
|
||||||
|
|
||||||
|
<meta property="og:url" content={`https://status.app${asPath}`} />
|
||||||
|
<meta
|
||||||
|
property="og:title"
|
||||||
|
content={`${ACTION_VERB[type]} ${data.info.displayName} in Status`}
|
||||||
|
/>
|
||||||
|
{/* <meta
|
||||||
|
property="og:image"
|
||||||
|
content={`${urlOrigin}/assets/preview/entity.png`}
|
||||||
|
key="og:image"
|
||||||
|
/> */}
|
||||||
|
<meta property="og:description" content={data.info.description} />
|
||||||
|
<meta
|
||||||
|
name="apple-itunes-app"
|
||||||
|
content={`app-id=1178893006, app-argument=status-app://${asPath.replace(
|
||||||
|
/\//,
|
||||||
|
''
|
||||||
|
)}`}
|
||||||
|
/>
|
||||||
|
{!index && <meta name="robots" content="noindex" />}
|
||||||
|
</Head>
|
||||||
<>
|
<>
|
||||||
{/* todo: theme; based on user system settings */}
|
{/* todo: theme; based on user system settings */}
|
||||||
{/* todo: (system or both?) install banner */}
|
|
||||||
<div
|
<div
|
||||||
style={!bannerURL ? getGradientStyles(data) : undefined}
|
style={!bannerURL ? getGradientStyles(data) : undefined}
|
||||||
className="relative h-full bg-gradient-to-b from-[var(--gradient-color)] to-[#fff] to-20% xl:grid xl:grid-cols-[560px,auto]"
|
className="relative h-full bg-gradient-to-b from-[var(--gradient-color)] to-[#fff] to-20% xl:grid xl:grid-cols-[560px,auto]"
|
||||||
|
|
|
@ -4,6 +4,9 @@ import '@/styles/nav-nested-links.css'
|
||||||
import { ThemeProvider } from '@status-im/components'
|
import { ThemeProvider } from '@status-im/components'
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||||
import { Inter } from 'next/font/google'
|
import { Inter } from 'next/font/google'
|
||||||
|
import Head from 'next/head'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { match, P } from 'ts-pattern'
|
||||||
|
|
||||||
import type { Page, PageLayout } from 'next'
|
import type { Page, PageLayout } from 'next'
|
||||||
import type { AppProps } from 'next/app'
|
import type { AppProps } from 'next/app'
|
||||||
|
@ -23,11 +26,122 @@ type Props = AppProps & {
|
||||||
export default function App({ Component, pageProps }: Props) {
|
export default function App({ Component, pageProps }: Props) {
|
||||||
const getLayout: PageLayout = Component.getLayout || (page => page)
|
const getLayout: PageLayout = Component.getLayout || (page => page)
|
||||||
|
|
||||||
|
// const urlOrigin = process.env.VERCEL_URL
|
||||||
|
// ? 'https://' + process.env.VERCEL_URL
|
||||||
|
// : ''
|
||||||
|
|
||||||
|
const { pathname, asPath } = useRouter()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Status - Private, Secure Communication</title>
|
||||||
|
|
||||||
|
<meta name="title" content="Status - Private, Secure Communication" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Status brings the power of Ethereum into your pocket by combining a messenger, crypto-wallet, and Web3 browser."
|
||||||
|
/>
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content={`https://status.app${asPath}`} />
|
||||||
|
<meta
|
||||||
|
property="og:title"
|
||||||
|
content="Status - Private, Secure Communication"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Status brings the power of Ethereum into your pocket by combining a messenger, crypto-wallet, and Web3 browser."
|
||||||
|
/>
|
||||||
|
{/* <meta
|
||||||
|
property="og:image"
|
||||||
|
content={`${urlOrigin}/assets/preview/page.png`}
|
||||||
|
key="og:image"
|
||||||
|
/> */}
|
||||||
|
<meta property="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@ethstatus" />
|
||||||
|
<meta name="apple-itunes-app" content="app-id=1178893006" />
|
||||||
|
<meta
|
||||||
|
property="al:ios:url"
|
||||||
|
content={`https://status.app${asPath}`}
|
||||||
|
key="al:ios:url"
|
||||||
|
/>
|
||||||
|
<meta property="al:ios:app_store_id" content="1178893006" />
|
||||||
|
<meta
|
||||||
|
property="al:ios:app_name"
|
||||||
|
content="Status — Ethereum. Anywhere"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="al:android:url"
|
||||||
|
content={`https://status.app${asPath}`}
|
||||||
|
key="al:android:url"
|
||||||
|
/>
|
||||||
|
<meta property="al:android:package" content="im.status.ethereum" />
|
||||||
|
<meta
|
||||||
|
property="al:android:app_name"
|
||||||
|
content="Status — Ethereum. Anywhere"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="article:publisher"
|
||||||
|
content="https://www.facebook.com/ethstatus"
|
||||||
|
/>
|
||||||
|
{match(pathname)
|
||||||
|
.with(
|
||||||
|
P.when(p => p.startsWith('/insights')),
|
||||||
|
() => (
|
||||||
|
<>
|
||||||
|
<link rel="icon" href="/assets/favicon/dev.png" />
|
||||||
|
{/* <link rel="apple-touch-icon" href="/assets/favicon/dev.png" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon-precomposed"
|
||||||
|
href="/assets/favicon/dev.png"
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.with(
|
||||||
|
P.when(p => p.startsWith('/learn')),
|
||||||
|
() => (
|
||||||
|
<>
|
||||||
|
<link rel="icon" href="/assets/favicon/learn.png" />
|
||||||
|
{/* <link rel="apple-touch-icon" href="/assets/favicon/learn.png" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon-precomposed"
|
||||||
|
href="/assets/favicon/learn.png"
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.with(
|
||||||
|
P.when(p => p.startsWith('/blog')),
|
||||||
|
() => (
|
||||||
|
<>
|
||||||
|
<link rel="icon" href="/assets/favicon/blog.png" />
|
||||||
|
{/* <link rel="apple-touch-icon" href="/assets/favicon/blog.png" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon-precomposed"
|
||||||
|
href="/assets/favicon/blog.png"
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.otherwise(() => (
|
||||||
|
<>
|
||||||
|
<link rel="icon" href="/assets/favicon/default.png" />
|
||||||
|
{/* <link rel="apple-touch-icon" href="/assets/favicon/default.png" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon-precomposed"
|
||||||
|
href="/assets/favicon/default.png"
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</Head>
|
||||||
<div id="app" className={inter.variable + ' font-sans'}>
|
<div id="app" className={inter.variable + ' font-sans'}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<ThemeProvider>{getLayout(<Component {...pageProps} />)}</ThemeProvider>
|
<ThemeProvider>
|
||||||
|
{getLayout(<Component {...pageProps} />)}
|
||||||
|
</ThemeProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ export default class Document extends NextDocument {
|
||||||
id="tamagui"
|
id="tamagui"
|
||||||
dangerouslySetInnerHTML={{ __html: Tamagui.getCSS() }}
|
dangerouslySetInnerHTML={{ __html: Tamagui.getCSS() }}
|
||||||
/>
|
/>
|
||||||
<meta name="theme-color" content="#09101C" />
|
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<Main />
|
<Main />
|
||||||
|
|
|
@ -223,7 +223,7 @@ const BlogDetailPage: Page<Props> = ({ post, relatedPosts }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{relatedPosts.length && (
|
{relatedPosts.length > 0 && (
|
||||||
<div className="border-t border-neutral-10 bg-neutral-5 px-5 pb-[64px] pt-12 lg:px-10">
|
<div className="border-t border-neutral-10 bg-neutral-5 px-5 pb-[64px] pt-12 lg:px-10">
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<Text size={27} weight="semibold">
|
<Text size={27} weight="semibold">
|
||||||
|
|
Loading…
Reference in New Issue