Skip to content

Commit

Permalink
dynamic map location merchant page og images
Browse files Browse the repository at this point in the history
  • Loading branch information
secondl1ght committed May 23, 2024
1 parent 92c5cef commit cf15051
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 17 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ LNBITS_WALLET_ID=
OPENCAGE_API_KEY=
SERVER_CRYPTO_KEY=
SERVER_INIT_VECTOR=
STADIA_API_KEY=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ node_modules
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.netlify
4 changes: 4 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
[build]
command = "yarn build"
publish = "build"

[images]
remote_images = ["https://static.btcmap.org/images/communities/.*", "https://www.openstreetmap.org/.*", "https://avatars.githubusercontent.com/.*" ]
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"format": "prettier --plugin=prettier-plugin-svelte --plugin=prettier-plugin-tailwindcss --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.2.0",
"@resvg/resvg-js": "^2.6.2",
"@sveltejs/adapter-netlify": "^4.2.0",
"@sveltejs/kit": "^2.5.8",
"@sveltejs/vite-plugin-svelte": "^3.1.0",
"@types/d3-geo": "^3.1.0",
Expand All @@ -33,6 +34,8 @@
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.2.3",
"prettier-plugin-tailwindcss": "^0.5.14",
"satori": "^0.10.13",
"satori-html": "^0.3.2",
"svelte": "^4.2.17",
"svelte-check": "^3.7.1",
"svelte-preprocess": "^5.1.4",
Expand Down
12 changes: 12 additions & 0 deletions src/components/MerchantOG.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
export let lat: string;
export let lon: string;
export let STADIA_API_KEY: string;
</script>

<img
src="https://tiles.stadiamaps.com/static_cacheable/osm_bright.png?size=600x315@2x&markers={lat},{lon},custom:https://btcmap.org/icons/og-marker.png,,,,-16,-43&api_key={STADIA_API_KEY}"
alt="merchant location"
width="1200"
height="630"
/>
1 change: 1 addition & 0 deletions src/lib/comp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export { default as MerchantButton } from '../components/MerchantButton.svelte';
export { default as MerchantCard } from '../components/MerchantCard.svelte';
export { default as MerchantEvent } from '../components/MerchantEvent.svelte';
export { default as MerchantLink } from '../components/MerchantLink.svelte';
export { default as MerchantOG } from '../components/MerchantOG.svelte';
export { default as NavDropdownDesktop } from '../components/NavDropdownDesktop.svelte';
export { default as NavDropdownMobile } from '../components/NavDropdownMobile.svelte';
export { default as OpenTicket } from '../components/OpenTicket.svelte';
Expand Down
6 changes: 4 additions & 2 deletions src/routes/merchant/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,15 @@
map.remove();
}
});
const ogImage = `https://btcmap.org/og/merchant?lat=${data.lat}&lon=${data.lon}`;
</script>

<svelte:head>
<title>{name ? name + ' - ' : ''}BTC Map Merchant</title>
<meta property="og:image" content="https://btcmap.org/images/og/merchant.png" />
<meta property="og:image" content={ogImage} />
<meta property="twitter:title" content="{name ? name + ' - ' : ''}BTC Map Merchant" />
<meta property="twitter:image" content="https://btcmap.org/images/og/merchant.png" />
<meta property="twitter:image" content={ogImage} />

{#if payment && payment.type === 'uri' && payment.url?.startsWith('lightning:')}
<meta name="lightning" content="lnurlp:{payment.url.slice(10, payment.url.length)}" />
Expand Down
12 changes: 9 additions & 3 deletions src/routes/merchant/[id]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { latCalc, longCalc } from '$lib/map/setup';
import type { Element } from '$lib/types';
import { error } from '@sveltejs/kit';
import axios from 'axios';
import axiosRetry from 'axios-retry';
Expand All @@ -10,12 +12,16 @@ export const load: PageLoad = async ({ params }) => {
try {
const response = await axios.get(`https://api.btcmap.org/v2/elements/${id}`);

const data = response.data;
const data: Element = response.data;
const lat = latCalc(data.osm_json);
const lon = longCalc(data.osm_json);

if (data && data.id && !data['deleted_at']) {
if (data && data.id && lat && lon && !data['deleted_at']) {
return {
id: data.id,
name: data.osm_json.tags?.name
name: data.osm_json.tags?.name,
lat,
lon
};
}
} catch (err) {
Expand Down
38 changes: 38 additions & 0 deletions src/routes/og/generateImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { read } from '$app/server';
import { Resvg } from '@resvg/resvg-js';
import satori from 'satori';
import { html as toReactNode } from 'satori-html';
import Manrope from '/static/fonts/Manrope-Regular.ttf';

const fontData = read(Manrope).arrayBuffer();

const height = 630;
const width = 1200;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const generateImage = async (component: any) => {
const jsx = toReactNode(`${component.html}<style>${component.css.code}</style>`);

const svg = await satori(jsx, {
fonts: [
{
name: 'Manrope',
data: await fontData,
style: 'normal'
}
],
height,
width
});

const resvg = new Resvg(svg, {
fitTo: {
mode: 'width',
value: width
}
});

const image = resvg.render();

return image.asPng();
};
22 changes: 22 additions & 0 deletions src/routes/og/merchant/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { STADIA_API_KEY } from '$env/static/private';
import { MerchantOG } from '$lib/comp';
import { generateImage } from '../generateImage';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async ({ url }) => {
const lat = url.searchParams.get('lat');
const lon = url.searchParams.get('lon');

if (!lat || !lon) return new Response(undefined, { status: 418 });

const component = MerchantOG.render({ lat, lon, STADIA_API_KEY });

const image = await generateImage(component);

return new Response(image, {
headers: {
'content-type': 'image/png',
'cache-control': 'max-age=31449600'
}
});
};
2 changes: 1 addition & 1 deletion svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-netlify';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
Expand Down
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [sveltekit()]
plugins: [sveltekit()],
optimizeDeps: { exclude: ['@resvg/resvg-js'] }
});
Loading

0 comments on commit cf15051

Please sign in to comment.