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
12 changes: 9 additions & 3 deletions .cache/pages.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@
"contact",
"offline",
{
"privacy": ["my-data"]
"privacy": [
"my-data"
]
},
{
"services": ["consulting", "overview", "web-development"]
"services": [
"consulting",
"overview",
"web-development"
]
},
{
"tags": [
Expand All @@ -47,4 +53,4 @@
"typescript"
]
}
]
]
134 changes: 10 additions & 124 deletions _TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ text-white, other default Tailwind colors

## Typing client-side API calls and SSR API endpoints

Use Astro Actions

Shared Types vs Swagger / Keeping Docs in Sync

1. Type-only sharing (current approach)
Expand Down Expand Up @@ -117,21 +119,6 @@ fatal: /home/kevin/Repos/Webstack: '/home/kevin/Repos/Webstack' is outside repos

⚠️ Privacy policy version fallback applied: 2025-12-08

## @TODO: Add Check HTML Links to test workflow

npm i -D check-html-links
npx check-html-links _site
`https://github.com/modernweb-dev/rocket/tree/main/packages/check-html-links`

22:38:43 [ERROR] [astro-link-validator] ❌ Found 2 broken links:
\n📄 index.html:
🔗 /services/web-development
File not found: services/web-development
Text: "Improve Your Product"
🔗 /services/consulting
File not found: services/consulting
Text: "Start from scratch"

## Tags

Can we add a markdown page to explain what each tag is, and use those pages instead of src/content/_tagList.ts to define the tags available?
Expand All @@ -140,118 +127,44 @@ Can we add a markdown page to explain what each tag is, and use those pages inst

Looking at the social-card endpoint implementation, it's designed to work with third-party screenshot services, not the social networks themselves.

Here's how it works:

The Two Formats
HTML format (format=html or default): Returns a full HTML page with inline CSS styled as a 1200x630px card - the standard Open Graph image dimensions.

OG format (format=og): Returns JSON with Open Graph meta tags, where the og:image URL points back to the HTML version of the card.

How Social Networks Actually Work
Social networks like Twitter, Facebook, LinkedIn, etc. don't screenshot HTML pages. They expect:

- Direct image URLs (PNG, JPEG, etc.)
- Standard dimensions (1200x630px for most platforms)

**The Intended Workflow**

This endpoint is designed to integrate with screenshot services like:

- Puppeteer or Playwright - Run your own screenshot service
- Vercel OG Image Generation - Vercel's built-in service
- Cloudinary - Can fetch and screenshot URLs
- ScreenshotOne or ApiFlash - Dedicated screenshot APIs
- Satori - Convert HTML/CSS to SVG/PNG

**Current Limitation**

As implemented, this endpoint would need an additional step to be useful for social sharing:

Your endpoint → Screenshot service → Image file → Social networks

Better Approaches

For a production Astro site, you'd typically:

- Use @vercel/og or Satori to generate actual images server-side
- Pre-generate images at build time for static content
- Use a screenshot service that can be called from your endpoint to return actual images

**Social Media Preview Generators**

There are several integrations available that vary based on the library they use to create an image file to snapshot, whether they allow the template for generating the image to be modified, and what options they provide for output.

