diff --git a/assets/.well-known/traffic-advice b/assets/.well-known/traffic-advice
index 8cd8df9..54e23d9 100644
--- a/assets/.well-known/traffic-advice
+++ b/assets/.well-known/traffic-advice
@@ -1,6 +1,6 @@
{
"user_agent": "prefetch-proxy",
"google_prefetch_proxy_eap": {
- "fraction": 1.0
+ "fraction": 0.7
}
}
\ No newline at end of file
diff --git a/src/layout/helpers/htmxConfig.tsx b/src/layout/helpers/htmxConfig.tsx
new file mode 100644
index 0000000..a566ac9
--- /dev/null
+++ b/src/layout/helpers/htmxConfig.tsx
@@ -0,0 +1,28 @@
+import { raw } from "hono/html";
+import type { LooseObj, NoncePropType } from "../../types";
+
+export function getHTMXConfigStr(nonce: string | undefined) {
+ const HTMXConfigObj: LooseObj = {
+ responseHandling: [
+ { code: "204", swap: false },
+ { code: "400", swap: false, error: true },
+ { code: "404", swap: true, error: true },
+ { code: "[234]..", swap: true, error: false },
+ { code: "500", swap: true, error: true },
+ { code: "[5]..", swap: false, error: true },
+ { code: "...", swap: true },
+ ],
+ };
+ if (nonce !== undefined) {
+ HTMXConfigObj.allowEval = false;
+ HTMXConfigObj.inlineScriptNonce =
+ HTMXConfigObj.inlineStyleNonce = nonce;
+ }
+
+ return ``;
+}
+
+export function HTMXConfig({ nonce }: NoncePropType) {
+ return raw(getHTMXConfigStr(nonce));
+}
+
diff --git a/src/layout/helpers/includesTags.tsx b/src/layout/helpers/includesTags.tsx
index 89794a5..83720d4 100644
--- a/src/layout/helpers/includesTags.tsx
+++ b/src/layout/helpers/includesTags.tsx
@@ -1,9 +1,4 @@
-import { raw } from "hono/html";
-import type { LooseObj, PreloadRules } from "../../types";
-
-interface NoncePropType {
- nonce?: string;
-}
+import type { NoncePropType, PreloadRules } from "../../types";
type DepTagsType = NoncePropType & {
scripts?: PreloadRules[]
@@ -54,27 +49,3 @@ export function PreloadDependencyTags({ scripts }: DepTagsType) {
});
return <>{html}>;
}
-
-export function getHTMXConfigStr(nonce: string | undefined) {
- const HTMXConfigObj: LooseObj = {
- responseHandling: [
- { code: "204", swap: false },
- { code: "400", swap: false, error: true },
- { code: "404", swap: true, error: true },
- { code: "[234]..", swap: true, error: false },
- { code: "500", swap: true, error: true },
- { code: "[5]..", swap: false, error: true },
- { code: "...", swap: true },
- ],
- };
- if (nonce !== undefined) {
- HTMXConfigObj.allowEval = false;
- HTMXConfigObj.inlineScriptNonce = HTMXConfigObj.inlineStyleNonce = nonce;
- }
-
- return ``;
-}
-
-export function HTMXNonceTag({ nonce }: NoncePropType) {
- return raw(getHTMXConfigStr(nonce));
-}
diff --git a/src/layout/helpers/speculation.tsx b/src/layout/helpers/speculation.tsx
new file mode 100644
index 0000000..aabcfb3
--- /dev/null
+++ b/src/layout/helpers/speculation.tsx
@@ -0,0 +1,28 @@
+// this file handles injecting speculation rules.
+import { raw } from "hono/html";
+import { ALLOW_SPECULATION_RULES } from "../../limits";
+
+export function SpeculationRulesTag() {
+ if (!ALLOW_SPECULATION_RULES)
+ return (<>>);
+
+ const speculationDefines = {
+ prerender: [
+ {
+ where: {
+ and: [
+ { href_matches: "/*" },
+ // sensitive pages
+ { not: { href_matches: "/(dashboard|reset)" } },
+ // redirects
+ { not: { href_matches: "/(reset|tip|contact|bsky|source)" } },
+ ]
+ },
+ eagerness: "moderate",
+ },
+ ],
+ // fetch everything that's not outside the main site
+ prefetch: [{ where: { not: { href_matches: "/*" } }, eagerness: "moderate" }],
+ };
+ return ;
+}
diff --git a/src/layout/main.tsx b/src/layout/main.tsx
index 0d4927c..4fc5d22 100644
--- a/src/layout/main.tsx
+++ b/src/layout/main.tsx
@@ -3,9 +3,11 @@ import type { Child } from "hono/jsx";
import { APP_NAME } from "../appInfo";
import { ScriptInclusionLevel } from "../enums";
import type { BaseElementProps, PreloadRules } from "../types";
+import { HTMXConfig } from "./helpers/htmxConfig";
import { getScriptsForInteractivity } from "./helpers/includesList";
-import { HTMXNonceTag, IncludeDependencyTags, PreloadDependencyTags } from "./helpers/includesTags";
+import { IncludeDependencyTags, PreloadDependencyTags } from "./helpers/includesTags";
import { MetaTags, PersonaTags } from "./helpers/metaTags";
+import { SpeculationRulesTag } from "./helpers/speculation";
type BaseLayoutProps = BaseElementProps & {
children: Child;
@@ -41,7 +43,8 @@ export const BaseLayout = (props: BaseLayoutProps) => {
-
+
+
{props.interactivity === ScriptInclusionLevel.NonInteractive ? : null}
diff --git a/src/limits.ts b/src/limits.ts
index f1aacd8..fd137b3 100644
--- a/src/limits.ts
+++ b/src/limits.ts
@@ -111,6 +111,9 @@ export const USE_DEPRECATED_SIZE_PARSE: boolean = true;
// if we should try to use SSG rendering for pages vs dynamic rendering
export const USE_STATIC_HTML: boolean = true;
+// if we should enable chrome speculation rules to speed up the site
+export const ALLOW_SPECULATION_RULES: boolean = false;
+
/*********************************************************/
/**** APPLICATION INTERVAL SETTINGS ****/
/*********************************************************/
diff --git a/src/middleware/ssg.ts b/src/middleware/ssg.ts
index 4afe6c5..e4f28bf 100644
--- a/src/middleware/ssg.ts
+++ b/src/middleware/ssg.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/dot-notation */
+import { readFile } from "fs/promises";
import { createMiddleware } from "hono/factory";
import { isSSGContext } from "hono/ssg";
-import { readFile } from "fs/promises";
-import { getHTMXConfigStr } from "../layout/helpers/includesTags";
+import { getHTMXConfigStr } from "../layout/helpers/htmxConfig";
import { USE_GRANULAR_CSP_SETTINGS, USE_STATIC_HTML } from "../limits";
import type { BaseContext, NextMiddleware } from "../types";
import { has } from "../utils/helpers";
@@ -27,7 +27,8 @@ class NonceInject {
if (scriptType !== null &&
scriptType !== "text/javascript" &&
scriptType !== "application/javascript" &&
- scriptType !== "module") {
+ scriptType !== "module")
+ {
return;
}
}
diff --git a/src/types.ts b/src/types.ts
index eaae0fc..6d3669b 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -264,6 +264,10 @@ export type ContextVariables = SecureHeadersVariables & {
ssg: boolean;
};
+export interface NoncePropType {
+ nonce?: string;
+}
+
export interface HonoBase {
Bindings: Bindings;
Variables: ContextVariables;