@lightupai/polaris 0.0.59 → 0.0.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -91,5 +91,6 @@ jobs:
91
91
  git pull --ff-only &&
92
92
  docker compose -f docker-compose.prod.yml build &&
93
93
  docker compose -f docker-compose.prod.yml up -d --remove-orphans &&
94
+ docker compose -f docker-compose.prod.yml exec caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || true &&
94
95
  docker compose -f docker-compose.prod.yml ps
95
96
  "
package/deploy.sh CHANGED
@@ -12,6 +12,7 @@ ssh "$USER@$HOST" "
12
12
  git pull --ff-only &&
13
13
  docker compose -f docker-compose.prod.yml build &&
14
14
  docker compose -f docker-compose.prod.yml up -d --remove-orphans &&
15
+ docker compose -f docker-compose.prod.yml exec caddy caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || true &&
15
16
  docker compose -f docker-compose.prod.yml ps
16
17
  "
17
18
 
package/docker/Caddyfile CHANGED
@@ -1,7 +1,9 @@
1
1
  withpolaris.ai, app.withpolaris.ai {
2
+ encode zstd gzip
2
3
  reverse_proxy web:3000
3
4
  }
4
5
 
5
6
  api.withpolaris.ai {
7
+ encode zstd gzip
6
8
  reverse_proxy api:4321
7
9
  }
package/docs/seo-geo.md CHANGED
@@ -11,6 +11,10 @@
11
11
  - [x] **sitemap.xml** — lists the landing page
12
12
  - [x] **Cloudflare DNS** — domain managed on Cloudflare with MX + SPF records
13
13
  - [x] **Email routing** — `*@withpolaris.ai` forwards to `support@lightup.ai`
14
+ - [x] **Self-host Tailwind CSS** — replaced 127KB CDN script with purged 26KB static CSS (5.5KB gzip). Production Lighthouse: score 84→99, FCP 3.4s→1.6s, page weight 175KB→77KB
15
+ - [x] **Lighthouse performance audit** — `make perf` runs mobile+desktop against prod and local, checks Google "good" budgets (score≥90, FCP≤1.8s, LCP≤2.5s), saves JSON to `docs/audits/`
16
+ - [x] **DataForSEO on-page audit** — `make seo` runs 20 SEO checks via DataForSEO API, saves JSON to `docs/audits/`
17
+ - [x] **Heading hierarchy** — verified: 1×h1, 7×h2, 18×h3, proper structure (DataForSEO score 100/100)
14
18
 
15
19
  ## SEO — To Do
16
20
 
@@ -27,10 +31,13 @@
27
31
  - Cloudflare Web Analytics (free, built into Cloudflare dashboard)
28
32
  Add the tracking script to the layout.
29
33
 
30
- - [ ] **Self-host Tailwind CSS**
31
- Currently loading Tailwind CDN (~300KB) on every page. Purge and self-host
32
- to reduce to ~10KB. Improves page speed and Core Web Vitals score.
33
- Affects Google ranking.
34
+ - [ ] **Favicon**
35
+ No favicon set. Flagged by DataForSEO audit. Add one for browser tabs and bookmarks.
36
+ Use the Polaris hub icon or a simplified version.
37
+
38
+ - [ ] **Enable gzip/brotli compression**
39
+ DataForSEO flagged `no_content_encoding`. Caddy should be compressing responses.
40
+ Add `encode gzip zstd` to the Caddyfile.
34
41
 
35
42
  ### Medium Priority
36
43
 
@@ -61,15 +68,11 @@
61
68
  - "Gong for AI coding"
62
69
  Options: simple `/blog` route with markdown rendering, or a subdomain `blog.withpolaris.ai`.
63
70
 
64
- - [ ] **Heading hierarchy audit**
65
- Ensure proper h1 → h2 → h3 structure on the landing page.
66
- Only one h1 per page. Check that section headers use correct levels.
67
-
68
71
  ### Low Priority
69
72
 
