diff --git a/.agents/skills/seo/SKILL.md b/.agents/skills/seo/SKILL.md
new file mode 100644
index 0000000..f2be260
--- /dev/null
+++ b/.agents/skills/seo/SKILL.md
@@ -0,0 +1,513 @@
+---
+name: seo
+description: Optimize for search engine visibility and ranking. Use when asked to "improve SEO", "optimize for search", "fix meta tags", "add structured data", "sitemap optimization", or "search engine optimization".
+license: MIT
+metadata:
+ author: web-quality-skills
+ version: "1.0"
+---
+
+# SEO optimization
+
+Search engine optimization based on Lighthouse SEO audits and Google Search guidelines. Focus on technical SEO, on-page optimization, and structured data.
+
+## SEO fundamentals
+
+Search ranking factors (approximate influence):
+
+| Factor | Influence | This Skill |
+|--------|-----------|------------|
+| Content quality & relevance | ~40% | Partial (structure) |
+| Backlinks & authority | ~25% | ✗ |
+| Technical SEO | ~15% | ✓ |
+| Page experience (Core Web Vitals) | ~10% | See [Core Web Vitals](../core-web-vitals/SKILL.md) |
+| On-page SEO | ~10% | ✓ |
+
+---
+
+## Technical SEO
+
+### Crawlability
+
+**robots.txt:**
+```text
+# /robots.txt
+User-agent: *
+Allow: /
+
+# Block admin/private areas
+Disallow: /admin/
+Disallow: /api/
+Disallow: /private/
+
+# Don't block resources needed for rendering
+# ❌ Disallow: /static/
+
+Sitemap: https://example.com/sitemap.xml
+```
+
+**Meta robots:**
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**Canonical URLs:**
+```html
+
+
+
+
+
+
+
+
+
+```
+
+### XML sitemap
+
+```xml
+
+
+
+ https://example.com/
+ 2024-01-15
+ daily
+ 1.0
+
+
+ https://example.com/products
+ 2024-01-14
+ weekly
+ 0.8
+
+
+```
+
+**Sitemap best practices:**
+- Maximum 50,000 URLs or 50MB per sitemap
+- Use sitemap index for larger sites
+- Include only canonical, indexable URLs
+- Update `lastmod` when content changes
+- Submit to Google Search Console
+
+### URL structure
+
+```
+✅ Good URLs:
+https://example.com/products/blue-widget
+https://example.com/blog/how-to-use-widgets
+
+❌ Poor URLs:
+https://example.com/p?id=12345
+https://example.com/products/item/category/subcategory/blue-widget-2024-sale-discount
+```
+
+**URL guidelines:**
+- Use hyphens, not underscores
+- Lowercase only
+- Keep short (< 75 characters)
+- Include target keywords naturally
+- Avoid parameters when possible
+- Use HTTPS always
+
+### HTTPS & security
+
+```html
+
+
+
+
+
+```
+
+**Security headers for SEO trust signals:**
+```
+Strict-Transport-Security: max-age=31536000; includeSubDomains
+X-Content-Type-Options: nosniff
+X-Frame-Options: DENY
+```
+
+---
+
+## On-page SEO
+
+### Title tags
+
+```html
+
+
Page
+Home
+
+
+Blue Widgets for Sale | Premium Quality | Example Store
+```
+
+**Title tag guidelines:**
+- 50-60 characters (Google truncates ~60)
+- Primary keyword near the beginning
+- Unique for every page
+- Brand name at end (unless homepage)
+- Action-oriented when appropriate
+
+### Meta descriptions
+
+```html
+
+
+
+
+
+```
+
+**Meta description guidelines:**
+- 150-160 characters
+- Include primary keyword naturally
+- Compelling call-to-action
+- Unique for every page
+- Matches page content
+
+### Heading structure
+
+```html
+
+Welcome to Our Store
+Products
+Contact Us
+
+
+Blue Widgets - Premium Quality
+ Product Features
+ Durability
+ Design
+ Customer Reviews
+ Pricing
+```
+
+**Heading guidelines:**
+- Single `` per page (the main topic)
+- Logical hierarchy (don't skip levels)
+- Include keywords naturally
+- Descriptive, not generic
+
+### Image SEO
+
+```html
+
+
+
+
+
+```
+
+**Image guidelines:**
+- Descriptive filenames with keywords
+- Alt text describes the image content
+- Compressed and properly sized
+- WebP/AVIF with fallbacks
+- Lazy load below-fold images
+
+### Internal linking
+
+```html
+
+Click here
+Read more
+
+
+Browse our blue widget collection
+Learn how to maintain your widgets
+```
+
+**Linking guidelines:**
+- Descriptive anchor text with keywords
+- Link to relevant internal pages
+- Reasonable number of links per page
+- Fix broken links promptly
+- Use breadcrumbs for hierarchy
+
+---
+
+## Structured data (JSON-LD)
+
+### Organization
+
+```html
+
+```
+
+### Article
+
+```html
+
+```
+
+### Product
+
+```html
+
+```
+
+### FAQ
+
+```html
+
+```
+
+### Breadcrumbs
+
+```html
+
+```
+
+### Validation
+
+Test structured data at:
+- [Google Rich Results Test](https://search.google.com/test/rich-results)
+- [Schema.org Validator](https://validator.schema.org/)
+
+---
+
+## Mobile SEO
+
+### Responsive design
+
+```html
+
+
+
+
+
+```
+
+### Tap targets
+
+```css
+/* ❌ Too small for mobile */
+.small-link {
+ padding: 4px;
+ font-size: 12px;
+}
+
+/* ✅ Adequate tap target */
+.mobile-friendly-link {
+ padding: 12px;
+ font-size: 16px;
+ min-height: 48px;
+ min-width: 48px;
+}
+```
+
+### Font sizes
+
+```css
+/* ❌ Too small on mobile */
+body {
+ font-size: 10px;
+}
+
+/* ✅ Readable without zooming */
+body {
+ font-size: 16px;
+ line-height: 1.5;
+}
+```
+
+---
+
+## International SEO
+
+### Hreflang tags
+
+```html
+
+
+
+
+
+```
+
+### Language declaration
+
+```html
+
+
+
+```
+
+---
+
+## SEO audit checklist
+
+### Critical
+- [ ] HTTPS enabled
+- [ ] robots.txt allows crawling
+- [ ] No `noindex` on important pages
+- [ ] Title tags present and unique
+- [ ] Single `` per page
+
+### High priority
+- [ ] Meta descriptions present
+- [ ] Sitemap submitted
+- [ ] Canonical URLs set
+- [ ] Mobile-responsive
+- [ ] Core Web Vitals passing
+
+### Medium priority
+- [ ] Structured data implemented
+- [ ] Internal linking strategy
+- [ ] Image alt text
+- [ ] Descriptive URLs
+- [ ] Breadcrumb navigation
+
+### Ongoing
+- [ ] Fix crawl errors in Search Console
+- [ ] Update sitemap when content changes
+- [ ] Monitor ranking changes
+- [ ] Check for broken links
+- [ ] Review Search Console insights
+
+---
+
+## Tools
+
+| Tool | Use |
+|------|-----|
+| Google Search Console | Monitor indexing, fix issues |
+| Google PageSpeed Insights | Performance + Core Web Vitals |
+| Rich Results Test | Validate structured data |
+| Lighthouse | Full SEO audit |
+| Screaming Frog | Crawl analysis |
+
+## References
+
+- [Google Search Central](https://developers.google.com/search)
+- [Schema.org](https://schema.org/)
+- [Core Web Vitals](../core-web-vitals/SKILL.md)
+- [Web Quality Audit](../web-quality-audit/SKILL.md)
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index d73b694..276eb6b 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -14,7 +14,8 @@
"Bash(git remote:*)",
"Bash(find /Users/jeet/Desktop/Jio/grateful-journal/src -type f -name *.ts -o -name *.tsx)",
"Bash(ls -la /Users/jeet/Desktop/Jio/grateful-journal/*.config.*)",
- "mcp__ide__getDiagnostics"
+ "mcp__ide__getDiagnostics",
+ "Bash(npx skills:*)"
]
}
}
diff --git a/.claude/skills/seo b/.claude/skills/seo
new file mode 120000
index 0000000..946efb7
--- /dev/null
+++ b/.claude/skills/seo
@@ -0,0 +1 @@
+../../.agents/skills/seo
\ No newline at end of file
diff --git a/index.html b/index.html
index 941ae98..e3da8ee 100644
--- a/index.html
+++ b/index.html
@@ -20,10 +20,12 @@
Grateful Journal — Your Private Gratitude Journal
+
+
@@ -45,16 +47,40 @@
"description": "A private, end-to-end encrypted gratitude journal. No feeds, no noise — just you and your thoughts.",
"applicationCategory": "LifestyleApplication",
"operatingSystem": "Web, Android, iOS",
+ "browserRequirements": "Requires JavaScript. Requires HTML5.",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
- }
+ },
+ "featureList": [
+ "End-to-end encrypted journal entries",
+ "Daily gratitude prompts",
+ "Private and secure — no ads, no tracking",
+ "Works offline as a PWA"
+ ]
}
+
diff --git a/nginx/default.conf b/nginx/default.conf
index 62d319e..e88ce53 100644
--- a/nginx/default.conf
+++ b/nginx/default.conf
@@ -23,7 +23,17 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
}
- location / {
- try_files $uri $uri/ /index.html;
+ # Known SPA routes — serve index.html
+ location = / {
+ try_files /index.html =404;
}
-}
\ No newline at end of file
+
+ location ~ ^/(write|history|settings)(/|$) {
+ try_files /index.html =404;
+ }
+
+ # Static assets — serve directly, 404 if missing
+ location / {
+ try_files $uri $uri/ =404;
+ }
+}
diff --git a/public/robots.txt b/public/robots.txt
index e1bed4f..2a36987 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -1,7 +1,6 @@
User-agent: *
-Allow: /
-Disallow: /
+Disallow: /write
+Disallow: /history
+Disallow: /settings
-User-agent: Googlebot
-Allow: /login
-Disallow: /
+Sitemap: https://gratefuljournal.online/sitemap.xml
diff --git a/public/sitemap.xml b/public/sitemap.xml
index bef057f..41c5e8a 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -1,7 +1,8 @@
- https://gratefuljournal.online/login
+ https://gratefuljournal.online/
+ 2026-04-08
monthly
1.0
diff --git a/skills-lock.json b/skills-lock.json
new file mode 100644
index 0000000..ebf08d6
--- /dev/null
+++ b/skills-lock.json
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "skills": {
+ "seo": {
+ "source": "addyosmani/web-quality-skills",
+ "sourceType": "github",
+ "computedHash": "f1fed683b76913d26fbf1aa1e008e6932f7771701fc3a79925b042236aa4681a"
+ }
+ }
+}
diff --git a/src/App.css b/src/App.css
index 224b6b8..f8a55c2 100644
--- a/src/App.css
+++ b/src/App.css
@@ -2917,11 +2917,17 @@
font-weight: 600 !important;
}
+@keyframes tour-btn-pulse {
+ 0%, 100% { opacity: 1; transform: scale(1); }
+ 50% { opacity: 0.6; transform: scale(0.96); }
+}
+
.gj-tour-popover .driver-popover-next-btn {
background: var(--color-primary, #22c55e) !important;
color: #fff !important;
border: none !important;
text-shadow: none !important;
+ animation: tour-btn-pulse 1.2s ease-in-out infinite !important;
}
.gj-tour-popover .driver-popover-prev-btn {
diff --git a/src/App.tsx b/src/App.tsx
index afe9b3c..4e1a59e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,8 +12,9 @@ function App() {
+ } />
@@ -36,8 +37,7 @@ function App() {
}
/>
- } />
- } />
+ } />
diff --git a/src/components/BottomNav.tsx b/src/components/BottomNav.tsx
index 8340737..efa3a5e 100644
--- a/src/components/BottomNav.tsx
+++ b/src/components/BottomNav.tsx
@@ -21,8 +21,8 @@ export default function BottomNav() {
{/* Write */}
diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx
index 1ebbef3..703f1b4 100644
--- a/src/pages/LoginPage.tsx
+++ b/src/pages/LoginPage.tsx
@@ -13,7 +13,7 @@ export default function LoginPage() {
useEffect(() => {
if (loading) return
- if (user) navigate('/', { replace: true })
+ if (user) navigate('/write', { replace: true })
}, [user, loading, navigate])
async function handleGoogleSignIn() {
diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx
index aced983..9854342 100644
--- a/src/pages/SettingsPage.tsx
+++ b/src/pages/SettingsPage.tsx
@@ -71,9 +71,8 @@ export default function SettingsPage() {
}, [])
const handleSeeTutorial = () => {
- localStorage.removeItem('gj-onboarding-done')
- localStorage.removeItem('gj-tour-pending-step')
- navigate('/')
+ localStorage.setItem('gj-force-tour', 'true')
+ navigate('/write')
}
const displayName = mongoUser?.displayName || user?.displayName || 'User'