Skip to content

Commit

Permalink
OG image: automatically generate image on container start (#2496)
Browse files Browse the repository at this point in the history
* make script to generate OG image at container start

* add prod service URL

* remove og_image.png

* update path to file

* [skip ci] remove app url from payload
  • Loading branch information
tom2drum authored Jan 14, 2025
1 parent 78d5f02 commit 2b47bbe
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/public/icons/sprite.svg
/public/icons/sprite.*.svg
/public/icons/README.md
/public/static/og_image.png
/public/sitemap.xml
/public/robots.txt
/analyze
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ COPY --chmod=755 ./deploy/scripts/validate_envs.sh .
COPY --chmod=755 ./deploy/scripts/make_envs_script.sh .
## Assets downloader
COPY --chmod=755 ./deploy/scripts/download_assets.sh .
## OG image generator
COPY ./deploy/scripts/og_image_generator.js .
## Favicon generator
COPY --chmod=755 ./deploy/scripts/favicon_generator.sh .
COPY --from=builder /app/deploy/tools/favicon-generator ./deploy/tools/favicon-generator
Expand Down
2 changes: 1 addition & 1 deletion configs/app/meta.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import app from './app';
import { getEnvValue, getExternalAssetFilePath } from './utils';

const defaultImageUrl = '/static/og_placeholder.png';
const defaultImageUrl = '/static/og_image.png';

const meta = Object.freeze({
promoteBlockscoutInTitle: getEnvValue('NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE') === 'false' ? false : true,
Expand Down
18 changes: 13 additions & 5 deletions configs/envs/.env.zkevm
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,31 @@ NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "632019", "width": "728", "height": "90" }
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ "id": "632018", "width": "320", "height": "100" }
NEXT_PUBLIC_AD_BANNER_PROVIDER=adbutler
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=zkevm.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/zkevm.json
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0x25fcb396fc8652dcd0040f677a1dcc6fecff390ecafc815894379a3f254f1aa9
NEXT_PUBLIC_HAS_USER_OPS=true
NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=linear-gradient(122deg, rgba(162, 41, 197, 1) 0%, rgba(123, 63, 228, 1) 100%)
NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR=rgba(255, 255, 255, 1)
NEXT_PUBLIC_MARKETPLACE_ENABLED=false
NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(122deg, rgba(162, 41, 197, 1) 0%, rgba(123, 63, 228, 1) 100%)'],'text_color':['rgba(255, 255, 255, 1)']}
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://blockscout-polygon.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_ENABLED=true
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_METASUITES_ENABLED=true
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps']
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=MATIC
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=MATIC
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=ETH
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'GeckoTerminal','logo':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/explorer-logos/geckoterminal.png','baseUrl':'https://www.geckoterminal.com/','paths':{'token':'/polygon-zkevm/pools'}}]
NEXT_PUBLIC_NETWORK_ICON=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/polygon-short.svg
NEXT_PUBLIC_NETWORK_ID=1101
Expand Down
3 changes: 3 additions & 0 deletions deploy/scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export_envs_from_preset() {
# If there is a preset, load the environment variables from the its file
export_envs_from_preset

# Generate OG image
node --no-warnings ./og_image_generator.js

# Download external assets
./download_assets.sh ./public/assets/configs

Expand Down
61 changes: 61 additions & 0 deletions deploy/scripts/og_image_generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable no-console */
import fs from 'fs';
import path from 'path';

console.log('🎨 Generating OG image...');

const targetFile = path.resolve(process.cwd(), 'public/static/og_image.png');

function copyPlaceholderImage() {
const sourceFile = path.resolve(process.cwd(), 'public/static/og_placeholder.png');
fs.copyFileSync(sourceFile, targetFile);
}

if (process.env.NEXT_PUBLIC_OG_IMAGE_URL) {
console.log('⏩ NEXT_PUBLIC_OG_IMAGE_URL is set. Skipping OG image generation...');
} else if (!process.env.NEXT_PUBLIC_NETWORK_NAME) {
console.log('⏩ NEXT_PUBLIC_NETWORK_NAME is not set. Copying placeholder image...');
copyPlaceholderImage();
} else if (!process.env.NEXT_PUBLIC_NETWORK_LOGO && !process.env.NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG) {
console.log('⏩ Neither NEXT_PUBLIC_NETWORK_LOGO nor NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG is set. Copying placeholder image...');
copyPlaceholderImage();
} else {
try {
const bannerConfig = JSON.parse(process.env.NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG?.replaceAll('\'', '"') || '{}');
const data = {
title: `${ process.env.NEXT_PUBLIC_NETWORK_NAME } explorer`,
logo_url: process.env.NEXT_PUBLIC_NETWORK_LOGO_DARK ?? process.env.NEXT_PUBLIC_NETWORK_LOGO,
background: bannerConfig.background?.[0],
title_color: bannerConfig.text_color?.[0],
invert_logo: !process.env.NEXT_PUBLIC_NETWORK_LOGO_DARK,
};

console.log('⏳ Making request to OG image generator service...');

const response = await fetch('https://bigs.services.blockscout.com/generate/og', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});

if (response.ok) {
console.log('⬇️ Downloading the image...');
const buffer = await response.arrayBuffer();
const imageBuffer = Buffer.from(buffer);
fs.writeFileSync(targetFile, imageBuffer);
} else {
const payload = response.headers.get('Content-type')?.includes('application/json') ? await response.json() : await response.text();
console.error('🛑 Failed to generate OG image. Response:', payload);
console.log('Copying placeholder image...');
copyPlaceholderImage();
}
} catch (error) {
console.error('🛑 Failed to generate OG image. Error:', error?.message);
console.log('Copying placeholder image...');
copyPlaceholderImage();
}
}

console.log('✅ Done.');
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ export default tseslint.config(
'pages/**',
'nextjs/**',
'playwright/**',
'deploy/scripts/**',
'deploy/tools/**',
'middleware.ts',
'instrumentation*.ts',
Expand Down
2 changes: 1 addition & 1 deletion lib/metadata/__snapshots__/generate.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ exports[`generates correct metadata for: static route 1`] = `
"description": "Open-source block explorer by Blockscout. Search transactions, verify smart contracts, analyze addresses, and track network activity. Complete blockchain data and APIs for the Blockscout (Blockscout) Explorer network.",
"opengraph": {
"description": "",
"imageUrl": "http://localhost:3000/static/og_placeholder.png",
"imageUrl": "http://localhost:3000/static/og_image.png",
"title": "Blockscout transactions - Blockscout explorer | Blockscout",
},
"title": "Blockscout transactions - Blockscout explorer | Blockscout",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"test:jest": "jest",
"test:jest:watch": "jest --watch",
"favicon:generate:dev": "./tools/scripts/favicon-generator.dev.sh",
"og-image:generate:dev": "./tools/scripts/og-image-generator.dev.sh",
"sitemap:generate:dev": "./tools/scripts/sitemap-generator.dev.sh",
"monitoring:prometheus:local": "docker run --name blockscout_prometheus -d -p 127.0.0.1:9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus",
"monitoring:grafana:local": "docker run -d -p 4000:3000 --name=blockscout_grafana --user $(id -u) --volume $(pwd)/grafana:/var/lib/grafana grafana/grafana-enterprise"
Expand Down
Binary file removed public/static/og_twitter.png
Binary file not shown.
9 changes: 9 additions & 0 deletions tools/scripts/og-image-generator.dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

# use this script for testing the og image generator

config_file="./configs/envs/.env.zkevm"

dotenv \
-e $config_file \
-- bash -c 'node ./deploy/scripts/og_image_generator.js'

0 comments on commit 2b47bbe

Please sign in to comment.