Commit 2a5e42a7 authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

og improvements (#1175)

* og improvements

* update review configs

* review fix

* review fix 2
parent 944773f0
......@@ -2,6 +2,7 @@ import api from './api';
import app from './app';
import chain from './chain';
import * as features from './features';
import meta from './meta';
import services from './services';
import UI from './ui';
......@@ -12,6 +13,7 @@ const config = Object.freeze({
UI,
features,
services,
meta,
});
export default config;
import app from './app';
import { getEnvValue, getExternalAssetFilePath } from './utils';
const defaultImageUrl = app.baseUrl + '/static/og_placeholder.png';
const meta = Object.freeze({
promoteBlockscoutInTitle: getEnvValue(process.env.NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE) || 'true',
og: {
description: getEnvValue(process.env.NEXT_PUBLIC_OG_DESCRIPTION) || '',
imageUrl: getExternalAssetFilePath('NEXT_PUBLIC_OG_IMAGE_URL', process.env.NEXT_PUBLIC_OG_IMAGE_URL) || defaultImageUrl,
},
});
export default meta;
......@@ -41,3 +41,6 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
......@@ -46,3 +46,6 @@ NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_WEB3_WALLETS=['token_pocket','metamask']
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth-goerli.png?raw=true
......@@ -41,3 +41,6 @@ NEXT_PUBLIC_HAS_BEACON_CHAIN=false
# NEXT_PUBLIC_STATS_API_HOST=https://stats-rsk-testnet.k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_WEB3_WALLETS=['token_pocket','metamask']
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/polygon-mainnet.png?raw=true
......@@ -41,3 +41,6 @@ NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x97fa753626b8d44011d0b9f9a947c735f20b6e895efde
NEXT_PUBLIC_HAS_BEACON_CHAIN=false
NEXT_PUBLIC_STATS_API_HOST=https://stats-rsk-testnet.k8s.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/rootstock-testnet.png?raw=true
......@@ -21,6 +21,7 @@ ASSETS_ENVS=(
"NEXT_PUBLIC_NETWORK_LOGO_DARK"
"NEXT_PUBLIC_NETWORK_ICON"
"NEXT_PUBLIC_NETWORK_ICON_DARK"
"NEXT_PUBLIC_OG_IMAGE_URL"
)
# Create the assets directory if it doesn't exist
......
......@@ -325,6 +325,9 @@ const schema = yup
}),
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET: yup.boolean(),
NEXT_PUBLIC_AD_TEXT_PROVIDER: yup.string<AdTextProviders>().oneOf(SUPPORTED_AD_TEXT_PROVIDERS),
NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE: yup.boolean(),
NEXT_PUBLIC_OG_DESCRIPTION: yup.string(),
NEXT_PUBLIC_OG_IMAGE_URL: yup.string().url(),
// 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
......
......@@ -144,3 +144,5 @@ frontend:
_default: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID
NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY:
_default: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_FAVICON_GENERATOR_API_KEY
NEXT_PUBLIC_OG_IMAGE_URL:
_default: https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/base-goerli.png?raw=true
......@@ -13,6 +13,7 @@ The app instance could be customized by passing following variables to NodeJS en
- [Sidebar](ENVS.md#sidebar)
- [Footer](ENVS.md#footer)
- [Favicon](ENVS.md#favicon)
- [Meta](ENVS.md#meta)
- [Views](ENVS.md#views)
- [Block](ENVS.md#block-views)
- [Misc](ENVS.md#misc)
......@@ -145,6 +146,18 @@ By default, the app has generic favicon. You can override this behavior by provi
&nbsp;
### Meta
Settings for meta tags and OG tags
| Variable | Type| Description | Compulsoriness | Default value | Example value |
| --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE | `boolean` | Set to `true` to promote Blockscout in meta and OG titles | - | `true` | `true` |
| NEXT_PUBLIC_OG_DESCRIPTION | `string` | Custom OG description | - | - | `Blockscout is the #1 open-source blockchain explorer available today. 100+ chains and counting rely on Blockscout data availability, APIs, and ecosystem tools to support their networks.` |
| NEXT_PUBLIC_OG_IMAGE_URL | `string` | OG image url. Minimum image size is 200 x 20 pixels (recommended: 1200 x 600); maximum supported file size is 8 MB; 2:1 aspect ratio; supported formats: image/jpeg, image/gif, image/png | - | `static/og_placeholder.png` | `https://placekitten.com/1200/600` |
&nbsp;
### Views
#### Block views
......
......@@ -3,6 +3,11 @@
exports[`generates correct metadata for: dynamic route 1`] = `
{
"description": "View transaction 0x12345 on Blockscout (Blockscout) Explorer",
"opengraph": {
"description": "",
"imageUrl": "",
"title": "Blockscout transaction 0x12345 | Blockscout",
},
"title": "Blockscout transaction 0x12345 | Blockscout",
}
`;
......@@ -10,6 +15,11 @@ exports[`generates correct metadata for: dynamic route 1`] = `
exports[`generates correct metadata for: dynamic route with API data 1`] = `
{
"description": "0x12345, balances and analytics on the Blockscout (Blockscout) Explorer",
"opengraph": {
"description": "",
"imageUrl": "",
"title": "Blockscout USDT token details | Blockscout",
},
"title": "Blockscout USDT token details | Blockscout",
}
`;
......@@ -17,6 +27,11 @@ exports[`generates correct metadata for: dynamic route with API data 1`] = `
exports[`generates correct metadata for: static route 1`] = `
{
"description": "Blockscout is the #1 open-source blockchain explorer available today. 100+ chains and counting rely on Blockscout data availability, APIs, and ecosystem tools to support their networks.",
"opengraph": {
"description": "",
"imageUrl": "http://localhost:3000/static/og_placeholder.png",
"title": "Blockscout blocks | Blockscout",
},
"title": "Blockscout blocks | Blockscout",
}
`;
......@@ -6,6 +6,7 @@ import config from 'configs/app';
import getNetworkTitle from 'lib/networks/getNetworkTitle';
import compileValue from './compileValue';
import getPageOgType from './getPageOgType';
import * as templates from './templates';
export default function generate<R extends Route>(route: R, apiData?: ApiData<R>): Metadata {
......@@ -16,11 +17,19 @@ export default function generate<R extends Route>(route: R, apiData?: ApiData<R>
network_title: getNetworkTitle(),
};
const title = compileValue(templates.title.make(route.pathname), params);
const compiledTitle = compileValue(templates.title.make(route.pathname), params);
const title = compiledTitle ? compiledTitle + (config.meta.promoteBlockscoutInTitle ? ' | Blockscout' : '') : '';
const description = compileValue(templates.description.make(route.pathname), params);
const pageOgType = getPageOgType(route.pathname);
return {
title,
title: title,
description,
opengraph: {
title: title,
description: pageOgType !== 'Regular page' ? config.meta.og.description : '',
imageUrl: pageOgType !== 'Regular page' ? config.meta.og.imageUrl : '',
},
};
}
import type { Route } from 'nextjs-routes';
type OGPageType = 'Homepage' | 'Root page' | 'Regular page';
const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
'/': 'Homepage',
'/txs': 'Root page',
'/tx/[hash]': 'Regular page',
'/blocks': 'Root page',
'/block/[height_or_hash]': 'Regular page',
'/accounts': 'Root page',
'/address/[hash]': 'Regular page',
'/verified-contracts': 'Root page',
'/address/[hash]/contract-verification': 'Regular page',
'/tokens': 'Root page',
'/token/[hash]': 'Regular page',
'/token/[hash]/instance/[id]': 'Regular page',
'/apps': 'Root page',
'/apps/[id]': 'Regular page',
'/stats': 'Root page',
'/api-docs': 'Regular page',
'/graphiql': 'Regular page',
'/search-results': 'Regular page',
'/auth/profile': 'Root page',
'/account/watchlist': 'Regular page',
'/account/api-key': 'Regular page',
'/account/custom-abi': 'Regular page',
'/account/public-tags-request': 'Regular page',
'/account/tag-address': 'Regular page',
'/account/verified-addresses': 'Root page',
'/withdrawals': 'Root page',
'/visualize/sol2uml': 'Regular page',
'/csv-export': 'Regular page',
'/l2-deposits': 'Root page',
'/l2-output-roots': 'Root page',
'/l2-txn-batches': 'Root page',
'/l2-withdrawals': 'Root page',
'/404': 'Regular page',
// service routes, added only to make typescript happy
'/login': 'Regular page',
'/api/media-type': 'Regular page',
'/api/proxy': 'Regular page',
'/api/csrf': 'Regular page',
'/api/healthz': 'Regular page',
'/auth/auth0': 'Regular page',
'/auth/unverified-email': 'Regular page',
};
export default function getPageOgType(pathname: Route['pathname']) {
return OG_TYPE_DICT[pathname];
}
......@@ -48,5 +48,5 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
export function make(pathname: Route['pathname']) {
const template = TEMPLATE_MAP[pathname];
return `%network_name% ${ template } | Blockscout`;
return `%network_name% ${ template }`;
}
......@@ -10,4 +10,9 @@ never;
export interface Metadata {
title: string;
description: string;
opengraph: {
title: string;
description?: string;
imageUrl?: string;
};
}
......@@ -14,7 +14,7 @@ type Props = Route & {
}
const PageNextJs = (props: Props) => {
const { title, description } = metadata.generate(props);
const { title, description, opengraph } = metadata.generate(props);
useGetCsrfToken();
useAdblockDetect();
......@@ -28,6 +28,12 @@ const PageNextJs = (props: Props) => {
<Head>
<title>{ title }</title>
<meta name="description" content={ description }/>
{ /* OG TAGS */ }
<meta property="og:title" content={ opengraph.title }/>
{ opengraph.description && <meta property="og:description" content={ opengraph.description }/> }
<meta property="og:image" content={ opengraph.imageUrl }/>
<meta property="og:type" content="website"/>
</Head>
{ props.children }
</>
......
......@@ -5,7 +5,6 @@ import React from 'react';
import * as serverTiming from 'nextjs/utils/serverTiming';
import config from 'configs/app';
import theme from 'theme';
class MyDocument extends Document {
......@@ -46,19 +45,6 @@ class MyDocument extends Document {
<link rel="icon" sizes="16x16" type="image/png"href="/favicon/favicon-16x16.png"/>
<link rel="apple-touch-icon" href="/favicon/apple-touch-icon-180x180.png"/>
<link rel="mask-icon" href="/favicon/safari-pinned-tab.svg"/>
{ /* OG TAGS */ }
<meta property="og:title" content="Blockscout: A block explorer designed for a decentralized world."/>
<meta
property="og:description"
// eslint-disable-next-line max-len
content="Blockscout is the #1 open-source blockchain explorer available today. 100+ chains and counting rely on Blockscout data availability, APIs, and ecosystem tools to support their networks."
/>
<meta property="og:image" content={ config.app.baseUrl + '/static/og.png' }/>
<meta property="og:site_name" content="Blockscout"/>
<meta property="og:type" content="website"/>
<meta name="twitter:card" content="summary_large_image"/>
<meta property="twitter:image" content={ config.app.baseUrl + '/static/og_twitter.png' }/>
</Head>
<body>
<ColorModeScript initialColorMode={ theme.config.initialColorMode }/>
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment