diff --git a/docs/commercial/checkout-migration.md b/docs/commercial/checkout-migration.md index a88588d..79b38ea 100644 --- a/docs/commercial/checkout-migration.md +++ b/docs/commercial/checkout-migration.md @@ -11,7 +11,14 @@ This runbook moves Dictx Pro sales to `https://dictx.splitlabs.io/buy` while kee ## 1) Domain + Checkout 1. Create `dictx.splitlabs.io` as your Vercel custom domain and serve the landing site there. -2. Configure branded checkout: +2. Deploy the dedicated Vercel landing project from `landing/`: + +- Root Directory: `landing` +- Framework Preset: `Other` +- Build Command: empty +- Output Directory: empty + +3. Configure branded checkout: - Product name: `Dictx Pro` - Offer copy: `Signed binaries, auto-updates, and direct support` @@ -63,7 +70,7 @@ Completed in this repo: 2. Publish FAQ with key points: - Existing licenses remain honored -- New purchases go through `https://dictx.splitlabs.io/buy` +- New purchases go through `https://dictx.splitlabs.io/buy` (redirect target managed in `landing/vercel.json`) - Support contact stays unchanged 3. Use template: diff --git a/landing/README.md b/landing/README.md new file mode 100644 index 0000000..b0175cc --- /dev/null +++ b/landing/README.md @@ -0,0 +1,19 @@ +# Dictx Landing (Vercel) + +Deploy this folder as a separate Vercel project. + +## Vercel Settings + +- Root Directory: `landing` +- Framework Preset: `Other` +- Build Command: _(empty)_ +- Output Directory: _(empty)_ + +## Domain + +Attach `dictx.splitlabs.io` to this Vercel project. + +## Routes + +- `/` serves `landing/index.html` +- `/buy` redirects to `https://buy.splitlabs.io` diff --git a/landing/index.html b/landing/index.html new file mode 100644 index 0000000..e65658f --- /dev/null +++ b/landing/index.html @@ -0,0 +1,144 @@ + + + + + + Dictx | Privacy-first desktop speech-to-text + + + + +
+ + +
+
+

Split Labs • Dictx

+

Voice capture for serious writing workflows.

+

+ Transcribe locally, keep control of your data, and ship faster with a + desktop app designed for daily use. +

+ +

+ $29 one-time • signed binaries • auto-updates • macOS / Windows / + Linux +

+
+ +
+
+

100% local transcription

+

+ No cloud dependency for core speech-to-text. Your audio stays + on-device. +

+
+
+

Built for daily flow

+

+ Hotkeys, quick model switching, and output controls that fit real + writing sessions. +

+
+
+

Obsidian-ready output

+

+ Export notes with metadata and keep your knowledge workflow tidy. +

+
+
+ +
+

Free or Pro

+
+
+

Free

+

$0

+
    +
  • GPL source code
  • +
  • Build from source
  • +
  • All core functionality
  • +
  • Community support
  • +
+ View source +
+
+

Pro

+

$29 one-time

+
    +
  • Signed desktop binaries
  • +
  • In-app auto-updater
  • +
  • Professional checkout
  • +
  • Directly supports development
  • +
+ Get Dictx Pro +
+
+
+ +
+

FAQ

+
+ Is Dictx still open source? +

Yes. Dictx remains GPL-licensed and free to build from source.

+
+
+ What does Pro actually add? +

+ Pro is the distribution layer: signed installers and updater + convenience. +

+
+
+ Where does /buy go? +

+ `/buy` redirects to the hosted checkout target configured in + `landing/vercel.json`. +

+
+
+
+ + + + + + diff --git a/landing/styles.css b/landing/styles.css new file mode 100644 index 0000000..d35e506 --- /dev/null +++ b/landing/styles.css @@ -0,0 +1,331 @@ +:root { + --color-text: #e4e4e7; + --color-background: #09090b; + --color-background-ui: #6d28d9; + --color-logo-primary: #a78bfa; + --color-logo-stroke: #c4b5fd; + --color-mid-gray: #71717a; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; + background: + radial-gradient( + circle at 15% -10%, + rgba(109, 40, 217, 0.3), + transparent 40% + ), + radial-gradient( + circle at 85% -20%, + rgba(167, 139, 250, 0.22), + transparent 42% + ), + var(--color-background); + color: var(--color-text); + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; +} + +.noise { + position: fixed; + inset: 0; + pointer-events: none; + background-image: radial-gradient( + rgba(255, 255, 255, 0.18) 0.28px, + transparent 0.28px + ); + background-size: 3px 3px; + opacity: 0.05; +} + +.shell { + max-width: 1060px; + margin: 0 auto; + padding: 0 20px; +} + +.nav { + padding-top: 22px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; +} + +.wordmark { + color: var(--color-logo-primary); + text-decoration: none; + font-size: 34px; + font-weight: 700; + letter-spacing: -0.04em; +} + +.menu { + display: flex; + align-items: center; + gap: 16px; +} + +.menu a { + color: color-mix(in srgb, var(--color-text) 86%, transparent); + text-decoration: none; + font-size: 14px; +} + +.mini-cta { + padding: 8px 12px; + border-radius: 10px; + border: 1px solid color-mix(in srgb, var(--color-mid-gray) 40%, transparent); + background: color-mix(in srgb, var(--color-logo-primary) 18%, transparent); +} + +main { + padding-top: 30px; + padding-bottom: 66px; +} + +.panel { + border: 1px solid color-mix(in srgb, var(--color-mid-gray) 28%, transparent); + border-radius: 16px; + background: linear-gradient( + 180deg, + color-mix(in srgb, var(--color-logo-primary) 9%, transparent) 0%, + color-mix(in srgb, var(--color-background) 96%, transparent) 70% + ); + backdrop-filter: blur(2px); +} + +.hero { + padding: 34px; +} + +.kicker { + margin: 0; + color: color-mix(in srgb, var(--color-logo-primary) 75%, white 25%); + font-size: 12px; + font-weight: 700; + letter-spacing: 0.11em; + text-transform: uppercase; +} + +h1 { + margin: 10px 0 0; + font-size: clamp(34px, 5.8vw, 64px); + line-height: 0.98; + letter-spacing: -0.03em; +} + +.lede { + margin: 18px 0 0; + max-width: 720px; + color: color-mix(in srgb, var(--color-text) 80%, transparent); + font-size: clamp(18px, 2.2vw, 23px); +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 26px; +} + +.btn { + font-weight: 500; + border-radius: 10px; + border: 1px solid transparent; + text-decoration: none; + padding: 10px 16px; + font-size: 14px; + transition: + background-color 0.15s ease, + border-color 0.15s ease, + transform 0.12s ease; +} + +.btn:hover { + transform: translateY(-1px); +} + +.btn.primary { + color: #fff; + background: var(--color-background-ui); + border-color: var(--color-background-ui); +} + +.btn.primary:hover { + background: color-mix(in srgb, var(--color-background-ui) 84%, black 16%); + border-color: color-mix(in srgb, var(--color-background-ui) 84%, black 16%); +} + +.btn.soft { + color: var(--color-text); + background: color-mix(in srgb, var(--color-logo-primary) 18%, transparent); + border-color: transparent; +} + +.btn.soft:hover, +.btn.ghost:hover { + border-color: var(--color-logo-primary); +} + +.btn.ghost { + color: var(--color-text); + background: color-mix(in srgb, var(--color-mid-gray) 10%, transparent); + border-color: color-mix(in srgb, var(--color-mid-gray) 20%, transparent); +} + +.meta { + margin: 14px 0 0; + color: color-mix(in srgb, var(--color-text) 58%, transparent); + font-size: 13px; +} + +.grid3 { + margin-top: 16px; + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; +} + +.card { + border: 1px solid color-mix(in srgb, var(--color-mid-gray) 24%, transparent); + border-radius: 14px; + background: color-mix(in srgb, var(--color-background) 92%, #13131a 8%); + padding: 18px; +} + +.card h2 { + margin: 0; + font-size: 20px; +} + +.card p { + margin: 10px 0 0; + color: color-mix(in srgb, var(--color-text) 72%, transparent); +} + +.pricing, +.faq { + margin-top: 16px; + padding: 22px; +} + +.pricing h2, +.faq h2 { + margin: 0; + font-size: 28px; + letter-spacing: -0.02em; +} + +.price-grid { + margin-top: 14px; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; +} + +.plan { + border: 1px solid color-mix(in srgb, var(--color-mid-gray) 24%, transparent); + border-radius: 14px; + padding: 16px; + background: color-mix(in srgb, var(--color-background) 88%, #15151f 12%); +} + +.plan.pro { + border-color: color-mix(in srgb, var(--color-logo-primary) 48%, transparent); + box-shadow: inset 0 0 0 1px + color-mix(in srgb, var(--color-logo-primary) 18%, transparent); +} + +.plan-name { + margin: 0; + font-size: 12px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: color-mix(in srgb, var(--color-text) 58%, transparent); +} + +.plan-price { + margin: 9px 0; + font-size: 34px; + font-weight: 700; +} + +.plan-price span { + font-size: 14px; + color: color-mix(in srgb, var(--color-text) 62%, transparent); +} + +.plan ul { + list-style: none; + padding: 0; + margin: 0 0 14px; + display: grid; + gap: 8px; +} + +.plan li { + font-size: 14px; + color: color-mix(in srgb, var(--color-text) 78%, transparent); + padding-left: 18px; + position: relative; +} + +.plan li::before { + content: ""; + position: absolute; + width: 7px; + height: 7px; + border-radius: 999px; + left: 0; + top: 7px; + background: var(--color-logo-primary); +} + +details { + border-top: 1px solid + color-mix(in srgb, var(--color-mid-gray) 24%, transparent); + padding: 12px 0; +} + +summary { + cursor: pointer; + font-weight: 600; +} + +details p { + margin: 9px 0 0; + color: color-mix(in srgb, var(--color-text) 72%, transparent); +} + +.foot { + padding-bottom: 30px; + color: color-mix(in srgb, var(--color-text) 48%, transparent); + font-size: 12px; +} + +@media (max-width: 860px) { + .nav { + flex-direction: column; + align-items: flex-start; + } + + .menu { + flex-wrap: wrap; + } + + .hero { + padding: 24px; + } + + .grid3, + .price-grid { + grid-template-columns: 1fr; + } +} diff --git a/vercel.json b/landing/vercel.json similarity index 69% rename from vercel.json rename to landing/vercel.json index 570dd66..3ea9a5a 100644 --- a/vercel.json +++ b/landing/vercel.json @@ -6,15 +6,9 @@ "statusCode": 307 } ], - "rewrites": [ - { - "source": "/", - "destination": "/site/index.html" - } - ], "headers": [ { - "source": "/site/(.*)", + "source": "/(.*)", "headers": [ { "key": "Cache-Control", diff --git a/site/index.html b/site/index.html deleted file mode 100644 index 72552b6..0000000 --- a/site/index.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - Dictx | Private speech-to-text for serious writing - - - - - - - -
-
- Dictx - -
- -
-
-

Split Labs

-

- Talk. Edit. Ship. - Without sending your voice to the cloud. -

-

- Dictx is desktop speech-to-text for people who write all day. Local - transcription, polished text output, and pro-grade distribution. -

- -

- $29 one-time • signed binary • auto-updates • macOS / Windows / Linux -

-
- -
-
-

Private by default

-

- All core transcription runs locally on your machine. No voice data - routed through Dictx servers. -

-
-
-

Fast enough for flow state

-

- Built for real writing sessions, with quick trigger-to-text loops - and model options for speed or precision. -

-
-
-

Built for Obsidian workflows

-

- Capture, clean, and export voice notes into your vault with - metadata-rich output. -

-
-
- -
-

Choose your path

-
-
-

Free

-

$0

-
    -
  • Full GPL source code
  • -
  • Build from source
  • -
  • All core transcription features
  • -
  • Community support
  • -
- View Source -
-
-

Pro

-

$29 one-time

-
    -
  • Signed installers
  • -
  • Built-in auto-updates
  • -
  • Professional distribution
  • -
  • Funds active development
  • -
- Get Dictx Pro -
-
-
- -
-

FAQ

-
- Is Dictx still open source? -

Yes. Dictx remains GPL-licensed and free to build from source.

-
-
- What does Pro include? -

- Pro is the convenience layer: signed binaries and updater flow so - you do not have to compile manually. -

-
-
- How do updates work? -

- The app checks signed release metadata and applies updates in-app - when available. -

-
-
-
- - - - - - diff --git a/site/styles.css b/site/styles.css deleted file mode 100644 index 2ac35d5..0000000 --- a/site/styles.css +++ /dev/null @@ -1,311 +0,0 @@ -:root { - --bg: #f4efe6; - --surface: #fdf9f1; - --text: #191611; - --muted: #5d5347; - --line: #d5cab9; - --brand: #0f7d5b; - --brand-deep: #0a4f3a; - --accent: #d96a2d; -} - -* { - box-sizing: border-box; -} - -body { - margin: 0; - color: var(--text); - background: - radial-gradient(circle at 15% 10%, #fff5da 0%, transparent 28%), - radial-gradient(circle at 88% 15%, #dceee8 0%, transparent 35%), var(--bg); - font-family: "Bricolage Grotesque", sans-serif; - line-height: 1.4; -} - -.grain { - pointer-events: none; - position: fixed; - inset: 0; - opacity: 0.08; - background-image: radial-gradient(#000 0.3px, transparent 0.3px); - background-size: 3px 3px; -} - -.topbar { - max-width: 1080px; - margin: 0 auto; - padding: 20px 24px; - display: flex; - justify-content: space-between; - align-items: center; -} - -.brand { - color: var(--brand-deep); - text-decoration: none; - font-family: "Fraunces", serif; - font-size: 28px; -} - -.topbar nav { - display: flex; - align-items: center; - gap: 18px; -} - -.topbar nav a { - color: var(--text); - text-decoration: none; - font-size: 14px; -} - -.cta-mini { - padding: 8px 12px; - border-radius: 999px; - background: var(--text); - color: #fff !important; -} - -main { - max-width: 1080px; - margin: 0 auto; - padding: 18px 24px 80px; -} - -.hero { - background: linear-gradient(145deg, #fefbf4 0%, #f7efdf 55%, #f4e6d2 100%); - border: 1px solid var(--line); - border-radius: 28px; - padding: 44px; - box-shadow: 0 20px 45px rgba(48, 34, 10, 0.08); - animation: rise 500ms ease-out both; -} - -.eyebrow { - margin: 0; - color: var(--brand); - text-transform: uppercase; - letter-spacing: 0.09em; - font-size: 12px; - font-weight: 700; -} - -h1 { - margin: 10px 0 0; - font-size: clamp(36px, 6vw, 68px); - line-height: 0.98; - letter-spacing: -0.025em; -} - -h1 span { - display: block; - font-family: "Fraunces", serif; - color: var(--brand-deep); - font-size: 0.7em; - margin-top: 12px; -} - -.lead { - max-width: 720px; - margin: 22px 0 0; - font-size: clamp(18px, 2.4vw, 24px); - color: var(--muted); -} - -.hero-actions { - margin-top: 30px; - display: flex; - gap: 14px; - flex-wrap: wrap; -} - -.btn { - border: 1px solid var(--text); - border-radius: 12px; - padding: 13px 18px; - text-decoration: none; - font-weight: 700; - transition: - transform 120ms ease, - box-shadow 120ms ease; -} - -.btn:hover { - transform: translateY(-2px); -} - -.btn-primary { - background: var(--brand); - color: #fff; - border-color: var(--brand-deep); - box-shadow: 0 10px 20px rgba(15, 125, 91, 0.25); -} - -.btn-ghost { - background: transparent; - color: var(--text); -} - -.subline { - margin-top: 14px; - font-size: 13px; - color: var(--muted); -} - -.pillars { - margin-top: 26px; - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 14px; -} - -.pillars article, -.pricing, -.faq { - border: 1px solid var(--line); - border-radius: 18px; - background: var(--surface); -} - -.pillars article { - padding: 18px; -} - -.pillars h2 { - margin: 0; - font-size: 20px; -} - -.pillars p { - margin: 10px 0 0; - color: var(--muted); -} - -.pricing { - margin-top: 22px; - padding: 24px; -} - -.pricing > h2, -.faq h2 { - margin: 0; - font-family: "Fraunces", serif; - font-size: 34px; -} - -.cards { - margin-top: 16px; - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 14px; -} - -.card { - border: 1px solid var(--line); - border-radius: 14px; - padding: 18px; - background: #fff; -} - -.card.pro { - background: linear-gradient(170deg, #f1fff7 0%, #ebf5ff 100%); -} - -.card-label { - margin: 0; - text-transform: uppercase; - letter-spacing: 0.07em; - font-size: 11px; - color: var(--muted); -} - -.price { - margin: 10px 0; - font-size: 34px; - font-weight: 800; -} - -.price span { - font-size: 14px; - font-weight: 600; - color: var(--muted); -} - -.card ul { - margin: 0 0 18px; - padding: 0; - list-style: none; - display: grid; - gap: 8px; -} - -.card li { - padding-left: 20px; - position: relative; -} - -.card li::before { - content: "◆"; - color: var(--accent); - position: absolute; - left: 0; - top: 0; - font-size: 11px; -} - -.faq { - margin-top: 22px; - padding: 24px; -} - -details { - border-top: 1px solid var(--line); - padding: 14px 0; -} - -summary { - cursor: pointer; - font-weight: 700; -} - -details p { - margin: 10px 0 0; - color: var(--muted); -} - -footer { - max-width: 1080px; - margin: 0 auto; - padding: 0 24px 36px; - color: var(--muted); - font-size: 13px; -} - -@keyframes rise { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@media (max-width: 840px) { - .hero { - padding: 28px; - } - - .pillars, - .cards { - grid-template-columns: 1fr; - } - - .topbar { - flex-direction: column; - gap: 10px; - align-items: flex-start; - } -}