Skip to content
Merged
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 .github/workflows/deploy-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
- run: npm ci
- run: npm run check
- run: npm run build:site
env:
SOCIAL_IMAGE_ORIGIN: https://beta.perryts.com
- run: npm run check:blog

- name: Deploy beta
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ The Nginx configuration is in `deploy/nginx-beta.conf`, installed at
`/etc/nginx/sites-available/beta.perryts.com` and linked from `sites-enabled`.
It uses the existing Certbot certificate, redirects `/` to `/en/`, handles clean
URLs, and excludes beta from indexing. Canonical URLs still point to production.
Beta builds set `SOCIAL_IMAGE_ORIGIN=https://beta.perryts.com` so social previews
fetch beta's image. Builds without this override use the production origin.

Newsletter requests use a separate `perryts-beta-subscribe` systemd service on
loopback port 3852 (`deploy/perryts-beta-subscribe.service`). It reads the existing
Expand Down
2 changes: 1 addition & 1 deletion deploy-beta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ REMOTE_DIR="/var/www/beta.perryts.com"
RELEASE="$(date -u +%Y%m%dT%H%M%SZ)-$(git rev-parse --short HEAD)"

case "${1:-}" in
"") npm run build:site ;;
"") SOCIAL_IMAGE_ORIGIN=https://beta.perryts.com npm run build:site ;;
--skip-build) ;; # CI has already built and checked this checkout.
*) echo "Usage: $0 [--skip-build]" >&2; exit 2 ;;
esac
Expand Down
Binary file modified public/og.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/perry-social-banner.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 13 additions & 9 deletions src/layouts/Base.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import "../styles/global.css";
import Nav from "../components/Nav.astro";
import Footer from "../components/Footer.astro";
import { locales, localePath, type Locale } from "../i18n/index.ts";
import { metaDescription, pageTitle } from "../lib/seo.ts";
import { DEFAULT_SOCIAL_IMAGE, metaDescription, pageTitle, socialImageUrl } from "../lib/seo.ts";

interface Props {
lang: Locale;
Expand Down Expand Up @@ -33,15 +33,17 @@ const {
titleIsAbsolute = false,
canonical,
alternates = locales,
image = "/og.png",
image = DEFAULT_SOCIAL_IMAGE,
type = "website",
publishedTime,
noindex = false,
} = Astro.props;
const fullTitle = pageTitle(title, titleIsAbsolute);
const descriptionText = metaDescription(description);
const socialTitle = fullTitle.replaceAll("JavaScript/TypeScript", "TypeScript/JavaScript");
const socialDescription = descriptionText.replaceAll("JavaScript/TypeScript", "TypeScript/JavaScript");
const canonicalUrl = new URL(canonical ?? localePath(lang, path), Astro.site);
const imageUrl = new URL(image, Astro.site);
const imageUrl = socialImageUrl(image, Astro.site);
const ogLocale = lang.replace("-", "_");
---

Expand All @@ -62,19 +64,21 @@ const ogLocale = lang.replace("-", "_");
<link rel="preload" href="/fonts/instrument-sans-latin.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/jetbrains-mono-latin.woff2" as="font" type="font/woff2" crossorigin />
<meta property="og:site_name" content="Perry" />
<meta property="og:title" content={fullTitle} />
<meta property="og:description" content={descriptionText} />
<meta property="og:title" content={socialTitle} />
<meta property="og:description" content={socialDescription} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:type" content={type} />
<meta property="og:locale" content={ogLocale} />
<meta property="og:image" content={imageUrl} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:width" content="1731" />
<meta property="og:image:height" content="909" />
{image === DEFAULT_SOCIAL_IMAGE && <meta property="og:image:alt" content="Your TypeScript/JavaScript, compiled to native. Perry." />}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={fullTitle} />
<meta name="twitter:description" content={descriptionText} />
<meta name="twitter:title" content={socialTitle} />
<meta name="twitter:description" content={socialDescription} />
{publishedTime && <meta property="article:published_time" content={publishedTime} />}
<meta name="twitter:image" content={imageUrl} />
{image === DEFAULT_SOCIAL_IMAGE && <meta name="twitter:image:alt" content="Your TypeScript/JavaScript, compiled to native. Perry." />}
<slot name="head" />
<script is:inline>document.documentElement.classList.add("js");</script>
<!-- Plausible (self-hosted), same snippet as the previous site. -->
Expand Down
7 changes: 7 additions & 0 deletions src/lib/seo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ const BRAND = " — Perry";
const TITLE_MAX = 60;
const DESCRIPTION_MAX = 160;

export const DEFAULT_SOCIAL_IMAGE = "/og.png?v=typescript-javascript";

/** Beta serves its own preview image while canonical URLs remain on production. */
export function socialImageUrl(image: string, site: URL | undefined): URL {
return new URL(image, import.meta.env.SOCIAL_IMAGE_ORIGIN || site);
}

/**
* "<title> — Perry". The brand is dropped when the title already names Perry or when it would push
* the title past what search results show.
Expand Down
3 changes: 2 additions & 1 deletion src/pages/[lang]/blog/[slug]/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { messages, plural } from "../../../../i18n/messages.ts";
import { locales, localePath, type Locale } from "../../../../i18n/index.ts";
import { formatPostDate, getPosts, type Post } from "../../../../lib/blog.ts";
import { readingMinutes } from "../../../../lib/reading-time.ts";
import { DEFAULT_SOCIAL_IMAGE, socialImageUrl } from "../../../../lib/seo.ts";

// Every post exists under every locale, like the previous site; untranslated ones show English with a notice.
export async function getStaticPaths() {
Expand Down Expand Up @@ -56,7 +57,7 @@ const blogPosting = {
keywords: entry.data.tags.join(", "),
url,
mainEntityOfPage: url,
image: new URL("/og.png", Astro.site).toString(),
image: socialImageUrl(DEFAULT_SOCIAL_IMAGE, Astro.site).toString(),
author: { "@type": "Organization", name: "Perry", url: "https://perryts.com/" },
publisher: { "@type": "Organization", name: "Perry", logo: { "@type": "ImageObject", url: new URL("/perry-icon.svg", Astro.site).toString() } },
};
Expand Down
Loading