openvibers/openvibe.blog Commits
The Blog home opens with what OpenVibe.Blog is for (plan T11, D92; openvibe-shared v2.3.1 showcase): 'Write on OpenVibe', where to start (Start writing, or read the OpenVibe blog below), and the six things a blog really gets today (drafts and revisions, scheduling, feeds, Community comments, themes, VIP members-only posts); the official blog's posts follow unchanged. The kit's stylesheet is linked only on the home (cached; loaded styles-first on a boost swap). Home budgets raised as a decision (html 29 KB, css 17.5 KB). Suites green.
Changes
@@@ -253,7 +253,7 @@ Called elsewhere, as the service principal `blog`: `identity.subject.resolve` an`openvibe-sdk/db`; Valkey holds the per-actor limit counters (optional: without `VALKEY_URL` they count per process).- **Packages** (all pinned by release tarball): `openvibe-publishing` v1.0.0 (async PostgreSQL stores: revisions,schedule, taxonomy, citations, media, discussion, seo, authorship, index-hooks, ssr), `openvibe-contracts`-- v0.79.0, `openvibe-shared` v2.2.0 (Frame, app icon, footer, legal, release, metrics, ready, theme presets),++ v0.79.0, `openvibe-shared` v2.3.1 (Frame, app icon, footer, legal, release, metrics, ready, theme presets),`openvibe-sdk` v0.25.0 (sso, db, PostgreSQL events outbox, service tokens, per-actor limits, testing).- **OpenVibe.Network:**- SSO: the OAuth client `blog` is already seeded with redirect@@@ -11,7 +11,7 @@"packages": ["openvibe-publishing v1.0.0","openvibe-contracts v0.79.0",-- "openvibe-shared v2.2.0",++ "openvibe-shared v2.3.1","openvibe-sdk v0.25.0"],"capabilities": [@@@ -18,7 +18,7 @@"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0","openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1","pg": "^8.23.0"},"devDependencies": {@@@ -1210,9 +1210,9 @@}},"node_modules/openvibe-shared": {-- "version": "2.2.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",-- "integrity": "sha512-1q+iUuUxzPeylTYmithW4jR++Jccvn5GEOrB1B3D18Dgn6OXQhPpvhPQAa1D1k1p+dWIa1/SmggyJwSGFnTNtw==",++ "version": "2.3.1",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",++ "integrity": "sha512-K+MXnB4O+8xIFi+NQGC2SDTvDq3RkzfxQ3bTVx76Y/Rbuq7kC/L5kL3c/06xr9sPYcjyzF3Bhpv5yH2YNfR4Zw==","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0"@@@ -30,7 +30,7 @@"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0","openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1","pg": "^8.23.0"},"devDependencies": {@@@ -58,3 +58,11 @@ table.posts th, table.posts td { text-align: left; padding: 6px 8px; border-bott.ov-diff { white-space: pre-wrap; }@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }@media (max-width: 600px) { h1 { font-size: 1.7rem; } body { font-size: 16px; } }++++/* The home's showcase sections (openvibe-shared/showcase.css) sit inside the reading column, which has its own gutter. */++.page .sc-hero, .page .sc-sec { padding-left: 0; padding-right: 0; }++.page .sc-hero { padding-top: 24px; }++.page .sc-hero h1 { font-size: clamp(30px, 5vw, 42px); }++.page .sc-sec { margin-top: 36px; }++.page .sc-sec + #posts { display: block; margin-top: 40px; }++.page .sc-ic .ov-icon { --ovi-size: 28px !important; }@@@ -16,6 +16,7 @@* `public, max-age=60`; everything else — signed-in views, drafts, previews, unlisted,* members/VIP and private posts, refusals, 404/410 — is `private, no-store` + X-Robots-Tag.*/++const showcase = require('openvibe-shared/showcase');const express = require('express');const ovServe = require('openvibe-shared/serve');const frame = require('openvibe-shared/frame');@@@ -79,6 +80,26 @@ function createPublicRoutes(ctx) {// ── Blog front pages ────────────────────────────────────++ /** The product's own words above the official blog's posts: only features Blog has today. */++ function blogShowcase() {++ return showcase.hero({++ eyebrow: 'OpenVibe.Blog',++ title: 'Write on', accent: 'OpenVibe',++ lede: 'A blog of your own with drafts, scheduling, feeds and comments. Sign in once with your OpenVibe account; anyone can read without one.',++ actions: [{ label: 'Start writing', href: '/write', primary: true }, { label: 'Read the OpenVibe blog', href: '#posts' }],++ }) + showcase.features({++ title: 'What your blog gets',++ items: [++ { icon: 'ov:blog', title: 'Drafts and revisions', text: 'Every save is a revision you can go back to; publish when it is ready.' },++ { icon: 'ov:history', title: 'Scheduling', text: 'Pick the minute a post goes live.' },++ { icon: 'ov:news', title: 'Feeds', text: 'RSS, Atom and JSON Feed for every blog, series and category.' },++ { icon: 'ov:community', title: 'Comments', text: 'Threads on OpenVibe.Community, moderated by you.' },++ { icon: 'ov:theme', title: 'Your theme', text: 'Pick a theme preset and your blog wears it.' },++ { icon: 'ov:vip', title: 'Members-only posts', text: 'Your OpenVibe.VIP members read the whole post; everyone else sees a teaser.' },++ ],++ }) + '<div id="posts"></div>';++ }++async function blogFront(req, res, blog, { home = false } = {}) {const page = pageNumber(req);const restricted = await isMember(blog, req.viewer);@@@ -115,7 +136,9 @@ function createPublicRoutes(ctx) {jsonLd: [blog.kind === 'official'? { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined, publisher: { '@type': 'Organization', name: 'OpenVibe', url: 'https://openvibe.network' } }: { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined }],-- body: pages.blogIndex({++ // The network's blog home opens with what OpenVibe.Blog is for (openvibe-shared/showcase), then the posts.++ ...(home && pager.page === 1 ? { styles: [showcase.STYLESHEET] } : {}),++ body: (home && pager.page === 1 ? blogShowcase() : '') + pages.blogIndex({blog, blogUrl: `/@${blog.handle}`, items, pager, feeds,series: seriesShown, categories: await prune(await reading.categoriesTree(blog)),canWrite: await access.canWrite(store, req.viewer, blog, 'create'),@@@ -47,7 +47,7 @@ function themeStyle(vars) {/*** o: title, description, decision (required), canonical, type ('website'|'article'), image,* jsonLd [], feeds [{ type, href, title }], body (HTML), viewer, config, csrf,-- * theme { slug, vars }, published, modified, author, prev, next, bodyClass++ * theme { slug, vars }, published, modified, author, prev, next, bodyClass, styles [openvibe-shared stylesheet names]*/function renderPage(o) {if (!o.decision) throw new TypeError('renderPage needs the gate decision');@@@ -97,6 +97,7 @@ ${o.modified ? `<meta property="article:modified_time" content="${esc(o.modified${seo.feedLinks(o.feeds || [])}${appIcon.headTags({ site: 'blog' })}<link rel="stylesheet" href="${asset('css/blog.css')}">++${(o.styles || []).map((name) => `<link rel="stylesheet" href="${esc(ovServe.url(name))}">`).join('\n')}<script src="${ovServe.url('theme-loader.js')}" defer></script><script src="${ovServe.url('navbar.js')}" defer></script><script src="${ovServe.url('footer.js')}" defer></script>@@@ -11,15 +11,17 @@ const path = require('path');const { spawn } = require('child_process');const { measure, check, format } = require('openvibe-shared/perf-budget');++// 2026-09-29: the home opens with the showcase hero and features (six inline ring icons) and links the cached++// /shared/showcase.css: measured html 26.2 KB (6.8 br), css 15.9 KB (4.0 br). Raised as a decision.const BUDGETS = {-- htmlRawKB: 22, // measured 17.4 (fresh database)-- htmlBrotliKB: 5.5, // 4.5++ htmlRawKB: 29, // measured 17.4 (fresh database)++ htmlBrotliKB: 7.5, // 4.5jsFiles: 4, // 3jsRawKB: 230, // 197.7jsBrotliKB: 53, // 45.6cssFiles: 2, // 1-- cssRawKB: 6.5, // 5.0-- cssBrotliKB: 2, // 1.4++ cssRawKB: 17.5, // 5.0++ cssBrotliKB: 4.5, // 1.4externalFiles: 1, // 0};
@@ -253,7 +253,7 @@ Called elsewhere, as the service principal `blog`: `identity.subject.resolve` an
@@ -253,7 +253,7 @@ Called elsewhere, as the service principal `blog`: `identity.subject.resolve` an
`openvibe-sdk/db`; Valkey holds the per-actor limit counters (optional: without `VALKEY_URL` they count per process).
`openvibe-sdk/db`; Valkey holds the per-actor limit counters (optional: without `VALKEY_URL` they count per process).
- **Packages** (all pinned by release tarball): `openvibe-publishing` v1.0.0 (async PostgreSQL stores: revisions,
- **Packages** (all pinned by release tarball): `openvibe-publishing` v1.0.0 (async PostgreSQL stores: revisions,
schedule, taxonomy, citations, media, discussion, seo, authorship, index-hooks, ssr), `openvibe-contracts`
schedule, taxonomy, citations, media, discussion, seo, authorship, index-hooks, ssr), `openvibe-contracts`
- v0.79.0, `openvibe-shared` v2.2.0 (Frame, app icon, footer, legal, release, metrics, ready, theme presets),
+ v0.79.0, `openvibe-shared` v2.3.1 (Frame, app icon, footer, legal, release, metrics, ready, theme presets),
`openvibe-sdk` v0.25.0 (sso, db, PostgreSQL events outbox, service tokens, per-actor limits, testing).
`openvibe-sdk` v0.25.0 (sso, db, PostgreSQL events outbox, service tokens, per-actor limits, testing).
- **OpenVibe.Network:**
- **OpenVibe.Network:**
- SSO: the OAuth client `blog` is already seeded with redirect
- SSO: the OAuth client `blog` is already seeded with redirect
@@ -11,7 +11,7 @@
@@ -11,7 +11,7 @@
"packages": [
"packages": [
"openvibe-publishing v1.0.0",
"openvibe-publishing v1.0.0",
"openvibe-contracts v0.79.0",
"openvibe-contracts v0.79.0",
- "openvibe-shared v2.2.0",
+ "openvibe-shared v2.3.1",
"openvibe-sdk v0.25.0"
"openvibe-sdk v0.25.0"
],
],
"capabilities": [
"capabilities": [
@@ -18,7 +18,7 @@
@@ -18,7 +18,7 @@
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
"devDependencies": {
"devDependencies": {
@@ -1210,9 +1210,9 @@
@@ -1210,9 +1210,9 @@
}
}
},
},
"node_modules/openvibe-shared": {
"node_modules/openvibe-shared": {
- "version": "2.2.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
- "integrity": "sha512-1q+iUuUxzPeylTYmithW4jR++Jccvn5GEOrB1B3D18Dgn6OXQhPpvhPQAa1D1k1p+dWIa1/SmggyJwSGFnTNtw==",
+ "version": "2.3.1",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
+ "integrity": "sha512-K+MXnB4O+8xIFi+NQGC2SDTvDq3RkzfxQ3bTVx76Y/Rbuq7kC/L5kL3c/06xr9sPYcjyzF3Bhpv5yH2YNfR4Zw==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0"
"jsonwebtoken": "^9.0.0"
@@ -30,7 +30,7 @@
@@ -30,7 +30,7 @@
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.79.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.25.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
"devDependencies": {
"devDependencies": {
@@ -58,3 +58,11 @@ table.posts th, table.posts td { text-align: left; padding: 6px 8px; border-bott
@@ -58,3 +58,11 @@ table.posts th, table.posts td { text-align: left; padding: 6px 8px; border-bott
.ov-diff { white-space: pre-wrap; }
.ov-diff { white-space: pre-wrap; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
@media (max-width: 600px) { h1 { font-size: 1.7rem; } body { font-size: 16px; } }
@media (max-width: 600px) { h1 { font-size: 1.7rem; } body { font-size: 16px; } }
+
+/* The home's showcase sections (openvibe-shared/showcase.css) sit inside the reading column, which has its own gutter. */
+.page .sc-hero, .page .sc-sec { padding-left: 0; padding-right: 0; }
+.page .sc-hero { padding-top: 24px; }
+.page .sc-hero h1 { font-size: clamp(30px, 5vw, 42px); }
+.page .sc-sec { margin-top: 36px; }
+.page .sc-sec + #posts { display: block; margin-top: 40px; }
+.page .sc-ic .ov-icon { --ovi-size: 28px !important; }
@@ -16,6 +16,7 @@
@@ -16,6 +16,7 @@
* `public, max-age=60`; everything else — signed-in views, drafts, previews, unlisted,
* `public, max-age=60`; everything else — signed-in views, drafts, previews, unlisted,
* members/VIP and private posts, refusals, 404/410 — is `private, no-store` + X-Robots-Tag.
* members/VIP and private posts, refusals, 404/410 — is `private, no-store` + X-Robots-Tag.
*/
*/
+const showcase = require('openvibe-shared/showcase');
const express = require('express');
const express = require('express');
const ovServe = require('openvibe-shared/serve');
const ovServe = require('openvibe-shared/serve');
const frame = require('openvibe-shared/frame');
const frame = require('openvibe-shared/frame');
@@ -79,6 +80,26 @@ function createPublicRoutes(ctx) {
@@ -79,6 +80,26 @@ function createPublicRoutes(ctx) {
// ── Blog front pages ────────────────────────────────────
// ── Blog front pages ────────────────────────────────────
+ /** The product's own words above the official blog's posts: only features Blog has today. */
+ function blogShowcase() {
+ return showcase.hero({
+ eyebrow: 'OpenVibe.Blog',
+ title: 'Write on', accent: 'OpenVibe',
+ lede: 'A blog of your own with drafts, scheduling, feeds and comments. Sign in once with your OpenVibe account; anyone can read without one.',
+ actions: [{ label: 'Start writing', href: '/write', primary: true }, { label: 'Read the OpenVibe blog', href: '#posts' }],
+ }) + showcase.features({
+ title: 'What your blog gets',
+ items: [
+ { icon: 'ov:blog', title: 'Drafts and revisions', text: 'Every save is a revision you can go back to; publish when it is ready.' },
+ { icon: 'ov:history', title: 'Scheduling', text: 'Pick the minute a post goes live.' },
+ { icon: 'ov:news', title: 'Feeds', text: 'RSS, Atom and JSON Feed for every blog, series and category.' },
+ { icon: 'ov:community', title: 'Comments', text: 'Threads on OpenVibe.Community, moderated by you.' },
+ { icon: 'ov:theme', title: 'Your theme', text: 'Pick a theme preset and your blog wears it.' },
+ { icon: 'ov:vip', title: 'Members-only posts', text: 'Your OpenVibe.VIP members read the whole post; everyone else sees a teaser.' },
+ ],
+ }) + '<div id="posts"></div>';
+ }
+
async function blogFront(req, res, blog, { home = false } = {}) {
async function blogFront(req, res, blog, { home = false } = {}) {
const page = pageNumber(req);
const page = pageNumber(req);
const restricted = await isMember(blog, req.viewer);
const restricted = await isMember(blog, req.viewer);
@@ -115,7 +136,9 @@ function createPublicRoutes(ctx) {
@@ -115,7 +136,9 @@ function createPublicRoutes(ctx) {
jsonLd: [blog.kind === 'official'
jsonLd: [blog.kind === 'official'
? { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined, publisher: { '@type': 'Organization', name: 'OpenVibe', url: 'https://openvibe.network' } }
? { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined, publisher: { '@type': 'Organization', name: 'OpenVibe', url: 'https://openvibe.network' } }
: { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined }],
: { '@context': 'https://schema.org', '@type': 'Blog', '@id': `${publication.abs(path)}#blog`, name: blog.title, url: publication.abs(path), description: blog.description || undefined }],
- body: pages.blogIndex({
+ // The network's blog home opens with what OpenVibe.Blog is for (openvibe-shared/showcase), then the posts.
+ ...(home && pager.page === 1 ? { styles: [showcase.STYLESHEET] } : {}),
+ body: (home && pager.page === 1 ? blogShowcase() : '') + pages.blogIndex({
blog, blogUrl: `/@${blog.handle}`, items, pager, feeds,
blog, blogUrl: `/@${blog.handle}`, items, pager, feeds,
series: seriesShown, categories: await prune(await reading.categoriesTree(blog)),
series: seriesShown, categories: await prune(await reading.categoriesTree(blog)),
canWrite: await access.canWrite(store, req.viewer, blog, 'create'),
canWrite: await access.canWrite(store, req.viewer, blog, 'create'),
@@ -47,7 +47,7 @@ function themeStyle(vars) {
@@ -47,7 +47,7 @@ function themeStyle(vars) {
/**
/**
* o: title, description, decision (required), canonical, type ('website'|'article'), image,
* o: title, description, decision (required), canonical, type ('website'|'article'), image,
* jsonLd [], feeds [{ type, href, title }], body (HTML), viewer, config, csrf,
* jsonLd [], feeds [{ type, href, title }], body (HTML), viewer, config, csrf,
- * theme { slug, vars }, published, modified, author, prev, next, bodyClass
+ * theme { slug, vars }, published, modified, author, prev, next, bodyClass, styles [openvibe-shared stylesheet names]
*/
*/
function renderPage(o) {
function renderPage(o) {
if (!o.decision) throw new TypeError('renderPage needs the gate decision');
if (!o.decision) throw new TypeError('renderPage needs the gate decision');
@@ -97,6 +97,7 @@ ${o.modified ? `<meta property="article:modified_time" content="${esc(o.modified
@@ -97,6 +97,7 @@ ${o.modified ? `<meta property="article:modified_time" content="${esc(o.modified
${seo.feedLinks(o.feeds || [])}
${seo.feedLinks(o.feeds || [])}
${appIcon.headTags({ site: 'blog' })}
${appIcon.headTags({ site: 'blog' })}
<link rel="stylesheet" href="${asset('css/blog.css')}">
<link rel="stylesheet" href="${asset('css/blog.css')}">
+${(o.styles || []).map((name) => `<link rel="stylesheet" href="${esc(ovServe.url(name))}">`).join('\n')}
<script src="${ovServe.url('theme-loader.js')}" defer></script>
<script src="${ovServe.url('theme-loader.js')}" defer></script>
<script src="${ovServe.url('navbar.js')}" defer></script>
<script src="${ovServe.url('navbar.js')}" defer></script>
<script src="${ovServe.url('footer.js')}" defer></script>
<script src="${ovServe.url('footer.js')}" defer></script>
@@ -11,15 +11,17 @@ const path = require('path');
@@ -11,15 +11,17 @@ const path = require('path');
const { spawn } = require('child_process');
const { spawn } = require('child_process');
const { measure, check, format } = require('openvibe-shared/perf-budget');
const { measure, check, format } = require('openvibe-shared/perf-budget');
+// 2026-09-29: the home opens with the showcase hero and features (six inline ring icons) and links the cached
+// /shared/showcase.css: measured html 26.2 KB (6.8 br), css 15.9 KB (4.0 br). Raised as a decision.
const BUDGETS = {
const BUDGETS = {
- htmlRawKB: 22, // measured 17.4 (fresh database)
- htmlBrotliKB: 5.5, // 4.5
+ htmlRawKB: 29, // measured 17.4 (fresh database)
+ htmlBrotliKB: 7.5, // 4.5
jsFiles: 4, // 3
jsFiles: 4, // 3
jsRawKB: 230, // 197.7
jsRawKB: 230, // 197.7
jsBrotliKB: 53, // 45.6
jsBrotliKB: 53, // 45.6
cssFiles: 2, // 1
cssFiles: 2, // 1
- cssRawKB: 6.5, // 5.0
- cssBrotliKB: 2, // 1.4
+ cssRawKB: 17.5, // 5.0
+ cssBrotliKB: 4.5, // 1.4
externalFiles: 1, // 0
externalFiles: 1, // 0
};
};