Skip to content

Commit 98bdcc3

Browse files
committed
Website: Features page, smart quotes, copy pass
Huge update, now it's not just AI-gen shite - Add `/features` page with detailed descriptions for each feature, sourced from CLAUDE.md files and code - Add "Private LLM included" feature box after "Live full-disk index" with `sparkles.svg` icon - Make all feature boxes clickable, linking to `/features#slug` - Add smart quote auto-conversion: `remark-smartypants` for markdown, custom Astro integration for .astro pages - Fix roadmap mobile layout (CSS grid so checkbox + title share a row) - Align pricing card CTAs with `flex-col` + `mt-auto` - Rewrite website copy to match writing style guide (casual tone, contractions, active voice, no corporate speak) - Sync FAQ ld+json structured data with visible FAQ text - Update footer: personal branding with social links, drop "All rights reserved" - Update nav/footer links from `/#features` to `/features`
1 parent 87e0e58 commit 98bdcc3

20 files changed

Lines changed: 500 additions & 116 deletions

apps/website/astro.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
import { defineConfig } from 'astro/config'
33
import tailwindcss from '@tailwindcss/vite'
44
import rehypeExternalLinks from 'rehype-external-links'
5+
import remarkSmartypants from 'remark-smartypants'
56
import sitemap from '@astrojs/sitemap'
7+
import { smartQuotesIntegration } from './src/plugins/smart-quotes.mjs'
68