70
- - [ ] **Favicon**
71
- No favicon set. Add one for browser tabs and bookmarks.
72
- Use the Polaris hub icon or a simplified version.
73
+ - [ ] **Improve content rate**
74
+ DataForSEO flagged text at 8.2% of page HTML (want ≥10%).
75
+ More copy or blog content will fix this.
73
76
 
74
77
  - [ ] **404 page**
75
78
  Custom 404 page with navigation back to the landing page.
@@ -108,9 +111,9 @@
108
111
  - Or relying on Cloudflare proxy to cache static content at edge
109
112
 
110
113
  - [ ] **Cache headers for static assets**
111
- OG image has 24h cache. Landing page HTML has `Cache-Control: no-store`.
112
- Consider adding short cache (5-10 min) for the landing page since it
113
- changes infrequently. CSS/JS should have long cache with versioned URLs.
114
+ OG image has 24h cache. CSS has immutable 1yr cache. Landing page HTML
115
+ has `Cache-Control: no-store` — consider short cache (5-10 min) since
116
+ it changes infrequently.
114
117
 
115
118
  ### Low Priority
116
119
 
package/favicon.svg ADDED
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <circle cx="16" cy="16" r="14" fill="#4c6ef5"/>
3
+ <circle cx="16" cy="16" r="4" fill="white"/>
4
+ <circle cx="16" cy="6" r="2.5" fill="white"/>
5
+ <circle cx="24.7" cy="21" r="2.5" fill="white"/>
6
+ <circle cx="7.3" cy="21" r="2.5" fill="white"/>
7
+ <line x1="16" y1="12" x2="16" y2="8.5" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
8
+ <line x1="19.5" y1="18" x2="22.5" y2="19.5" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
9
+ <line x1="12.5" y1="18" x2="9.5" y2="19.5" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
10
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightupai/polaris",
3
- "version": "0.0.59",
3
+ "version": "0.0.61",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "polaris": "bin/polaris",
@@ -118,8 +118,8 @@ check("Desc/content match", content.description_to_content_consistency >= 0.8,
118
118
 
119
119
  // Technical
120
120
  check("Favicon", !checks.no_favicon, checks.no_favicon ? "missing" : "present");
121
- check("No render-blocking", !checks.has_render_blocking_resources,
122
- checks.has_render_blocking_resources ? `${meta.render_blocking_scripts_count} script(s)` : "clean");
121
+ check("No render-blocking scripts", (meta.render_blocking_scripts_count ?? 0) === 0,
122
+ (meta.render_blocking_scripts_count ?? 0) === 0 ? "clean" : `${meta.render_blocking_scripts_count} script(s)`);
123
123
  check("Content encoding", !checks.no_content_encoding,
124
124
  checks.no_content_encoding ? "no gzip/brotli" : "enabled");
125
125
  check("SEO-friendly URL", !!checks.seo_friendly_url, checks.seo_friendly_url ? "yes" : "no");
package/src/web/app.ts CHANGED
@@ -149,6 +149,15 @@ export function createApp(sql: Sql) {
149
149
  });
150
150
  });
151
151
 
152
+ app.get("/favicon.svg", async (c) => {
153
+ const file = Bun.file(new URL("../../favicon.svg", import.meta.url).pathname);
154
+ return new Response(await file.arrayBuffer(), {
155
+ headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=31536000, immutable" },
156
+ });
157
+ });
158
+
159
+ app.get("/favicon.ico", (c) => c.redirect("/favicon.svg", 301));
160
+
152
161
  // --- SEO ---
153
162
 
154
163
  app.get("/og-image.png", async (c) => {
package/src/web/layout.ts CHANGED
@@ -37,6 +37,7 @@ export function layout(body: string, title = "Polaris", seo?: SeoOpts): Response
37
37
  <meta name="twitter:title" content="${pageTitle}">
38
38
  <meta name="twitter:description" content="${description}">
39
39
  <meta name="twitter:image" content="${ogImage}">
40
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg">
40
41
  <link rel="stylesheet" href="/styles.css">
41
42
  </head>
42
43
  <body class="bg-gray-50 text-gray-900 antialiased"><div class="overflow-x-hidden max-w-[100vw]">${body}</div>