From 7c4d51a642d9edbf60ed7f1834dd44826131df7d Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:14:04 +0800 Subject: [PATCH 01/22] release(mobile): release v0.5.6 --- apps/mobile/changelog/0.5.6.md | 14 ++++++++++++++ apps/mobile/changelog/next.md | 13 +++++-------- apps/mobile/ios/Folo/Info.plist | 4 ++-- apps/mobile/package.json | 2 +- apps/mobile/release.json | 8 ++++---- 5 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 apps/mobile/changelog/0.5.6.md diff --git a/apps/mobile/changelog/0.5.6.md b/apps/mobile/changelog/0.5.6.md new file mode 100644 index 000000000..4fd0850d4 --- /dev/null +++ b/apps/mobile/changelog/0.5.6.md @@ -0,0 +1,14 @@ +# What's New in v0.5.6 + +## Improvements + +- Upgraded the app to Expo SDK 57, React Native 0.86, and updated native integrations + +## No longer broken + +- Fixed social sign-in callbacks and legacy session migration using the Folo app scheme +- Fixed signed-out launches not opening the login screen +- Fixed two-factor authentication cookies being dropped during session updates +- Fixed push notification registration after sign-in, including retries and token refreshes +- Fixed the timeline view selector overflowing on narrow screens +- Restored the header background after scrolling diff --git a/apps/mobile/changelog/next.md b/apps/mobile/changelog/next.md index 8c3affe62..000f858e3 100644 --- a/apps/mobile/changelog/next.md +++ b/apps/mobile/changelog/next.md @@ -1,14 +1,11 @@ # What's New in vNEXT_VERSION +## Shiny new things + ## Improvements -- Upgraded the app to Expo SDK 57, React Native 0.86, and updated native integrations - ## No longer broken -- Fixed social sign-in callbacks and legacy session migration using the Folo app scheme -- Fixed signed-out launches not opening the login screen -- Fixed two-factor authentication cookies being dropped during session updates -- Fixed push notification registration after sign-in, including retries and token refreshes -- Fixed the timeline view selector overflowing on narrow screens -- Restored the header background after scrolling +## Thanks + +Special thanks to volunteer contributors @ for their valuable contributions diff --git a/apps/mobile/ios/Folo/Info.plist b/apps/mobile/ios/Folo/Info.plist index 6680d0043..649773993 100644 --- a/apps/mobile/ios/Folo/Info.plist +++ b/apps/mobile/ios/Folo/Info.plist @@ -33,7 +33,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 0.5.5 + 0.5.6 CFBundleSignature ???? CFBundleURLTypes @@ -54,7 +54,7 @@ CFBundleVersion - 8 + 9 ITSAppUsesNonExemptEncryption LSApplicationCategoryType diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 2b364248c..be6faa61c 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@follow/mobile", - "version": "0.5.5", + "version": "0.5.6", "private": true, "main": "src/main.tsx", "scripts": { diff --git a/apps/mobile/release.json b/apps/mobile/release.json index e8eb0ec2e..6184b941a 100644 --- a/apps/mobile/release.json +++ b/apps/mobile/release.json @@ -1,6 +1,6 @@ { - "version": "0.5.5", - "mode": "ota", - "runtimeVersion": "0.5.0", - "channel": "production" + "version": "0.5.6", + "mode": "store", + "runtimeVersion": null, + "channel": null } From 06135760ba116b979b722c86ca0e62d8d7e67f46 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:14:43 +0800 Subject: [PATCH 02/22] docs(mobile): restore desktop release inputs --- apps/desktop/changelog/next.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/desktop/changelog/next.md b/apps/desktop/changelog/next.md index fefb84147..8f5eac449 100644 --- a/apps/desktop/changelog/next.md +++ b/apps/desktop/changelog/next.md @@ -1,13 +1,11 @@ # What's new in vNEXT_VERSION +## Shiny new things + ## Improvements -- Upgraded the desktop runtime to Electron 43 and refreshed core dependencies - ## No longer broken -- Fixed YouTube embeds in entry content and readability view failing to play due to a missing referrer - ## Thanks -Special thanks to volunteer contributor @TonyRL for the YouTube embed fix +Special thanks to volunteer contributors @ for their valuable contributions From d726ccccb2df4cb15997d614886b333b58ed976d Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 11:32:42 +0800 Subject: [PATCH 03/22] fix(desktop): use js-yaml ESM exports --- apps/desktop/scripts/merge-yml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/merge-yml.ts b/apps/desktop/scripts/merge-yml.ts index f28562c8c..12d124382 100644 --- a/apps/desktop/scripts/merge-yml.ts +++ b/apps/desktop/scripts/merge-yml.ts @@ -1,6 +1,6 @@ import fs from "node:fs" -import yaml from "js-yaml" +import * as yaml from "js-yaml" import path from "pathe" const outDir = "./out/make" From d90cdfe2b376e3481ce17c9d143e88e1af15a646 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 12:12:50 +0800 Subject: [PATCH 04/22] fix(desktop): package jsdom runtime dependencies --- apps/desktop/forge.config.cts | 43 +++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/apps/desktop/forge.config.cts b/apps/desktop/forge.config.cts index 8237ffa68..ea509deee 100644 --- a/apps/desktop/forge.config.cts +++ b/apps/desktop/forge.config.cts @@ -36,7 +36,43 @@ const ymlMapsMap = { win32: "latest.yml", } -const keepModules = new Set(["font-list", "vscode-languagedetection"]) +// Keep external runtime modules and their production dependency trees in app.asar. +// Scoped packages are copied as a whole because cleanSources operates on top-level entries. +const keepModules = new Set([ + "@asamuzakjp", + "@bramus", + "@csstools", + "@exodus", + "bidi-js", + "css-tree", + "data-urls", + "decimal.js", + "entities", + "font-list", + "html-encoding-sniffer", + "is-potential-custom-element-name", + "jsdom", + "lru-cache", + "mdn-data", + "parse5", + "punycode", + "require-from-string", + "saxes", + "source-map-js", + "symbol-tree", + "tldts", + "tldts-core", + "tough-cookie", + "tr46", + "undici", + "vscode-languagedetection", + "w3c-xmlserializer", + "webidl-conversions", + "whatwg-mimetype", + "whatwg-url", + "xml-name-validator", + "xmlchars", +]) const keepLanguages = new Set(["en", "en_GB", "en-US", "en_US"]) // remove folders & files not to be included in the app @@ -93,7 +129,10 @@ async function cleanSources(buildPath, _electronVersion, platform, _arch, callba const noopAfterCopy = (_buildPath, _electronVersion, _platform, _arch, callback) => callback() -const ignorePattern = new RegExp(`^/node_modules/(?!${[...keepModules].join("|")})`) +const keepModulePattern = [...keepModules] + .map((item) => item.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")) + .join("|") +const ignorePattern = new RegExp(`^/node_modules/(?!(?:${keepModulePattern})(?:/|$))`) const config: ForgeConfig = { packagerConfig: { From 192a7139ce0adbff37f964bdbd52f737a16ede81 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Mon, 13 Jul 2026 13:03:25 +0800 Subject: [PATCH 05/22] fix(desktop): use js-yaml ESM exports for Windows metadata --- apps/desktop/scripts/update-windows-yml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/update-windows-yml.ts b/apps/desktop/scripts/update-windows-yml.ts index 45afd2775..5c04c075c 100644 --- a/apps/desktop/scripts/update-windows-yml.ts +++ b/apps/desktop/scripts/update-windows-yml.ts @@ -2,7 +2,7 @@ import crypto from "node:crypto" import fs from "node:fs" import { fileURLToPath, resolve } from "node:url" -import yaml from "js-yaml" +import * as yaml from "js-yaml" const __dirname = fileURLToPath(new URL(".", import.meta.url)) const basePath = resolve(__dirname, "../out/make/squirrel.windows/x64/") From 773f1bfe218ac349b9fb9b5cbd982c320f6b414f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 09:00:49 +0800 Subject: [PATCH 06/22] build(deps): bump actions/setup-node from 6 to 7 (#5046) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-desktop.yml | 4 ++-- .github/workflows/build-ios-development.yml | 4 ++-- .github/workflows/build-ios.yml | 2 +- .github/workflows/build-web.yml | 2 +- .github/workflows/deploy-cloudflare-desktop.yml | 2 +- .github/workflows/deploy-cloudflare-landing.yml | 2 +- .github/workflows/deploy-cloudflare-ssr.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-ota.yml | 2 +- .github/workflows/tag.yml | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 9ab5b3225..fb381dd0b 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -57,7 +57,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index fe1417385..3816beb22 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -83,7 +83,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Use Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" @@ -407,7 +407,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Use Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-ios-development.yml b/.github/workflows/build-ios-development.yml index 46ca32ba3..5c16f9eca 100644 --- a/.github/workflows/build-ios-development.yml +++ b/.github/workflows/build-ios-development.yml @@ -97,7 +97,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" @@ -148,7 +148,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml index cd5defeeb..d790be1dc 100644 --- a/.github/workflows/build-ios.yml +++ b/.github/workflows/build-ios.yml @@ -117,7 +117,7 @@ jobs: uses: pnpm/action-setup@v6 - name: 🏗 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 9b3c504fe..368b2cfd6 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -34,7 +34,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-desktop.yml b/.github/workflows/deploy-cloudflare-desktop.yml index 877486508..c0a0fa672 100644 --- a/.github/workflows/deploy-cloudflare-desktop.yml +++ b/.github/workflows/deploy-cloudflare-desktop.yml @@ -35,7 +35,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-landing.yml b/.github/workflows/deploy-cloudflare-landing.yml index a9cd90314..187ccd4f4 100644 --- a/.github/workflows/deploy-cloudflare-landing.yml +++ b/.github/workflows/deploy-cloudflare-landing.yml @@ -39,7 +39,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/deploy-cloudflare-ssr.yml b/.github/workflows/deploy-cloudflare-ssr.yml index 1671fe558..32ae35df2 100644 --- a/.github/workflows/deploy-cloudflare-ssr.yml +++ b/.github/workflows/deploy-cloudflare-ssr.yml @@ -42,7 +42,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js LTS - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* cache: "pnpm" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ff1af2bad..4b7ba8eac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,7 +39,7 @@ jobs: - uses: pnpm/action-setup@v6 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} cache: "pnpm" diff --git a/.github/workflows/publish-ota.yml b/.github/workflows/publish-ota.yml index c09ad4733..100a5aed7 100644 --- a/.github/workflows/publish-ota.yml +++ b/.github/workflows/publish-ota.yml @@ -60,7 +60,7 @@ jobs: uses: pnpm/action-setup@v6 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 22 cache: "pnpm" diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index a9d6abf63..24f1c7c0a 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v7 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: lts/* From cf224d63f5dc336c5751d532a3cbf861531e67da Mon Sep 17 00:00:00 2001 From: DIYgod Date: Sat, 25 Jul 2026 12:38:49 +0800 Subject: [PATCH 07/22] fix(ssr): escape hydration data in inline scripts --- apps/ssr/package.json | 1 + apps/ssr/src/lib/hydration-script.test.ts | 109 ++++++++++++++++++++++ apps/ssr/src/lib/hydration-script.ts | 38 ++++++++ apps/ssr/src/router/global.ts | 9 +- apps/ssr/src/router/og/index.ts | 3 +- apps/ssr/tsconfig.json | 1 + apps/ssr/vitest.config.ts | 7 ++ apps/ssr/worker-entry.ts | 10 +- 8 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 apps/ssr/src/lib/hydration-script.test.ts create mode 100644 apps/ssr/src/lib/hydration-script.ts create mode 100644 apps/ssr/vitest.config.ts diff --git a/apps/ssr/package.json b/apps/ssr/package.json index 87ae4d16b..8628f10d9 100644 --- a/apps/ssr/package.json +++ b/apps/ssr/package.json @@ -10,6 +10,7 @@ "dev": "cross-env NODE_ENV=development tsx watch --include \"src/**/*.ts\" --exclude \"./*.ts\" --exclude \"./*.mjs\" index.ts", "meta": "tsx helper/meta-map.ts --watch", "start": "tsx index.ts", + "test": "vitest run --config vitest.config.ts", "typecheck": "tsc --noEmit" }, "dependencies": { diff --git a/apps/ssr/src/lib/hydration-script.test.ts b/apps/ssr/src/lib/hydration-script.test.ts new file mode 100644 index 000000000..a270043ef --- /dev/null +++ b/apps/ssr/src/lib/hydration-script.test.ts @@ -0,0 +1,109 @@ +import { runInNewContext } from "node:vm" + +import { minify } from "html-minifier-terser" +import { parseHTML } from "linkedom" +import { describe, expect, it } from "vitest" + +import { createHydrationScript, injectHydrationScript } from "./hydration-script" + +describe("hydration script", () => { + it("keeps attacker-controlled keys and data inside a single script element", () => { + const key = `profile