diff --git a/frontend/src/app/components/about/about.component.ts b/frontend/src/app/components/about/about.component.ts
index 3fea849a1..44bee5828 100644
--- a/frontend/src/app/components/about/about.component.ts
+++ b/frontend/src/app/components/about/about.component.ts
@@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, ElementRef, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core';
import { WebsocketService } from '../../services/websocket.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { StateService } from '../../services/state.service';
import { Observable } from 'rxjs';
import { ApiService } from '../../services/api.service';
@@ -33,6 +34,7 @@ export class AboutComponent implements OnInit {
constructor(
private websocketService: WebsocketService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
public stateService: StateService,
private enterpriseService: EnterpriseService,
private apiService: ApiService,
@@ -46,6 +48,7 @@ export class AboutComponent implements OnInit {
this.backendInfo$ = this.stateService.backendInfo$;
this.seoService.setTitle($localize`:@@004b222ff9ef9dd4771b777950ca1d0e4cd4348a:About`);
this.seoService.setDescription($localize`:@@meta.description.about:Learn more about The Mempool Open Source Project®\: enterprise sponsors, individual sponsors, integrations, who contributes, FOSS licensing, and more.`);
+ this.ogService.setManualOgImage('about.jpg');
this.websocketService.want(['blocks']);
this.profiles$ = this.apiService.getAboutPageProfiles$().pipe(
diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts
index 91b77f5e8..877f4414d 100644
--- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts
+++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts
@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component, HostListener, OnInit } from '@angular/core';
import { SeoService } from '../../../services/seo.service';
+import { OpenGraphService } from '../../../services/opengraph.service';
import { WebsocketService } from '../../../services/websocket.service';
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
import { StateService } from '../../../services/state.service';
@@ -34,11 +35,13 @@ export class AcceleratorDashboardComponent implements OnInit {
constructor(
private seoService: SeoService,
+ private ogService: OpenGraphService,
private websocketService: WebsocketService,
private serviceApiServices: ServicesApiServices,
private stateService: StateService,
) {
this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Accelerator Dashboard`);
+ this.ogService.setManualOgImage('accelerator.jpg');
}
ngOnInit(): void {
diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.ts b/frontend/src/app/components/blocks-list/blocks-list.component.ts
index 196a0341e..23280e1ef 100644
--- a/frontend/src/app/components/blocks-list/blocks-list.component.ts
+++ b/frontend/src/app/components/blocks-list/blocks-list.component.ts
@@ -6,6 +6,7 @@ import { ApiService } from '../../services/api.service';
import { StateService } from '../../services/state.service';
import { WebsocketService } from '../../services/websocket.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { seoDescriptionNetwork } from '../../shared/common.utils';
@Component({
@@ -39,6 +40,7 @@ export class BlocksList implements OnInit {
public stateService: StateService,
private cd: ChangeDetectorRef,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) {
this.isMempoolModule = this.stateService.env.BASE_MODULE === 'mempool';
}
@@ -57,6 +59,7 @@ export class BlocksList implements OnInit {
if (!this.widget) {
this.seoService.setTitle($localize`:@@m8a7b4bd44c0ac71b2e72de0398b303257f7d2f54:Blocks`);
+ this.ogService.setManualOgImage('recent-blocks.jpg');
}
if( this.stateService.network==='liquid'||this.stateService.network==='liquidtestnet' ) {
this.seoService.setDescription($localize`:@@meta.description.liquid.blocks:See the most recent Liquid${seoDescriptionNetwork(this.stateService.network)} blocks along with basic stats such as block height, block size, and more.`);
diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
index cfc8ef230..96058e7bf 100644
--- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
+++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.ts
@@ -1,5 +1,6 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, OnInit } from '@angular/core';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { WebsocketService } from '../../services/websocket.service';
import { StateService } from '../../services/state.service';
import { EventType, NavigationStart, Router } from '@angular/router';
@@ -15,12 +16,14 @@ export class MiningDashboardComponent implements OnInit, AfterViewInit {
constructor(
private seoService: SeoService,
+ private ogService: OpenGraphService,
private websocketService: WebsocketService,
private stateService: StateService,
private router: Router
) {
this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Mining Dashboard`);
this.seoService.setDescription($localize`:@@meta.description.mining.dashboard:Get real-time Bitcoin mining stats like hashrate, difficulty adjustment, block rewards, pool dominance, and more.`);
+ this.ogService.setManualOgImage('mining.jpg');
}
ngOnInit(): void {
diff --git a/frontend/src/app/components/privacy-policy/privacy-policy.component.ts b/frontend/src/app/components/privacy-policy/privacy-policy.component.ts
index b98390731..05f77c063 100644
--- a/frontend/src/app/components/privacy-policy/privacy-policy.component.ts
+++ b/frontend/src/app/components/privacy-policy/privacy-policy.component.ts
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { Env, StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
@Component({
selector: 'app-privacy-policy',
@@ -13,10 +14,12 @@ export class PrivacyPolicyComponent {
constructor(
private stateService: StateService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
this.seoService.setTitle('Privacy Policy');
this.seoService.setDescription('Trusted third parties are security holes, as are trusted first parties...you should only trust your own self-hosted instance of The Mempool Open Source Project®.');
+ this.ogService.setManualOgImage('privacy.jpg');
}
}
diff --git a/frontend/src/app/components/push-transaction/push-transaction.component.ts b/frontend/src/app/components/push-transaction/push-transaction.component.ts
index cbc5d905a..a85cd47db 100644
--- a/frontend/src/app/components/push-transaction/push-transaction.component.ts
+++ b/frontend/src/app/components/push-transaction/push-transaction.component.ts
@@ -3,6 +3,7 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms
import { ApiService } from '../../services/api.service';
import { StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { seoDescriptionNetwork } from '../../shared/common.utils';
@Component({
@@ -21,6 +22,7 @@ export class PushTransactionComponent implements OnInit {
private apiService: ApiService,
public stateService: StateService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
@@ -30,6 +32,7 @@ export class PushTransactionComponent implements OnInit {
this.seoService.setTitle($localize`:@@meta.title.push-tx:Broadcast Transaction`);
this.seoService.setDescription($localize`:@@meta.description.push-tx:Broadcast a transaction to the ${this.stateService.network==='liquid'||this.stateService.network==='liquidtestnet'?'Liquid':'Bitcoin'}${seoDescriptionNetwork(this.stateService.network)} network using the transaction's hash.`);
+ this.ogService.setManualOgImage('broadcast-tx.jpg');
}
postTx() {
diff --git a/frontend/src/app/components/rbf-list/rbf-list.component.ts b/frontend/src/app/components/rbf-list/rbf-list.component.ts
index 0721c7fdf..ff30dd1c9 100644
--- a/frontend/src/app/components/rbf-list/rbf-list.component.ts
+++ b/frontend/src/app/components/rbf-list/rbf-list.component.ts
@@ -7,6 +7,7 @@ import { RbfTree } from '../../interfaces/node-api.interface';
import { ApiService } from '../../services/api.service';
import { StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { seoDescriptionNetwork } from '../../shared/common.utils';
@Component({
@@ -29,6 +30,7 @@ export class RbfList implements OnInit, OnDestroy {
public stateService: StateService,
private websocketService: WebsocketService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
@@ -57,6 +59,7 @@ export class RbfList implements OnInit, OnDestroy {
this.seoService.setTitle($localize`:@@5e3d5a82750902f159122fcca487b07f1af3141f:RBF Replacements`);
this.seoService.setDescription($localize`:@@meta.description.rbf-list:See the most recent RBF replacements on the Bitcoin${seoDescriptionNetwork(this.stateService.network)} network, updated in real-time.`);
+ this.ogService.setManualOgImage('rbf.jpg');
}
ngOnDestroy(): void {
diff --git a/frontend/src/app/components/terms-of-service/terms-of-service.component.ts b/frontend/src/app/components/terms-of-service/terms-of-service.component.ts
index 708ebad76..71a86c759 100644
--- a/frontend/src/app/components/terms-of-service/terms-of-service.component.ts
+++ b/frontend/src/app/components/terms-of-service/terms-of-service.component.ts
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { Env, StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
@Component({
selector: 'app-terms-of-service',
@@ -12,10 +13,12 @@ export class TermsOfServiceComponent {
constructor(
private stateService: StateService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
this.seoService.setTitle('Terms of Service');
this.seoService.setDescription('Out of respect for the Bitcoin community, the mempool.space website is Bitcoin Only and does not display any advertising.');
+ this.ogService.setManualOgImage('tos.jpg');
}
}
diff --git a/frontend/src/app/components/trademark-policy/trademark-policy.component.ts b/frontend/src/app/components/trademark-policy/trademark-policy.component.ts
index b8f53afcf..ad8b6b372 100644
--- a/frontend/src/app/components/trademark-policy/trademark-policy.component.ts
+++ b/frontend/src/app/components/trademark-policy/trademark-policy.component.ts
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { Env, StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
@Component({
selector: 'app-trademark-policy',
@@ -13,10 +14,12 @@ export class TrademarkPolicyComponent {
constructor(
private stateService: StateService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
this.seoService.setTitle('Trademark Policy');
this.seoService.setDescription('An overview of the trademarks registered by Mempool Space K.K. and The Mempool Open Source Project® and what we consider to be lawful usage of those trademarks.');
+ this.ogService.setManualOgImage('trademark-policy.jpg');
}
}
diff --git a/frontend/src/app/docs/docs/docs.component.ts b/frontend/src/app/docs/docs/docs.component.ts
index 6d6c3b0c1..e3737b545 100644
--- a/frontend/src/app/docs/docs/docs.component.ts
+++ b/frontend/src/app/docs/docs/docs.component.ts
@@ -3,6 +3,7 @@ import { ActivatedRoute } from '@angular/router';
import { Env, StateService } from '../../services/state.service';
import { WebsocketService } from '../../services/websocket.service';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
@Component({
selector: 'app-docs',
@@ -24,6 +25,7 @@ export class DocsComponent implements OnInit {
private stateService: StateService,
private websocket: WebsocketService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
) { }
ngOnInit(): void {
@@ -44,6 +46,7 @@ export class DocsComponent implements OnInit {
this.activeTab = 0;
this.seoService.setTitle($localize`:@@meta.title.docs.faq:FAQ`);
this.seoService.setDescription($localize`:@@meta.description.docs.faq:Get answers to common questions like: What is a mempool? Why isn't my transaction confirming? How can I run my own instance of The Mempool Open Source Project? And more.`);
+ this.ogService.setManualOgImage('faq.jpg');
} else if( url[1].path === "rest" ) {
this.activeTab = 1;
this.seoService.setTitle($localize`:@@meta.title.docs.rest:REST API`);
diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
index 63cdab42d..a8c931da8 100644
--- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
+++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts
@@ -3,6 +3,7 @@ import { Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import { INodesRanking, INodesStatistics } from '../../interfaces/node-api.interface';
import { SeoService } from '../../services/seo.service';
+import { OpenGraphService } from '../../services/opengraph.service';
import { StateService } from '../../services/state.service';
import { LightningApiService } from '../lightning-api.service';
@@ -21,14 +22,16 @@ export class LightningDashboardComponent implements OnInit, AfterViewInit {
constructor(
private lightningApiService: LightningApiService,
private seoService: SeoService,
+ private ogService: OpenGraphService,
private stateService: StateService,
) { }
ngOnInit(): void {
this.onResize();
-
+
this.seoService.setTitle($localize`:@@142e923d3b04186ac6ba23387265d22a2fa404e0:Lightning Explorer`);
this.seoService.setDescription($localize`:@@meta.description.lightning.dashboard:Get stats on the Lightning network (aggregate capacity, connectivity, etc), Lightning nodes (channels, liquidity, etc) and Lightning channels (status, fees, etc).`);
+ this.ogService.setManualOgImage('lightning.jpg');
this.nodesRanking$ = this.lightningApiService.getNodesRanking$().pipe(share());
this.statistics$ = this.lightningApiService.getLatestStatistics$().pipe(share());
diff --git a/frontend/src/app/services/opengraph.service.ts b/frontend/src/app/services/opengraph.service.ts
index 9e2fef781..5e429ed70 100644
--- a/frontend/src/app/services/opengraph.service.ts
+++ b/frontend/src/app/services/opengraph.service.ts
@@ -25,7 +25,7 @@ export class OpenGraphService {
) {
// save og:image tag from original template
const initialOgImageTag = metaService.getTag("property='og:image'");
- this.defaultImageUrl = initialOgImageTag?.content || 'https://mempool.space/resources/mempool-space-preview.png';
+ this.defaultImageUrl = initialOgImageTag?.content || 'https://mempool.space/resources/previews/mempool-space-preview.jpg';
this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => this.activatedRoute),
@@ -53,7 +53,7 @@ export class OpenGraphService {
const lang = this.LanguageService.getLanguage();
const ogImageUrl = `${window.location.protocol}//${window.location.host}/render/${lang}/preview${this.router.url}`;
this.metaService.updateTag({ property: 'og:image', content: ogImageUrl });
- this.metaService.updateTag({ property: 'twitter:image:src', content: ogImageUrl });
+ this.metaService.updateTag({ name: 'twitter:image', content: ogImageUrl });
this.metaService.updateTag({ property: 'og:image:type', content: 'image/png' });
this.metaService.updateTag({ property: 'og:image:width', content: '1200' });
this.metaService.updateTag({ property: 'og:image:height', content: '600' });
@@ -61,12 +61,21 @@ export class OpenGraphService {
clearOgImage() {
this.metaService.updateTag({ property: 'og:image', content: this.defaultImageUrl });
- this.metaService.updateTag({ property: 'twitter:image:src', content: this.defaultImageUrl });
+ this.metaService.updateTag({ name: 'twitter:image', content: this.defaultImageUrl });
this.metaService.updateTag({ property: 'og:image:type', content: 'image/png' });
this.metaService.updateTag({ property: 'og:image:width', content: '1000' });
this.metaService.updateTag({ property: 'og:image:height', content: '500' });
}
+ setManualOgImage(imageFilename) {
+ const ogImage = `${window.location.protocol}//${window.location.host}/resources/previews/${imageFilename}`;
+ this.metaService.updateTag({ property: 'og:image', content: ogImage });
+ this.metaService.updateTag({ property: 'og:image:type', content: 'image/jpeg' });
+ this.metaService.updateTag({ property: 'og:image:width', content: '2000' });
+ this.metaService.updateTag({ property: 'og:image:height', content: '1000' });
+ this.metaService.updateTag({ name: 'twitter:image', content: ogImage });
+ }
+
/// register an event that needs to resolve before we can take a screenshot
waitFor(event) {
if (!this.previewLoadingEvents[event]) {
diff --git a/frontend/src/app/services/seo.service.ts b/frontend/src/app/services/seo.service.ts
index 7830690ff..cb9a321d6 100644
--- a/frontend/src/app/services/seo.service.ts
+++ b/frontend/src/app/services/seo.service.ts
@@ -39,14 +39,14 @@ export class SeoService {
setTitle(newTitle: string): void {
this.titleService.setTitle(newTitle + ' - ' + this.getTitle());
this.metaService.updateTag({ property: 'og:title', content: newTitle});
- this.metaService.updateTag({ property: 'twitter:title', content: newTitle});
+ this.metaService.updateTag({ name: 'twitter:title', content: newTitle});
this.metaService.updateTag({ property: 'og:meta:ready', content: 'ready'});
}
resetTitle(): void {
this.titleService.setTitle(this.getTitle());
this.metaService.updateTag({ property: 'og:title', content: this.getTitle()});
- this.metaService.updateTag({ property: 'twitter:title', content: this.getTitle()});
+ this.metaService.updateTag({ name: 'twitter:title', content: this.getTitle()});
this.metaService.updateTag({ property: 'og:meta:ready', content: 'ready'});
}
diff --git a/frontend/src/index.mempool.html b/frontend/src/index.mempool.html
index def14434e..838af21d0 100644
--- a/frontend/src/index.mempool.html
+++ b/frontend/src/index.mempool.html
@@ -8,17 +8,17 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/frontend/src/resources/previews/about.jpg b/frontend/src/resources/previews/about.jpg
new file mode 100644
index 000000000..720245d9c
Binary files /dev/null and b/frontend/src/resources/previews/about.jpg differ
diff --git a/frontend/src/resources/previews/accelerator.jpg b/frontend/src/resources/previews/accelerator.jpg
new file mode 100644
index 000000000..3a10b7221
Binary files /dev/null and b/frontend/src/resources/previews/accelerator.jpg differ
diff --git a/frontend/src/resources/previews/broadcast-tx.jpg b/frontend/src/resources/previews/broadcast-tx.jpg
new file mode 100644
index 000000000..f035f9d80
Binary files /dev/null and b/frontend/src/resources/previews/broadcast-tx.jpg differ
diff --git a/frontend/src/resources/previews/faq.jpg b/frontend/src/resources/previews/faq.jpg
new file mode 100644
index 000000000..4e198ed49
Binary files /dev/null and b/frontend/src/resources/previews/faq.jpg differ
diff --git a/frontend/src/resources/previews/lightning.jpg b/frontend/src/resources/previews/lightning.jpg
new file mode 100644
index 000000000..59431708c
Binary files /dev/null and b/frontend/src/resources/previews/lightning.jpg differ
diff --git a/frontend/src/resources/previews/mempool-space-preview.jpg b/frontend/src/resources/previews/mempool-space-preview.jpg
new file mode 100644
index 000000000..ca76ba008
Binary files /dev/null and b/frontend/src/resources/previews/mempool-space-preview.jpg differ
diff --git a/frontend/src/resources/previews/mining.jpg b/frontend/src/resources/previews/mining.jpg
new file mode 100644
index 000000000..f36f0ae57
Binary files /dev/null and b/frontend/src/resources/previews/mining.jpg differ
diff --git a/frontend/src/resources/previews/privacy.jpg b/frontend/src/resources/previews/privacy.jpg
new file mode 100644
index 000000000..f6d32bf69
Binary files /dev/null and b/frontend/src/resources/previews/privacy.jpg differ
diff --git a/frontend/src/resources/previews/rbf.jpg b/frontend/src/resources/previews/rbf.jpg
new file mode 100644
index 000000000..f96cf59cb
Binary files /dev/null and b/frontend/src/resources/previews/rbf.jpg differ
diff --git a/frontend/src/resources/previews/recent-blocks.jpg b/frontend/src/resources/previews/recent-blocks.jpg
new file mode 100644
index 000000000..91c44f0de
Binary files /dev/null and b/frontend/src/resources/previews/recent-blocks.jpg differ
diff --git a/frontend/src/resources/previews/tos.jpg b/frontend/src/resources/previews/tos.jpg
new file mode 100644
index 000000000..26865848b
Binary files /dev/null and b/frontend/src/resources/previews/tos.jpg differ
diff --git a/frontend/src/resources/previews/trademark-policy.jpg b/frontend/src/resources/previews/trademark-policy.jpg
new file mode 100644
index 000000000..d9fd24155
Binary files /dev/null and b/frontend/src/resources/previews/trademark-policy.jpg differ
diff --git a/unfurler/src/routes.ts b/unfurler/src/routes.ts
index f9280369c..fefd89902 100644
--- a/unfurler/src/routes.ts
+++ b/unfurler/src/routes.ts
@@ -30,7 +30,7 @@ const routes = {
},
lightning: {
title: "Lightning",
- fallbackImg: '/resources/previews/lightning.png',
+ fallbackImg: '/resources/previews/lightning.jpg',
routes: {
node: {
render: true,
@@ -68,7 +68,7 @@ const routes = {
},
mining: {
title: "Mining",
- fallbackImg: '/resources/previews/mining.png',
+ fallbackImg: '/resources/previews/mining.jpg',
routes: {
pool: {
render: true,
@@ -83,7 +83,7 @@ const routes = {
const networks = {
bitcoin: {
- fallbackImg: '/resources/previews/dashboard.png',
+ fallbackImg: '/resources/previews/mempool-space-preview.jpg',
routes: {
...routes // all routes supported
}
@@ -147,4 +147,4 @@ export function matchRoute(network: string, path: string): Match {
}
return match;
-}
\ No newline at end of file
+}