79
// https://astro.build/config
810
export default defineConfig({
911
site: 'https://getcmdr.com',
1012
output: 'static',
11-
integrations: [sitemap()],
13+
integrations: [sitemap(), smartQuotesIntegration()],
1214
server: {
1315
port: parseInt(process.env.PORT || '4321'),
1416
},
@@ -20,6 +22,8 @@ export default defineConfig({
2022
},
2123
defaultColor: false,
2224
},
25+
// @ts-expect-error remark-smartypants types use generic Node, Astro expects Root
26+
remarkPlugins: [remarkSmartypants],
2327
rehypePlugins: [[rehypeExternalLinks, { target: '_blank', rel: ['noopener', 'noreferrer'] }]],
2428
},
2529
vite: {

apps/website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"astro": "^5.18.0",
2626
"marked": "^17.0.4",
2727
"rehype-external-links": "3.0.0",
28+
"remark-smartypants": "^3.0.2",
2829
"satori": "0.19.2",
2930
"sharp": "^0.34.5",
3031
"tailwindcss": "^4.2.1"
Lines changed: 1 addition & 0 deletions
Loading

apps/website/src/components/Download.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import NewsletterInlineWrapper from './NewsletterInlineWrapper.astro'
1111
</div>
1212

1313
<div class="relative mx-auto max-w-4xl text-center">
14-
<h2 class="mb-4 text-3xl font-bold md:text-4xl lg:text-5xl">Ready to try Cmdr?</h2>
14+
<h2 class="mb-4 text-3xl font-bold md:text-4xl lg:text-5xl">Get Cmdr now!</h2>
1515
<p class="mb-10 text-lg text-[var(--color-text-secondary)]">
16-
Free forever for personal use. No signup required.
16+
Free forever for personal use. No signup, no account needed.
1717
</p>
1818

1919
<!-- Download card -->

apps/website/src/components/Features.astro

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,55 @@
11
---
22
const shipped = [
33
{
4+
slug: 'full-disk-index',
45
icon: '/icons/database.svg',
56
title: 'Live full-disk index',
67
description:
78
'Indexes your entire drive once in about 4 minutes. Then stays current forever, even across restarts.',
89
},
910
{
11+
slug: 'private-llm',
12+
icon: '/icons/sparkles.svg',
13+
title: 'Private LLM included',
14+
description:
15+
'Comes with an on-device model for free, private use. Bring your own OpenAI/Anthropic/etc. API key for smarter results.',
16+
},
17+
{
18+
slug: 'speed',
1019
icon: '/icons/rocket.svg',
11-
title: 'Blazing fast',
20+
title: 'Really, really fast',
1221
description:
13-
'Built in Rust. Opens a 100k-file folder in 4 seconds with icons, sizes, and dates. Try that in Finder.',
22+
'Built in Rust. Opens a 100k-file folder in 4 seconds with icons, sizes, and dates, cold. In 1 second when warm.',
1423
},
1524
{
25+
slug: 'keyboard-first',
1626
icon: '/icons/keyboard.svg',
1727
title: 'Keyboard-first',
18-
description: 'Navigate, select, copy, move. All without touching your mouse. Two panes, tabs, command palette.',
28+
description: 'Kb-first navigate, select, copy, move, rename; menus, tabs, settings; command palette. But works with a mouse, too.',
1929
},
2030
]
2131
2232
const upcoming = [
2333
{
34+
slug: 'smart-search',
2435
icon: '/icons/search.svg',
2536
title: 'Smart search',
2637
description:
27-
'Find files by describing them: "that PDF contract from last month" or "screenshots with error messages."',
38+
'Find files by saying: "that PDF contract from last month" or "all my node_modules folders"',
2839
badge: 'Works but early stage',
2940
},
3041
{
42+
slug: 'ai-rename',
3143
icon: '/icons/brain.svg',
3244
title: 'Natural language rename',
33-
description:
34-
'Type "make these lowercase and add date prefix" and watch it happen. No regex, no scripts, just words.',
45+
description: 'Commands like "make these files lowercase and add date prefix". No regex, no scripts.',
3546
badge: 'Coming soon',
3647
},
3748
{
49+
slug: 'ai-batch',
3850
icon: '/icons/zap.svg',
39-
title: 'AI batch operations',
40-
description: 'Organize hundreds of files with a single command. "Sort these into folders by project name."',
51+
title: 'AI file organization',
52+
description: 'Say "Clean up my Downloads folder" to get a list of move/delete suggestions you can approve/reject.',
4153
badge: 'Coming soon',
4254
},
4355
]
@@ -51,19 +63,22 @@ const upcoming = [
5163
Built for <span class="gradient-text">power users</span>
5264
</h2>
5365
<p class="mx-auto max-w-2xl text-lg text-[var(--color-text-secondary)]">
54-
Fast, keyboard-driven, and getting smarter.
66+
Fast, keyboard-driven, and getting smarter every week.
5567
</p>
5668
</div>
5769

5870
<!-- Shipped features -->
59-
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
71+
<div class="grid gap-6 md:grid-cols-2">
6072
{
6173
shipped.map((feature) => (
62-
<div class="group relative rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 transition-all duration-300 hover:border-[var(--color-accent)]/30 hover:bg-[var(--color-surface-elevated)]">
74+
<a
75+
href={`/features#${feature.slug}`}
76+
class="group relative block rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] p-8 no-underline transition-all duration-300 hover:border-[var(--color-accent)]/30 hover:bg-[var(--color-surface-elevated)]"
77+
>
6378
<img src={feature.icon} alt="" class="mb-4 size-10" />
6479
<h3 class="mb-2 text-xl font-semibold">{feature.title}</h3>
6580
<p class="text-[var(--color-text-secondary)]">{feature.description}</p>
66-
</div>
81+
</a>
6782
))
6883
}
6984
</div>
@@ -77,20 +92,19 @@ const upcoming = [
7792
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
7893
{
7994
upcoming.map((feature) => (
80-
<div class="group relative rounded-2xl border border-[var(--color-accent)]/30 bg-gradient-to-br from-[var(--color-surface)] to-[var(--color-accent)]/5 p-8 transition-all duration-300 hover:border-[var(--color-accent)]/50">
95+
<a
96+
href={`/features#${feature.slug}`}
97+
class="group relative block rounded-2xl border border-[var(--color-accent)]/30 bg-gradient-to-br from-[var(--color-surface)] to-[var(--color-accent)]/5 p-8 no-underline transition-all duration-300 hover:border-[var(--color-accent)]/50"
98+
>
8199
{feature.badge && (
82-
<a
83-
href="/roadmap"
84-
class="absolute top-4 right-4 rounded-full bg-[var(--color-accent)]/20 px-2.5 py-1 text-xs font-medium text-[var(--color-accent-text)] transition-colors hover:bg-[var(--color-accent)]/30"
85-
aria-label={`${feature.badge} — view roadmap`}
86-
>
100+
<span class="absolute top-4 right-4 rounded-full bg-[var(--color-accent)]/20 px-2.5 py-1 text-xs font-medium text-[var(--color-accent-text)]">
87101
{feature.badge}
88-
</a>
102+
</span>
89103
)}
90104
<img src={feature.icon} alt="" class="mb-4 size-10" />
91105
<h3 class="mb-2 text-xl font-semibold">{feature.title}</h3>
92106
<p class="text-[var(--color-text-secondary)]">{feature.description}</p>
93-
</div>
107+
</a>
94108
))
95109
}
96110
</div>

apps/website/src/components/Footer.astro

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const currentYear = new Date().getFullYear()
2222
<ul class="space-y-2 text-sm">
2323
<li>
2424
<a
25-
href="/#features"
25+
href="/features"
2626
class="text-[var(--color-text-secondary)] underline decoration-[var(--color-border)] underline-offset-2 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-tertiary)]"
2727
>
2828
Features
@@ -124,7 +124,7 @@ const currentYear = new Date().getFullYear()
124124
>
125125
<div>
126126
<p class="font-semibold text-[var(--color-text-primary)]">Stay in the loop</p>
127-
<p class="text-sm text-[var(--color-text-secondary)]">Product updates and Cmdr news. No spam, ever.</p>
127+
<p class="text-sm text-[var(--color-text-secondary)]">Product updates and news. No spam, ever.</p>
128128
</div>
129129
<div class="w-full md:w-auto md:min-w-[320px]">
130130
<NewsletterForm variant="inline" />
@@ -133,12 +133,16 @@ const currentYear = new Date().getFullYear()
133133

134134
<!-- Bottom bar -->
135135
<div
136-
class="flex flex-col items-center justify-between gap-4 border-t border-[var(--color-border-subtle)] pt-8 md:flex-row"
136+
class="flex flex-wrap items-center justify-center gap-x-1 border-t border-[var(--color-border-subtle)] pt-8 text-sm text-[var(--color-text-tertiary)]"
137137
>
138-
<p class="text-sm text-[var(--color-text-tertiary)]">
139-
© {currentYear} Rymdskottkärra AB. All rights reserved.
140-
</p>
141-
<p class="text-sm text-[var(--color-text-tertiary)]">Made with ❤️ in Sweden</p>
138+
<span{currentYear} David Veszelovszki ·</span>
139+
<a href="https://veszelovszki.com" target="_blank" rel="noopener noreferrer" class="underline decoration-[var(--color-border)] underline-offset-2 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-tertiary)]">veszelovszki.com</a>
140+
<span>·</span>
141+
<a href="https://github.com/vdavid" target="_blank" rel="noopener noreferrer" class="underline decoration-[var(--color-border)] underline-offset-2 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-tertiary)]">GitHub</a>
142+
<span>·</span>
143+
<a href="https://x.com/vdavid" target="_blank" rel="noopener noreferrer" class="underline decoration-[var(--color-border)] underline-offset-2 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-tertiary)]">X</a>
144+
<span>·</span>
145+
<a href="https://www.linkedin.com/in/veszelovszki/" target="_blank" rel="noopener noreferrer" class="underline decoration-[var(--color-border)] underline-offset-2 transition-colors hover:text-[var(--color-text-primary)] hover:decoration-[var(--color-text-tertiary)]">LinkedIn</a>
142146
</div>
143147
</div>
144148
</footer>

apps/website/src/components/Header.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import NewsletterForm from './NewsletterForm.astro'
44
import ThemeToggle from './ThemeToggle.astro'
55
66
const navLinks = [
7-
{ href: '/#features', label: 'Features' },
7+
{ href: '/features', label: 'Features' },
88
{ href: '/pricing', label: 'Pricing' },
99
{ href: '/blog', label: 'Blog' },
1010
{ href: '/changelog', label: 'Changelog' },

apps/website/src/components/Hero.astro

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ import DownloadButton from './DownloadButton.astro'
2626

2727
<!-- Headline - Steps 2 & 3 -->
2828
<h1 class="mb-6 text-3xl font-bold leading-tight tracking-tight md:text-4xl lg:text-6xl">
29-
<span class="animate-blur-in stagger-2 inline-block">Every folder sized.</span>
30-
<span class="animate-blur-in stagger-3 inline-block gradient-text">Every file found.</span>
29+
<span class="animate-blur-in stagger-2 inline-block">Finally, a file manager</span>
30+
<span class="animate-blur-in stagger-3 inline-block gradient-text">from 2026</span>
3131
</h1>
3232

3333
<!-- Subheadline - Step 4 -->
3434
<p
3535
class="animate-blur-in stagger-4 mb-10 max-w-xl text-lg leading-relaxed text-[var(--color-text-secondary)] md:text-xl"
3636
>
37-
Indexes your entire drive in minutes. Directory sizes everywhere, instant search, keyboard-driven
38-
everything. Built in Rust, free for personal use.
37+
Indexes your whole drive in minutes. Folder sizes everywhere, instant search, keyboard-driven everything.
38+
Built in Rust, free for personal use.
3939
</p>
4040

4141
<!-- CTA Buttons - Steps 5 & 6 -->

apps/website/src/components/Story.astro

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,4 @@
88
>a dev</a
99
> who's used two-pane file managers for 35 years and couldn't find a good one on Mac.
1010
</p>
11-
12-
<div class="mx-auto mt-6 flex max-w-xl flex-wrap items-center justify-center gap-x-8 gap-y-3 text-sm">
13-
<a
14-
href="https://gitstrata.com/github.com/vdavid/cmdr"
15-
target="_blank"
16-
rel="noopener noreferrer"
17-
class="text-[var(--color-text-tertiary)] transition-colors hover:text-[var(--color-accent-text)]"
18-
>
19-
<span class="font-semibold text-[var(--color-text-secondary)]">180k</span> lines of code
20-
</a>
21-
<a
22-
href="https://gitstrata.com/github.com/vdavid/cmdr"
23-
target="_blank"
24-
rel="noopener noreferrer"
25-
class="text-[var(--color-text-tertiary)] transition-colors hover:text-[var(--color-accent-text)]"
26-
>
27-
<span class="font-semibold text-[var(--color-text-secondary)]">1,000</span> commits in 12 weeks
28-
</a>
29-
<a
30-
href="https://github.com/vdavid/cmdr"
31-
target="_blank"
32-
rel="noopener noreferrer"
33-
class="text-[var(--color-text-tertiary)] transition-colors hover:text-[var(--color-accent-text)]"
34-
>
35-
<span class="font-semibold text-[var(--color-text-secondary)]">100%</span> source-available
36-
</a>
37-
</div>
3811
</section>

apps/website/src/components/Testimonials.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const testimonials = [
1515
<section class="relative px-6 py-32">
1616
<div class="mx-auto max-w-6xl">
1717
<div class="mb-16 text-center">
18-
<h2 class="mb-4 text-3xl font-bold md:text-4xl lg:text-5xl">Notes from the builder</h2>
18+
<h2 class="mb-4 text-3xl font-bold md:text-4xl lg:text-5xl">Notes from the dev</h2>
1919
</div>
2020

2121
<div class="grid gap-6 md:grid-cols-3">

0 commit comments

Comments
 (0)