Compare commits

...
Author SHA1 Message Date
Anthony Stirling a25cedfb12 Regenerate SaaS OG metadata after merging main 2026-07-14 09:08:13 +01:00
Anthony Stirling 216d81da49 Merge remote-tracking branch 'origin/main' into saas-og-metadata 2026-07-14 08:57:52 +01:00
Anthony Stirling f429cb468c Move SaaS OG card images into og_images/saas/ subdir 2026-07-14 08:29:14 +01:00
Anthony Stirling dccc540757 Update SaaS OG card art to final headline + product-visual design 2026-07-14 08:08:27 +01:00
Anthony Stirling d0722992d1 Add SaaS OG link-preview cards for app, processor and editor 2026-07-14 07:41:31 +01:00
2b118556f3 Merge hotfix/v2.14.2 into main (#7023)
Merges the `hotfix/v2.14.2` branch into `main`.
on the hotfix branch:

### What this actually changes on `main`
- **Version bump 2.14.1 → 2.14.2** `build.gradle`, `tauri.conf.json`,
both AUR `PKGBUILD`s, and the two `serverExperienceSimulations.ts`
test-config files.
- **Fix Postgres user settings for some users** removes `@Lob` from
`User.java that broke settings for some Postgres users.
- **Release workflow: stop msiexec hang in Windows signature verify**

---------

Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
Co-authored-by: James Brunton <jbrunton96@gmail.com>
Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com>
Co-authored-by: LFdev <146497073+LFd3v@users.noreply.github.com>
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-07-13 23:45:19 +01:00
Anthony Stirling fbaff56d1c Merge hotfix/v2.14.2 into main (v2.14.2 bump, Postgres user settings fix, msiexec release fix) 2026-07-13 20:23:14 +01:00
Anthony Stirling 38ccea074c Version bump 2026-07-08 10:50:37 +01:00
Anthony Stirling a7307ff393 Fix Postgres user settings for some users 2026-07-08 10:50:36 +01:00
Anthony Stirling 72729e99c1 fix(release): stop msiexec hang in Windows signature verify; don't force latest or regen release notes 2026-07-07 23:35:12 +01:00
Anthony Stirling 5fba2720f0 Fix cert sign not showing under certain instances (#6908) 2026-07-07 22:45:56 +01:00
01a1ef8c44 Fix missing app icon on Linux/Wayland (#6875)
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
2026-07-07 22:15:01 +01:00
LudyandAnthony Stirling 8535c7e9ac feat(ui): add dedicated third-party license sections to settings (#6820) 2026-07-07 22:15:01 +01:00
ConnorYohandAnthony Stirling cca3f42623 Set App version to v2.14.1 (#6891)
Upped version in build.gradle then ran build so version falls through
2026-07-07 12:15:01 +01:00
James BruntonandAnthony Stirling 1b7ffcdbac Fix tooltip positioning on Add Page Numbers (#6885)
# Description of Changes
## Before

<img width="483" height="227" alt="image"
src="https://github.com/user-attachments/assets/4bf86eec-a9cc-4f63-84f0-4eb2bd535bab"
/>

## After

<img width="732" height="235" alt="image"
src="https://github.com/user-attachments/assets/101d2ea4-36e8-4e8f-990a-d72b33fa0ac2"
/>
2026-07-07 12:09:51 +01:00
LudyandAnthony Stirling 67a0ca6110 fix(frontend): respect analytics config before initializing PostHog (#6812)
# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Moved PostHog startup out of `index.tsx` and into a config-aware
initializer inside `AppProviders`.
- Added a dedicated `usePosthogTracking` hook that only initializes
PostHog when `enableAnalytics` is explicitly `true` and `enablePosthog`
is not disabled.
- Kept cookie-consent handling in the same flow so consent is applied
only after PostHog is actually initialized.
- Removed the unconditional `PostHogProvider` and `posthog.init(...)`
bootstrap from the app entrypoint.
- Added targeted frontend tests covering analytics-disabled and
analytics-enabled startup behavior.

- Why the change was made
- The previous frontend bootstrap initialized PostHog before app config
was loaded, so disabling analytics in the UI or via environment settings
did not prevent PostHog network activity.
- This change makes analytics behavior follow the server-provided config
instead of always connecting on page load.

Closes #6358

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-07 12:09:51 +01:00
Anthony Stirling 8e4b2e2fc6 Disable update check and notification in SaaS mode (#6863)
# Description of Changes

In SaaS mode the self-hosted "Update Available" notification could still
appear and the update-check code (external call to
`supabase.stirling.com/functions/v1/updates`) still ran, even though the
cloud owns app versioning. The web `UpdateStartupPopup` was already
SaaS-gated via a null override, but two other paths were not:

- **Desktop app in SaaS connection mode** - `useDesktopUpdatePopup()`
ran its startup check and rendered the `UpdateModal` regardless of
connection mode, so a self-hosted update popup appeared while connected
to SaaS.
- **Settings → General** - the core `GeneralSection` fired
`checkForUpdate()` on mount unconditionally, even when the update
section was hidden (as SaaS does), so the external call still ran.

**What changed**

- `useDesktopUpdatePopup.ts` - the startup timer now bails out
immediately when `connectionModeService.getCurrentMode() === "saas"`. No
mode lookup, no external fetch, no modal.
- `core/GeneralSection.tsx` - the mount `checkForUpdate()` now returns
early when `hideUpdateSection` is set, so hiding the section (web SaaS,
managed-disabled desktop) also stops the external call.
- `desktop/GeneralSection.tsx` - passes `hideUpdateSection` when
`useSaaSMode()` is true, which (via the above) suppresses the settings
check in desktop-SaaS too.

**Why** - in SaaS the update check should never be called and no update
notification should be shown; the cloud handles versioning.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-07 12:09:51 +01:00
Anthony Stirling 3c93457021 Fix rearrange-pages DUPLICATE producing shared page nodes (pypdf cyclic-references CI break) (#6851) 2026-07-07 12:09:51 +01:00
20 changed files with 811 additions and 26 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Stirling PDF Inc <contact@stirlingpdf.com>
pkgname=stirling-pdf-desktop
pkgver=2.14.1
pkgver=2.14.2
pkgrel=1
pkgdesc="Locally hosted, web-based PDF manipulation tool (Tauri desktop app, official Stirling PDF Inc build)"
arch=('x86_64')
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Stirling PDF Inc <contact@stirlingpdf.com>
pkgname=stirling-pdf-server-bin
pkgver=2.14.1
pkgver=2.14.2
pkgrel=1
pkgdesc="Locally hosted, web-based PDF manipulation tool (server JAR, prebuilt)"
arch=('any')
+23 -6
View File
@@ -510,6 +510,7 @@ jobs:
# cargo output unsigned, so checking it produces false negatives.
- name: Verify Windows Code Signature
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
timeout-minutes: 15
shell: pwsh
run: |
$allSigned = $true
@@ -531,11 +532,26 @@ jobs:
# Extract MSI and verify the inner exe (the file that actually gets installed).
# This is the critical check - AV flags the installed exe at runtime.
# Use lessmsi, not `msiexec /a`: msiexec serializes on the global
# _MSIExecute mutex and hangs forever on hosted runners when another
# installer is busy. lessmsi reads MSI tables directly - no mutex, no service.
$msi = $msiFiles[0].FullName
$extractDir = Join-Path $env:RUNNER_TEMP "msi-verify"
if (Test-Path $extractDir) { Remove-Item $extractDir -Recurse -Force }
$proc = Start-Process msiexec.exe -ArgumentList '/a', $msi, '/qn', "TARGETDIR=$extractDir" -Wait -PassThru -NoNewWindow
if ($proc.ExitCode -eq 0) {
New-Item -ItemType Directory -Force -Path $extractDir | Out-Null
choco install lessmsi -y --no-progress --limit-output | Out-Null
# Bound the extraction and kill on hang (defence in depth over timeout-minutes).
$proc = Start-Process lessmsi -ArgumentList 'x', "`"$msi`"", "`"$extractDir\`"" -PassThru -NoNewWindow
if (-not $proc.WaitForExit(120000)) {
try { $proc.Kill() } catch {}
Write-Host "[ERROR] MSI extraction timed out after 120s"
$allSigned = $false
} elseif ($proc.ExitCode -ne 0) {
Write-Host "[ERROR] Failed to extract MSI for verification (exit code: $($proc.ExitCode))"
$allSigned = $false
} else {
$innerExe = Get-ChildItem -Path $extractDir -Filter "stirling-pdf.exe" -Recurse -File | Select-Object -First 1
if ($innerExe) {
$sig = Get-AuthenticodeSignature -FilePath $innerExe.FullName
@@ -548,9 +564,6 @@ jobs:
Write-Host "[ERROR] Could not find stirling-pdf.exe inside MSI"
$allSigned = $false
}
} else {
Write-Host "[ERROR] Failed to extract MSI for verification (exit code: $($proc.ExitCode))"
$allSigned = $false
}
if (-not $allSigned) {
@@ -800,7 +813,11 @@ jobs:
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
tag_name: v${{ needs.determine-matrix.outputs.version }}
generate_release_notes: true
# Don't regenerate/append notes on re-runs, and don't force this into the
# "Latest" slot - leave the release body and latest marker as they are.
generate_release_notes: false
append_body: false
make_latest: false
fail_on_unmatched_files: true
# Installers + updater payloads + manifest. .sig contents are embedded
# in latest.json so the .sig files themselves are not uploaded.
@@ -103,7 +103,6 @@ public class User implements UserDetails, Serializable {
@ElementCollection
@MapKeyColumn(name = "setting_key")
@Lob
@Column(name = "setting_value", columnDefinition = "text")
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
@JsonIgnore
+1 -1
View File
@@ -91,7 +91,7 @@ springBoot {
allprojects {
group = 'stirling.software'
version = '2.14.1'
version = '2.14.2'
configurations.configureEach {
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
+1
View File
@@ -11,6 +11,7 @@ editor/public/vendor/
editor/public/mockServiceWorker.js
# Auto-generated OG/social-preview metadata (scripts/generate-og-metadata.mjs); regenerated verbatim.
editor/public/og-metadata.json
editor/public/og-metadata.saas.json
editor/src/core/data/ogImageMap.json
editor/public/pdfjs*/
editor/public/js/thirdParty/
@@ -0,0 +1,679 @@
{
"default": {
"image": "/og_images/saas/app.png",
"title": "Stirling - Edit any PDF. Govern every PDF.",
"ogTitle": "Edit any PDF. Govern every PDF.",
"description": "The free, open-source PDF Editor, plus a Processor that governs every PDF your organization touches. 1¢ per PDF."
},
"byTool": {
"certSign": {
"image": "/og_images/certSign.png",
"title": "Certificate Sign - Stirling PDF",
"description": "Sign PDF documents using digital certificates"
},
"sign": {
"image": "/og_images/sign.png",
"title": "Sign - Stirling PDF",
"description": "Adds signature to PDF by drawing, text or image"
},
"sharedSign": {
"image": "/og_images/home.png",
"title": "Shared Signing - Stirling PDF",
"description": "Request signatures from others and track signing sessions"
},
"addText": {
"image": "/og_images/add-text.png",
"title": "Add Text - Stirling PDF",
"description": "Add custom text anywhere in your PDF"
},
"addPassword": {
"image": "/og_images/add-password.png",
"title": "Add Password - Stirling PDF",
"description": "Add password protection and restrictions to PDF files"
},
"removePassword": {
"image": "/og_images/remove-password.png",
"title": "Remove Password - Stirling PDF",
"description": "Remove password protection from PDF documents"
},
"removePages": {
"image": "/og_images/remove.png",
"title": "Remove Pages - Stirling PDF",
"description": "Remove specific pages from a PDF document"
},
"removeBlanks": {
"image": "/og_images/remove-blank-pages.png",
"title": "Remove Blank Pages - Stirling PDF",
"description": "Remove blank pages from PDF documents"
},
"removeAnnotations": {
"image": "/og_images/remove-annotations.png",
"title": "Remove Annotations - Stirling PDF",
"description": "Remove annotations and comments from PDF documents"
},
"removeImage": {
"image": "/og_images/remove-image.png",
"title": "Remove Images - Stirling PDF",
"description": "Remove all images from a PDF document"
},
"changePermissions": {
"image": "/og_images/change-permissions.png",
"title": "Change Permissions - Stirling PDF",
"description": "Change document restrictions and permissions"
},
"watermark": {
"image": "/og_images/add-watermark.png",
"title": "Add Watermark - Stirling PDF",
"description": "Add a custom watermark to your PDF document."
},
"sanitize": {
"image": "/og_images/sanitize.png",
"title": "Sanitize - Stirling PDF",
"description": "Remove potentially harmful elements from PDF files"
},
"split": {
"image": "/og_images/split.png",
"title": "Split - Stirling PDF",
"description": "Split PDFs into multiple documents"
},
"merge": {
"image": "/og_images/mergePdfs.png",
"title": "Merge - Stirling PDF",
"description": "Merge multiple PDFs into a single document"
},
"convert": {
"image": "/og_images/convert.png",
"title": "Convert - Stirling PDF",
"description": "Convert files to and from PDF format"
},
"ocr": {
"image": "/og_images/ocr.png",
"title": "OCR - Stirling PDF",
"description": "Extract text from scanned PDFs using Optical Character Recognition"
},
"addImage": {
"image": "/og_images/add-image.png",
"title": "Add Image - Stirling PDF",
"description": "Add images anywhere in your PDF"
},
"rotate": {
"image": "/og_images/rotate.png",
"title": "Rotate - Stirling PDF",
"description": "Easily rotate your PDFs."
},
"annotate": {
"image": "/og_images/annotate.png",
"title": "Annotate - Stirling PDF",
"description": "Highlight, draw, add notes, and shapes directly in the viewer"
},
"scannerImageSplit": {
"image": "/og_images/detect-split-scanned-photos.png",
"title": "Detect & Split Scanned Photos - Stirling PDF",
"description": "Detect and split scanned photos into separate pages"
},
"editTableOfContents": {
"image": "/og_images/edit-table-of-contents.png",
"title": "Edit Table of Contents - Stirling PDF",
"description": "Add or edit bookmarks and table of contents in PDF documents"
},
"scannerEffect": {
"image": "/og_images/scanner-effect.png",
"title": "Scanner Effect - Stirling PDF",
"description": "Create a PDF that looks like it was scanned"
},
"autoRename": {
"image": "/og_images/auto-rename-pdf-file.png",
"title": "Auto Rename PDF File - Stirling PDF",
"description": "Automatically rename PDF files based on their content"
},
"pageLayout": {
"image": "/og_images/multi-page-layout.png",
"title": "Multi-Page Layout - Stirling PDF",
"description": "Merge multiple pages of a PDF document into a single page"
},
"scalePages": {
"image": "/og_images/adjust-page-size-scale.png",
"title": "Adjust page size/scale - Stirling PDF",
"description": "Change the size/scale of a page and/or its contents."
},
"adjustContrast": {
"image": "/og_images/adjust-colors-contrast.png",
"title": "Adjust Colors/Contrast - Stirling PDF",
"description": "Adjust colors and contrast of PDF documents"
},
"crop": {
"image": "/og_images/cropPdf.png",
"title": "Crop PDF - Stirling PDF",
"description": "Crop a PDF to reduce its size (maintains text!)"
},
"pdfToSinglePage": {
"image": "/og_images/single-large-page.png",
"title": "PDF to Single Large Page - Stirling PDF",
"description": "Merges all PDF pages into one large single page"
},
"repair": {
"image": "/og_images/repair.png",
"title": "Repair - Stirling PDF",
"description": "Repair corrupted or damaged PDF files"
},
"compare": {
"image": "/og_images/compare.png",
"title": "Compare - Stirling PDF",
"description": "Compare two PDF documents and highlight differences"
},
"addPageNumbers": {
"image": "/og_images/add-page-numbers.png",
"title": "Add Page Numbers - Stirling PDF",
"description": "Add Page numbers throughout a document in a set location"
},
"redact": {
"image": "/og_images/redact.png",
"title": "Redact - Stirling PDF",
"description": "Permanently remove sensitive information from PDF documents"
},
"flatten": {
"image": "/og_images/flatten.png",
"title": "Flatten - Stirling PDF",
"description": "Remove all interactive elements and forms from a PDF"
},
"removeCertSign": {
"image": "/og_images/remove-certificate-sign.png",
"title": "Remove Certificate Sign - Stirling PDF",
"description": "Remove digital signature from PDF documents"
},
"unlockPDFForms": {
"image": "/og_images/unlock-pdf-forms.png",
"title": "Unlock PDF Forms - Stirling PDF",
"description": "Remove read-only property of form fields in a PDF document."
},
"compress": {
"image": "/og_images/compress.png",
"title": "Compress - Stirling PDF",
"description": "Compress PDFs to reduce their file size."
},
"extractPages": {
"image": "/og_images/extract-pages.png",
"title": "Extract Pages - Stirling PDF",
"description": "Extract specific pages from a PDF document"
},
"reorganizePages": {
"image": "/og_images/reorganize-pages.png",
"title": "Reorganize Pages - Stirling PDF",
"description": "Rearrange, duplicate, or delete PDF pages with visual drag-and-drop control."
},
"extractImages": {
"image": "/og_images/extract-images.png",
"title": "Extract Images - Stirling PDF",
"description": "Extract images from PDF documents"
},
"addStamp": {
"image": "/og_images/add-stamp.png",
"title": "Add Stamp to PDF - Stirling PDF",
"description": "Add text or add image stamps at set locations"
},
"addAttachments": {
"image": "/og_images/add-attachments.png",
"title": "Add Attachments - Stirling PDF",
"description": "Add or remove embedded files (attachments) to/from a PDF"
},
"changeMetadata": {
"image": "/og_images/change-metadata.png",
"title": "Change Metadata - Stirling PDF",
"description": "Change/Remove/Add metadata from a PDF document"
},
"overlayPdfs": {
"image": "/og_images/overlay-pdfs.png",
"title": "Overlay Pdfs - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"getPdfInfo": {
"image": "/og_images/get-all-info-on-pdf.png",
"title": "Get ALL Info on PDF - Stirling PDF",
"description": "Grabs any and all information possible on PDFs"
},
"validateSignature": {
"image": "/og_images/validate-pdf-signature.png",
"title": "Validate PDF Signature - Stirling PDF",
"description": "Verify digital signatures and certificates in PDF documents"
},
"timestampPdf": {
"image": "/og_images/timestamp-pdf.png",
"title": "Timestamp PDF - Stirling PDF",
"description": "Add an RFC 3161 document timestamp to prove when your PDF existed"
},
"replaceColor": {
"image": "/og_images/replace-and-invert-color.png",
"title": "Replace & Invert Color - Stirling PDF",
"description": "Replace or invert colors in PDF documents"
},
"showJS": {
"image": "/og_images/show-javascript.png",
"title": "Show JavaScript - Stirling PDF",
"description": "Extract and display JavaScript code from PDF documents"
},
"bookletImposition": {
"image": "/og_images/booklet-imposition.png",
"title": "Booklet Imposition - Stirling PDF",
"description": "Create booklets with proper page ordering and multi-page layout for printing and binding"
},
"pdfTextEditor": {
"image": "/og_images/pdf-text-editor.png",
"title": "PDF Text Editor - Stirling PDF",
"description": "Review and edit text and images in PDFs with grouped text editing and PDF regeneration"
},
"formFill": {
"image": "/og_images/form-fill.png",
"title": "Fill Form - Stirling PDF",
"description": "Fill PDF form fields interactively with a visual editor"
},
"multiTool": {
"image": "/og_images/multi-tool.png",
"title": "Multi-Tool - Stirling PDF",
"description": "Use multiple tools on a single PDF document"
},
"read": {
"image": "/og_images/read.png",
"title": "Read - Stirling PDF",
"description": "View and annotate PDFs. Highlight text, draw, or insert comments for review and collaboration."
},
"automate": {
"image": "/og_images/automate.png",
"title": "Automate - Stirling PDF",
"description": "Build multi-step workflows by chaining together PDF actions. Ideal for recurring tasks."
},
"devApi": {
"image": "/og_images/dev-api.png",
"title": "API - Stirling PDF",
"description": "Link to API documentation"
},
"devFolderScanning": {
"image": "/og_images/dev-folder-scanning.png",
"title": "Automated Folder Scanning - Stirling PDF",
"description": "Link to automated folder scanning guide"
},
"devSsoGuide": {
"image": "/og_images/dev-sso-guide.png",
"title": "SSO Guide - Stirling PDF",
"description": "Link to SSO guide"
},
"devAirgapped": {
"image": "/og_images/dev-airgapped.png",
"title": "Air-gapped Setup - Stirling PDF",
"description": "Link to air-gapped setup guide"
},
"/login": {
"image": "/og_images/home.png",
"title": "Sign In - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/signup": {
"image": "/og_images/home.png",
"title": "Sign Up - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/mobile-scanner": {
"image": "/og_images/home.png",
"title": "Mobile Scanner - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/files": {
"image": "/og_images/home.png",
"title": "Files - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings": {
"image": "/og_images/home.png",
"title": "Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/preferences": {
"image": "/og_images/home.png",
"title": "Preferences Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/notifications": {
"image": "/og_images/home.png",
"title": "Notifications Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/connections": {
"image": "/og_images/home.png",
"title": "Connections Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/account": {
"image": "/og_images/home.png",
"title": "Account Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/general": {
"image": "/og_images/home.png",
"title": "General Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/people": {
"image": "/og_images/home.png",
"title": "People Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/teams": {
"image": "/og_images/home.png",
"title": "Teams Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/security": {
"image": "/og_images/home.png",
"title": "Security Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/identity": {
"image": "/og_images/home.png",
"title": "Identity Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/plan": {
"image": "/og_images/home.png",
"title": "Plan Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/payments": {
"image": "/og_images/home.png",
"title": "Payments Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/requests": {
"image": "/og_images/home.png",
"title": "Requests Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/developer": {
"image": "/og_images/home.png",
"title": "Developer Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/api-keys": {
"image": "/og_images/home.png",
"title": "Api Keys Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/hotkeys": {
"image": "/og_images/home.png",
"title": "Hotkeys Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminGeneral": {
"image": "/og_images/home.png",
"title": "Admin General Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminSecurity": {
"image": "/og_images/home.png",
"title": "Admin Security Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminConnections": {
"image": "/og_images/home.png",
"title": "Admin Connections Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminPrivacy": {
"image": "/og_images/home.png",
"title": "Admin Privacy Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminDatabase": {
"image": "/og_images/home.png",
"title": "Admin Database Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminAdvanced": {
"image": "/og_images/home.png",
"title": "Admin Advanced Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminLegal": {
"image": "/og_images/home.png",
"title": "Admin Legal Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminPremium": {
"image": "/og_images/home.png",
"title": "Admin Premium Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminFeatures": {
"image": "/og_images/home.png",
"title": "Admin Features Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminPlan": {
"image": "/og_images/home.png",
"title": "Admin Plan Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminAudit": {
"image": "/og_images/home.png",
"title": "Admin Audit Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminUsage": {
"image": "/og_images/home.png",
"title": "Admin Usage Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminEndpoints": {
"image": "/og_images/home.png",
"title": "Admin Endpoints Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminStorageSharing": {
"image": "/og_images/home.png",
"title": "Admin Storage Sharing Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/adminMcp": {
"image": "/og_images/home.png",
"title": "Admin Mcp Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/help": {
"image": "/og_images/home.png",
"title": "Help Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/legal": {
"image": "/og_images/home.png",
"title": "Legal Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/backendThirdPartyLicenses": {
"image": "/og_images/home.png",
"title": "Backend Third Party Licenses Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/frontendThirdPartyLicenses": {
"image": "/og_images/home.png",
"title": "Frontend Third Party Licenses Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/payg": {
"image": "/og_images/home.png",
"title": "Payg Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/settings/account-link": {
"image": "/og_images/home.png",
"title": "Account Link Settings - Stirling PDF",
"description": "The Free Adobe Acrobat alternative (10M+ Downloads)"
},
"/processor": {
"image": "/og_images/saas/app-processor.png",
"title": "Stirling Processor - Govern every PDF your organization touches",
"ogTitle": "Govern every PDF your organization touches",
"description": "Redaction, retention, and encryption policies enforced everywhere PDFs enter your org. Distribute the free Editor anywhere. 1¢ per PDF."
},
"/editor": {
"image": "/og_images/saas/app-editor.png",
"title": "Stirling - The world's most secure PDF editor",
"ogTitle": "The world's most secure PDF editor",
"description": "Edit, sign, redact, and convert PDFs in your browser. Free forever, open source, and self-hostable."
}
},
"byPath": {
"/cert-sign": "certSign",
"/sign": "sign",
"/shared-sign": "sharedSign",
"/add-text": "addText",
"/add-password": "addPassword",
"/remove-password": "removePassword",
"/remove-pages": "removePages",
"/remove-blanks": "removeBlanks",
"/remove-annotations": "removeAnnotations",
"/remove-image": "removeImage",
"/change-permissions": "changePermissions",
"/watermark": "watermark",
"/sanitize": "sanitize",
"/split": "split",
"/merge": "merge",
"/convert": "convert",
"/ocr": "ocr",
"/add-image": "addImage",
"/rotate": "rotate",
"/annotate": "annotate",
"/scanner-image-split": "scannerImageSplit",
"/edit-table-of-contents": "editTableOfContents",
"/scanner-effect": "scannerEffect",
"/auto-rename": "autoRename",
"/page-layout": "pageLayout",
"/scale-pages": "scalePages",
"/adjust-contrast": "adjustContrast",
"/crop": "crop",
"/pdf-to-single-page": "pdfToSinglePage",
"/repair": "repair",
"/compare": "compare",
"/add-page-numbers": "addPageNumbers",
"/redact": "redact",
"/flatten": "flatten",
"/remove-cert-sign": "removeCertSign",
"/unlock-p-d-f-forms": "unlockPDFForms",
"/compress": "compress",
"/extract-pages": "extractPages",
"/reorganize-pages": "reorganizePages",
"/extract-images": "extractImages",
"/add-stamp": "addStamp",
"/add-attachments": "addAttachments",
"/change-metadata": "changeMetadata",
"/overlay-pdfs": "overlayPdfs",
"/get-pdf-info": "getPdfInfo",
"/validate-signature": "validateSignature",
"/timestamp-pdf": "timestampPdf",
"/replace-color": "replaceColor",
"/show-j-s": "showJS",
"/booklet-imposition": "bookletImposition",
"/pdf-text-editor": "pdfTextEditor",
"/form-fill": "formFill",
"/multi-tool": "multiTool",
"/read": "read",
"/automate": "automate",
"/dev-api": "devApi",
"/dev-folder-scanning": "devFolderScanning",
"/dev-sso-guide": "devSsoGuide",
"/dev-airgapped": "devAirgapped",
"/split-pdfs": "split",
"/merge-pdfs": "merge",
"/compress-pdf": "compress",
"/rotate-pdf": "rotate",
"/convert-pdf": "convert",
"/file-to-pdf": "convert",
"/eml-to-pdf": "convert",
"/html-to-pdf": "convert",
"/markdown-to-pdf": "convert",
"/pdf-to-csv": "convert",
"/pdf-to-xlsx": "convert",
"/pdf-to-img": "convert",
"/pdf-to-markdown": "convert",
"/pdf-to-pdfa": "convert",
"/pdf-to-word": "convert",
"/pdf-to-xml": "convert",
"/cbr-to-pdf": "convert",
"/pdf-to-cbr": "convert",
"/cbz-to-pdf": "convert",
"/pdf-to-cbz": "convert",
"/manage-signatures": "certSign",
"/remove-certificate-sign": "removeCertSign",
"/unlock-pdf-forms": "unlockPDFForms",
"/sanitize-pdf": "sanitize",
"/ocr-pdf": "ocr",
"/add-watermark": "watermark",
"/single-large-page": "pdfToSinglePage",
"/auto-split-pdf": "split",
"/auto-size-split-pdf": "split",
"/annotations": "annotate",
"/fake-scan": "scannerEffect",
"/replace-color-pdf": "replaceColor",
"/show-js": "showJS",
"/pdf-organizer": "reorganizePages",
"/multi-page-layout": "pageLayout",
"/extract-page": "extractPages",
"/img-to-pdf": "convert",
"/pdf-to-presentation": "convert",
"/pdf-to-text": "convert",
"/pdf-to-html": "convert",
"/auto-redact": "redact",
"/stamp": "addStamp",
"/view-pdf": "read",
"/get-info-on-pdf": "getPdfInfo",
"/remove-image-pdf": "removeImage",
"/replace-and-invert-color-pdf": "replaceColor",
"/pipeline": "automate",
"/extract-image-scans": "scannerImageSplit",
"/show-javascript": "showJS",
"/split-by-size-or-count": "split",
"/overlay-pdf": "overlayPdfs",
"/split-pdf-by-sections": "split",
"/split-pdf-by-chapters": "split",
"/login": "/login",
"/signup": "/signup",
"/mobile-scanner": "/mobile-scanner",
"/files": "/files",
"/settings": "/settings",
"/settings/preferences": "/settings/preferences",
"/settings/notifications": "/settings/notifications",
"/settings/connections": "/settings/connections",
"/settings/account": "/settings/account",
"/settings/general": "/settings/general",
"/settings/people": "/settings/people",
"/settings/teams": "/settings/teams",
"/settings/security": "/settings/security",
"/settings/identity": "/settings/identity",
"/settings/plan": "/settings/plan",
"/settings/payments": "/settings/payments",
"/settings/requests": "/settings/requests",
"/settings/developer": "/settings/developer",
"/settings/api-keys": "/settings/api-keys",
"/settings/hotkeys": "/settings/hotkeys",
"/settings/adminGeneral": "/settings/adminGeneral",
"/settings/adminSecurity": "/settings/adminSecurity",
"/settings/adminConnections": "/settings/adminConnections",
"/settings/adminPrivacy": "/settings/adminPrivacy",
"/settings/adminDatabase": "/settings/adminDatabase",
"/settings/adminAdvanced": "/settings/adminAdvanced",
"/settings/adminLegal": "/settings/adminLegal",
"/settings/adminPremium": "/settings/adminPremium",
"/settings/adminFeatures": "/settings/adminFeatures",
"/settings/adminPlan": "/settings/adminPlan",
"/settings/adminAudit": "/settings/adminAudit",
"/settings/adminUsage": "/settings/adminUsage",
"/settings/adminEndpoints": "/settings/adminEndpoints",
"/settings/adminStorageSharing": "/settings/adminStorageSharing",
"/settings/adminMcp": "/settings/adminMcp",
"/settings/help": "/settings/help",
"/settings/legal": "/settings/legal",
"/settings/backendThirdPartyLicenses": "/settings/backendThirdPartyLicenses",
"/settings/frontendThirdPartyLicenses": "/settings/frontendThirdPartyLicenses",
"/settings/payg": "/settings/payg",
"/settings/account-link": "/settings/account-link",
"/processor": "/processor",
"/editor": "/editor"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

@@ -4,7 +4,8 @@
//
// Outputs:
// src/core/data/ogImageMap.json - { toolId: imageBasename } (imported by the client)
// public/og-metadata.json - { default, byTool, byPath } (read by the backend at startup)
// public/og-metadata.json - { default, byTool, byPath } (prerender input, all flavors)
// public/og-metadata.saas.json - same shape, SaaS marketing copy/art (prerender input, --mode saas)
//
// Run: `node scripts/generate-og-metadata.mjs` (writes files)
// `node scripts/generate-og-metadata.mjs --check` (CI drift guard: fails if stale)
@@ -26,6 +27,35 @@ const SITE_TITLE = "Stirling PDF";
const SITE_DESC = "The Free Adobe Acrobat alternative (10M+ Downloads)";
const DEFAULT_IMAGE_BASENAME = "home";
// SaaS (stirling.com) link-preview cards. Only the SaaS build (`--mode saas`)
// uses og-metadata.saas.json; every other flavour keeps the tool-registry copy
// above. `ogTitle` is the punchy social headline; `title` is the SEO <title>.
// `home` overrides the site default (served at `/app`); the rest are extra
// marketing landing routes prerendered so their links unfurl with bespoke art.
const SAAS_DEFAULT = {
image: "/og_images/saas/app.png",
title: "Stirling - Edit any PDF. Govern every PDF.",
ogTitle: "Edit any PDF. Govern every PDF.",
description:
"The free, open-source PDF Editor, plus a Processor that governs every PDF your organization touches. 1¢ per PDF.",
};
const SAAS_ROUTE_OVERRIDES = {
"/processor": {
image: "/og_images/saas/app-processor.png",
title: "Stirling Processor - Govern every PDF your organization touches",
ogTitle: "Govern every PDF your organization touches",
description:
"Redaction, retention, and encryption policies enforced everywhere PDFs enter your org. Distribute the free Editor anywhere. 1¢ per PDF.",
},
"/editor": {
image: "/og_images/saas/app-editor.png",
title: "Stirling - The world's most secure PDF editor",
ogTitle: "The world's most secure PDF editor",
description:
"Edit, sign, redact, and convert PDFs in your browser. Free forever, open source, and self-hostable.",
},
};
// Tools whose art exists under a legacy v1 filename that does not match the
// tool id or any current URL slug. Verified against public/og_images contents.
const LEGACY_IMAGE_OVERRIDES = {
@@ -178,10 +208,33 @@ const manifest = {
byPath,
};
// SaaS manifest: same tool pages as above, but the home default and two extra
// marketing routes carry the stirling.com cards. Keeps all per-tool OG intact.
const saasManifest = {
default: SAAS_DEFAULT,
byTool: { ...byTool },
byPath: { ...byPath },
};
for (const [routePath, entry] of Object.entries(SAAS_ROUTE_OVERRIDES)) {
saasManifest.byTool[routePath] = entry;
saasManifest.byPath[routePath] = routePath;
}
// SaaS card art lives in the saas/ subdir (outside the root images scan), so
// check the files on disk directly.
const missingSaasImages = [SAAS_DEFAULT, ...Object.values(SAAS_ROUTE_OVERRIDES)]
.map((e) => e.image)
.filter((img) => !fs.existsSync(path.join(ROOT, "public" + img)));
if (missingSaasImages.length)
console.warn(
`\nWARNING: SaaS OG cards reference missing images: ${missingSaasImages.join(", ")}`,
);
const mapJson = JSON.stringify(ogImageMap, null, 2) + "\n";
const manifestJson = JSON.stringify(manifest, null, 2) + "\n";
const saasManifestJson = JSON.stringify(saasManifest, null, 2) + "\n";
const mapPath = "src/core/data/ogImageMap.json";
const manifestPath = "public/og-metadata.json";
const saasManifestPath = "public/og-metadata.saas.json";
const check = process.argv.includes("--check");
if (check) {
@@ -193,6 +246,11 @@ if (check) {
read(manifestPath) !== manifestJson
)
stale.push(manifestPath);
if (
!fs.existsSync(path.join(ROOT, saasManifestPath)) ||
read(saasManifestPath) !== saasManifestJson
)
stale.push(saasManifestPath);
if (stale.length) {
console.error(
"OG metadata is stale. Run `node scripts/generate-og-metadata.mjs`:\n " +
@@ -204,9 +262,13 @@ if (check) {
} else {
fs.writeFileSync(path.join(ROOT, mapPath), mapJson);
fs.writeFileSync(path.join(ROOT, manifestPath), manifestJson);
fs.writeFileSync(path.join(ROOT, saasManifestPath), saasManifestJson);
console.log(
`Wrote ${mapPath} (${Object.keys(ogImageMap).length} tools with art)`,
);
console.log(
`Wrote ${saasManifestPath} (${Object.keys(saasManifest.byPath).length} paths, SaaS)`,
);
console.log(`Wrote ${manifestPath} (${Object.keys(byPath).length} paths)`);
}
@@ -4,6 +4,8 @@ export interface OgEntry {
image: string;
title: string;
description: string;
/** Punchier social-card title; falls back to `title` for the <title> tag. */
ogTitle?: string;
}
export interface OgInjectOptions {
+4 -3
View File
@@ -15,12 +15,13 @@ export const escapeHtml = (value) =>
const absolute = (urlPath, ogBase) => (ogBase ? ogBase + urlPath : urlPath);
/**
* Build the OG/Twitter <meta> block for one route.
* @param {{image:string,title:string,description:string}} entry
* Build the OG/Twitter <meta> block for one route. `ogTitle` lets the social
* card show a punchier headline than the (SEO) <title>; falls back to `title`.
* @param {{image:string,title:string,description:string,ogTitle?:string}} entry
* @param {{ogBase?:string, pageUrlPath?:string|null}} opts
*/
export function buildOgTags(entry, { ogBase = "", pageUrlPath = null } = {}) {
const title = escapeHtml(entry.title);
const title = escapeHtml(entry.ogTitle ?? entry.title);
const description = escapeHtml(entry.description);
const imageUrl = absolute(entry.image, ogBase);
const image = escapeHtml(imageUrl);
+1 -1
View File
@@ -2,7 +2,7 @@
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
"productName": "Stirling PDF",
"mainBinaryName": "Stirling-PDF",
"version": "2.14.1",
"version": "2.14.2",
"identifier": "stirling.pdf.dev",
"build": {
"frontendDist": "../dist",
@@ -102,6 +102,28 @@ describe("injectOg (build-time prerender)", () => {
);
expect(tags).toContain("A &quot;B&quot; &amp; &lt;C&gt;");
});
it("uses ogTitle for the social card but title for the <title> tag", () => {
const out = injectOg(
TEMPLATE,
{
image: "/og_images/saas/app.png",
title: "Stirling - Edit any PDF. Govern every PDF.",
ogTitle: "Edit any PDF. Govern every PDF.",
description: "d",
},
{},
);
expect(out).toContain(
"<title>Stirling - Edit any PDF. Govern every PDF.</title>",
);
expect(out).toContain(
'<meta property="og:title" content="Edit any PDF. Govern every PDF." />',
);
expect(out).toContain(
'<meta name="twitter:title" content="Edit any PDF. Govern every PDF." />',
);
});
});
describe("prerenderOg (flat + nested route files)", () => {
@@ -38,7 +38,7 @@ const FREE_LICENSE_INFO: LicenseInfo = {
const BASE_NO_LOGIN_CONFIG: AppConfig = {
enableAnalytics: true,
appVersion: "2.14.1",
appVersion: "2.14.2",
serverCertificateEnabled: false,
enableAlphaFunctionality: false,
serverPort: 8080,
@@ -48,7 +48,7 @@ const FREE_LICENSE_INFO: LicenseInfo = {
const BASE_NO_LOGIN_CONFIG: AppConfig = {
enableAnalytics: true,
appVersion: "2.14.1",
appVersion: "2.14.2",
serverCertificateEnabled: false,
enableAlphaFunctionality: false,
enableDesktopInstallSlide: true,
+1 -1
View File
@@ -83,7 +83,7 @@ export default function Login() {
"app.description",
"The Free Adobe Acrobat alternative (10M+ Downloads)",
),
ogImage: `${baseUrl}/og_images/home.png`,
ogImage: `${baseUrl}/og_images/saas/app.png`,
ogUrl: `${window.location.origin}${window.location.pathname}`,
});
+1 -1
View File
@@ -108,7 +108,7 @@ export default function Signup() {
"app.description",
"The Free Adobe Acrobat alternative (10M+ Downloads)",
),
ogImage: `${baseUrl}/og_images/home.png`,
ogImage: `${baseUrl}/og_images/saas/app.png`,
ogUrl: `${window.location.origin}${window.location.pathname}`,
});
+9 -7
View File
@@ -88,7 +88,12 @@ function compressStaticCopyPlugin(): PluginOption {
// Pages). Otherwise URLs stay root-relative, which still resolves against whatever
// origin serves the page (correct for self-hosted Docker). Logic lives in
// scripts/og-prerender.mjs so it can be unit-tested without a full build.
function prerenderOgPlugin(): PluginOption {
function prerenderOgPlugin(isSaas: boolean): PluginOption {
// SaaS (stirling.com) prerenders the marketing cards from a dedicated
// manifest; every other flavour uses the tool-registry manifest.
const manifestFile = isSaas
? "public/og-metadata.saas.json"
: "public/og-metadata.json";
return {
name: "prerender-og",
apply: "build" as const,
@@ -105,14 +110,11 @@ function prerenderOgPlugin(): PluginOption {
let manifest;
try {
manifest = JSON.parse(
await fs.readFile(
path.resolve(__dirname, "public/og-metadata.json"),
"utf8",
),
await fs.readFile(path.resolve(__dirname, manifestFile), "utf8"),
);
} catch {
console.warn(
"[prerender-og] public/og-metadata.json missing; skipping OG prerender. " +
`[prerender-og] ${manifestFile} missing; skipping OG prerender. ` +
"Run `node scripts/generate-og-metadata.mjs`.",
);
return;
@@ -330,7 +332,7 @@ export default defineConfig(async ({ mode, command }) => {
],
}),
compressStaticCopyPlugin(),
prerenderOgPlugin(),
prerenderOgPlugin(effectiveMode === "saas"),
],
server: {
host: true,