Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const styles = {
'linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.6) 100vh, rgba(0,0,0,1) 100%)',
WebkitMaskImage:
'linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.6) 100vh, rgba(0,0,0,1) 100%)',
willChange: 'transform',
transform: 'translateZ(0)',
} as React.CSSProperties,
main: {
width: 'min(900px,96vw)',
Expand Down
8 changes: 4 additions & 4 deletions src/features/messages/MessageTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MultiProtocolProvider } from '@hyperlane-xyz/sdk';
import { shortenAddress } from '@hyperlane-xyz/utils';
import Image from 'next/image';
import Link from 'next/link';
import { PropsWithChildren, ReactNode, useMemo } from 'react';
import { PropsWithChildren, ReactNode, memo, useMemo } from 'react';
import { ChainLogo } from '../../components/icons/ChainLogo';
import { CheckmarkIcon } from '../../components/icons/CheckmarkIcon';
import { TokenIcon } from '../../components/icons/TokenIcon';
Expand Down Expand Up @@ -59,7 +59,7 @@ export function MessageTable({
);
}

export function MessageSummaryRow({
export const MessageSummaryRow = memo(function MessageSummaryRow({
message,
mp,
warpRouteChainAddressMap,
Expand Down Expand Up @@ -154,7 +154,7 @@ export function MessageSummaryRow({
</LinkCell>
</>
);
}
});

function LinkCell({
id,
Expand All @@ -167,7 +167,7 @@ function LinkCell({
const params = base64 ? `?data=${base64}` : '';
return (
<td className={tdClasses}>
<Link href={`${path}${params}`} className={aClasses}>
<Link href={`${path}${params}`} prefetch={true} className={aClasses}>
{children}
</Link>
</td>
Expand Down
14 changes: 4 additions & 10 deletions src/features/messages/cards/ContentDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,10 @@ export function ContentDetailsCard({
const getBlockExplorerLinks = useCallback(async (): Promise<
BlockExplorerAddressUrls | undefined
> => {
const senderAddressLink = await tryGetBlockExplorerAddressUrl(
multiProvider,
originChainId,
formattedSender,
);
const recipientAddressLink = await tryGetBlockExplorerAddressUrl(
multiProvider,
destinationChainId,
formattedRecipient,
);
const [senderAddressLink, recipientAddressLink] = await Promise.all([
tryGetBlockExplorerAddressUrl(multiProvider, originChainId, formattedSender),
tryGetBlockExplorerAddressUrl(multiProvider, destinationChainId, formattedRecipient),
]);
return { sender: senderAddressLink, recipient: recipientAddressLink };
}, [destinationChainId, originChainId, multiProvider, formattedSender, formattedRecipient]);

Expand Down
6 changes: 4 additions & 2 deletions src/features/messages/cards/KeyValueRow.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { memo } from 'react';

import { isZeroish } from '@hyperlane-xyz/utils';
import { BoxArrowIcon, CopyButton } from '@hyperlane-xyz/widgets';
import { truncateString } from '../../../utils/string';
Expand All @@ -17,7 +19,7 @@ interface Props {
truncateMiddle?: boolean;
}

export function KeyValueRow({
export const KeyValueRow = memo(function KeyValueRow({
label,
labelWidth,
display,
Expand Down Expand Up @@ -58,7 +60,7 @@ export function KeyValueRow({
</div>
</div>
);
}
});

function LinkIcon({ href }: { href: string }) {
return (
Expand Down
15 changes: 15 additions & 0 deletions src/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ export default function Document() {
<Head>
<meta charSet="utf-8" />

<link
rel="preload"
href="/fonts/PPValve-PlainVariable.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
<link
rel="preload"
href="/fonts/PPFraktionMono-Variable.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>

<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
Expand Down
14 changes: 13 additions & 1 deletion src/pages/message/[messageId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,14 @@ export const getServerSideProps: GetServerSideProps<PageProps> = async (ctx) =>
const protocol = host.includes('localhost') ? 'http' : 'https';
const baseUrl = `${protocol}://${host}`;

if (messageId && typeof messageId === 'string') {
// Skip OG data fetching for non-bot user agents (speeds up navigation for real users)
const userAgent = ctx.req?.headers['user-agent'] || '';
const isBot =
/bot|crawl|spider|slurp|facebookexternalhit|Twitterbot|LinkedInBot|Discordbot|WhatsApp/i.test(
userAgent,
);

if (isBot && messageId && typeof messageId === 'string') {
try {
const [messageData, domainNames, chainMetadata] = await Promise.all([
fetchMessageForOG(messageId),
Expand All @@ -125,6 +132,11 @@ export const getServerSideProps: GetServerSideProps<PageProps> = async (ctx) =>
}
}

// Cache the response for real users (instant navigation) while bots get fresh data
if (!isBot) {
ctx.res.setHeader('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public, s-maxage=60 on the non-bot HTML is cache-unsafe here. Because the response varies by user agent but doesn’t have a safe cache key split, a CDN can cache the ogData: null human response and serve it to bots, breaking OG tags in the common user-visit-then-share flow. In #295 this is fixed by avoiding shared HTML caching on this route rather than relying on bot/human cache variation.

}

return {
props: {
ogData,
Expand Down
19 changes: 10 additions & 9 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,13 @@ svg path[fill='white'] {
}

/* Widget text styling - default to primary font */
[class*='htw-'] {
.htw-text-sm,
.htw-text-xs,
.htw-text-base,
.htw-text-lg,
.htw-font-medium,
.htw-font-normal,
.htw-font-light {
font-family: 'PP Fraktion Mono', system-ui, sans-serif;
}

Expand All @@ -319,11 +325,7 @@ svg path[fill='white'] {
}

/* Explicitly set mono for technical content */
.htw-font-mono,
[class*='htw-'] input,
[class*='htw-'] textarea,
[class*='htw-'] a[href^='http'],
[class*='htw-'] a[href^='https'] {
.htw-font-mono {
font-family: 'PP Fraktion Mono', system-ui, monospace !important;
}

Expand All @@ -334,7 +336,8 @@ svg path[fill='white'] {
}

/* Input backgrounds in widgets */
[class*='htw-'] input {
.htw-bg-white input,
.htw-bg-gray-100 input {
background-color: #f8f8ff !important;
}

Expand All @@ -359,12 +362,10 @@ svg path[fill='white'] {
}

/* Widget hover states - match message table accent colors */
[class*='htw-']:hover.hover\:htw-bg-gray-100,
.hover\:htw-bg-gray-100:hover {
background-color: #e8caff !important; /* accent-50 */
}

[class*='htw-']:hover.hover\:htw-bg-gray-200,
.hover\:htw-bg-gray-200:hover {
background-color: #d9a4ff !important; /* accent-100 */
}
Expand Down
2 changes: 1 addition & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ module.exports = {
'brand-gradient': `radial-gradient(ellipse 200% 150% at 50% 100%, ${theme('colors.primary.800')} 0%, ${theme('colors.primary.950')} 40%, #0d0612 100%)`,
}),
boxShadow: ({ theme }) => ({
'accent-glow': `inset 0 0 20px 0 rgba(154, 13, 255, 0.35)`,
'accent-glow': `inset 0 0 10px 0 rgba(154, 13, 255, 0.35)`,
card: `0px 4px 6px ${theme('colors.gray.950')}1A`,
button: `0 4px 6px ${theme('colors.gray.950')}1A`,
input: `0 0 4px ${theme('colors.gray.400')}4D`,
Expand Down
Loading