[`astro-og-canvas`](https://www.npmjs.com/package/astro-og-canvas)

- Most popular option (~660 weekly d/l). Generates images at **run time**.
- Uses **`canvaskit-wasm`** for rendering
- Uses plain color or gradient background. Provide title, description, and logo (displayed at top left of card).
- Can't set size of final card.

[`astro-satori`](https://www.npmjs.com/package/astro-satori)

- Moderately popular option (~230 weekly d/l). Generates images at **run time**.
- Uses Vercel's **Satori** library for rendering (entirely done in JS with limitations on what CSS can be used). Satori is a library for generating SVG strings from pure HTML and CSS.
- Size of final card can be set.
- Seems opinionated, but it might be possible to have a lot of control (not sure).
- Output format?

[`astro-opengraph-image`](https://www.npmjs.com/package/@altano/astro-opengraph-image#fn-filename-change)

- Uses **Satori**. Has dependencies on [`@resvg/resvg-wasm`](https://www.npmjs.com/package/@resvg/resvg-wasm) and Sharp. Middleware integration. Generates images at **run time**.
- Provides element to add OG tags in document `<head>`.
- Very flexible, you can provide the Astro template to generate the card.

[Astro Open Graph Image](https://www.npmjs.com/package/astro-og-image)

- Uses **Puppeteer**. Generates images at **build time**.
- You can provide the Astro template to generate the card.
- Requires providing a `baseHead` property in page templates.

[Astro Open Graph Image Generator](https://www.npmjs.com/package/@cyberkoalastudios/og-image-generator)

- Uses **Puppeteer**. Has dependencies on [`canvaskit-wasm`](https://www.npmjs.com/package/@resvg/resvg-wasm) and Sharp.
- You can set the background image. No option to set the size of the card.
- Manually add OF properties on `<head>` element. Flexible.

## @TODO: Use Confetti on CTA forms
## Use Confetti on CTA forms

`canvas-confetti`
`https://github.com/catdad/canvas-confetti`
`https://www.kirilv.com/canvas-confetti/`

## @TODO: Use the Page Visibility API to pause videos, image carousels, and animations
## Use the Page Visibility API to pause videos, image carousels, and animations

Stop unnecessary processes when the user doesn't see the page or inversely to perform background actions.

## @TODO: "Add to Calendar" button
## "Add to Calendar" button

Google Calendar, Apple Calendar, Yahoo Calender, Microsoft 365, Outlook, and Teams, and generate iCal/ics files (for all other calendars and cases).

`https://github.com/add2cal/add-to-calendar-button`
`https://add-to-calendar-button.com/`

## @TODO: Set up webmentions
## Set up webmentions

Needs to add real API key and test

## @TODO: SCSS Use clothoid corners with border-radius
## SCSS Use clothoid corners with border-radius

`https://onotakehiko.dev/clothoid/`

`@TODO: SCSS Make sure accent-color or styling for checkboxes/radio button groups is set up. Sets the colour used by checkboxes and radio buttons, as well as range fields and progress indicators. The accent colour is inherited`
`SCSS Make sure accent-color or styling for checkboxes/radio button groups is set up. Sets the colour used by checkboxes and radio buttons, as well as range fields and progress indicators. The accent colour is inherited`

```scss
:root{
accent-color : #696;
}
```

## @TODO: Refactor modals
## Refactor modals

Modals should be wrapped in the `<dialog>` element and use programmatic methods to display - `showModal()` to disable the area outside of the modal (handles `esc` keypress natively) and `show()` to allow interaction outside the modal, along with `close()`.

## @TODO: Add for iOS
## Add for iOS

Specifying a Launch Screen Image

Expand Down Expand Up @@ -383,33 +296,6 @@ Adds some custom directives:

Allows any Mastodon instance to discover your Mastodon profile directly from your own domain.

## Preload hero images, usually loaded after stylesheets and fonts

```font
<head>
<!-- Hey browser! Please preload this important responsive image -->
<link
rel="preload"
as="image"
imagesrcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1600.jpg 1600w"
imagesizes="100vw"
>
</head>
<body>
<img
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1600.jpg 1600w"
sizes="100vw"
alt="..."
>
</body>
```

## Refactor social neworks in Authors collection to Contact collection format

The contact data collection uses an array of social networks, with keys:
Expand Down
6 changes: 6 additions & 0 deletions astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ export default defineConfig({
/** API routes are marked in their files for SSR */
output: 'static',
prefetch: true,
image: {
remotePatterns: [
{ protocol: 'https' },
{ protocol: 'http' },
],
},
/** Change URL between development and production environments */
site: getSiteUrl(),
trailingSlash: 'never',
Expand Down
45 changes: 45 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"astro": "5.16.4",
"astro-icon": "^1.1.5",
"astro-link-validator": "github:rodgtr1/astro-link-validator",
"astro-og-canvas": "^0.7.2",
"astro-vtbot": "^2.1.9",
"cross-env": "^10.1.0",
"dotenv": "17.2.3",
Expand Down
12 changes: 5 additions & 7 deletions src/components/Head/Meta.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import { getSiteUrl } from '@lib/config/siteUrlServer'
import contactData from '@content/contact.json'
import { absoluteUrl } from '@components/scripts/utils'
import { getMetaThemeData } from '@components/Head/server/meta'
Expand All @@ -13,7 +14,7 @@ export interface Props {
contentType?: 'article' | 'website'
/** Meta description */
description?: string
image?: string
/** Last modified date */
modifiedDate?: Date
/** Whether search engines should ignore the page, default: false */
noindex?: boolean
Expand All @@ -33,7 +34,6 @@ const {
author,
contentType,
description,
image,
modifiedDate,
noindex = false,
pageTitle,
Expand All @@ -43,7 +43,7 @@ const {
tags,
} = Astro.props

const { slug, defaultTheme } = getMetaThemeData(path)
const defaultTheme = getMetaThemeData()
---

<meta http-equiv="X-UA-Compatible" content="IE=edge" />
Expand All @@ -64,15 +64,13 @@ const { slug, defaultTheme } = getMetaThemeData(path)
<Social
title={pageTitle}
description={description || contactData.company.description}
slug={slug}
{...image && { image }}
path={path}
/>
{/* JSON-LD Structured Data for search engines */}
<StructuredData
path={path}
pageTitle={pageTitle}
{...description && { description }}
{...image && { image }}
{...contentType && { contentType }}
{...publishDate && { publishDate }}
{...modifiedDate && { modifiedDate }}
Expand Down Expand Up @@ -100,7 +98,7 @@ const { slug, defaultTheme } = getMetaThemeData(path)
<link
type="application/rss+xml"
rel="alternate"
href={absoluteUrl('rss.xml', Astro.site)}
href={absoluteUrl('rss.xml', new URL(getSiteUrl()))}
title={`RSS Feed for ${contactData.company.name}`}
/>
{/* Web App Manifest */}
Expand Down
Loading
Loading