Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions landing/buy/success/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@
/>
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="stylesheet" href="/styles.css" />
<!-- DataFast (cookieless build), served first-party via landing/vercel.json
rewrites and injected after the load event. On this page it also
attributes the purchase: the tag reads the checkout id from the URL
and DataFast joins it to the payment via its provider connection. -->
<script id="datafast-queue">
window.datafast =
window.datafast ||
function () {
(window.datafast.q = window.datafast.q || []).push(arguments);
};
addEventListener(
"load",
function () {
var s = document.createElement("script");
s.async = true;
s.src = "/js/script.cookieless.js";
s.dataset.websiteId = "dfid_kcdGTJEa3xayul7fOPaip";
s.dataset.domain = "dictx.splitlabs.io";
document.head.appendChild(s);
},
{ once: true },
);
</script>
</head>
<body>
<div class="noise"></div>
Expand All @@ -35,11 +58,21 @@ <h1>Activate Dictx Pro</h1>

<div class="card" style="margin-top: 16px">
<h2 style="font-size: 18px">Your License Key</h2>
<p id="license-key-value" style="word-break: break-all; font-family: monospace">
If no key is shown here, copy your key from Polar customer portal or receipt email.
<p
id="license-key-value"
style="word-break: break-all; font-family: monospace"
>
If no key is shown here, copy your key from Polar customer portal or
receipt email.
</p>
<div class="actions" style="margin-top: 12px">
<button id="copy-btn" class="btn primary" type="button" disabled>
<button
id="copy-btn"
class="btn primary"
type="button"
data-fast-goal="license_key_copied"
disabled
>
Copy License Key
</button>
<a class="btn ghost" href="/">Back to Dictx</a>
Expand Down Expand Up @@ -70,7 +103,8 @@ <h2 style="font-size: 18px">Your License Key</h2>
if (!key) return;
try {
await navigator.clipboard.writeText(key);
copyStatus.textContent = "Copied. Paste it in Dictx Settings -> About.";
copyStatus.textContent =
"Copied. Paste it in Dictx Settings -> About.";
} catch (_error) {
copyStatus.textContent = "Copy failed. Select and copy manually.";
}
Expand Down
108 changes: 93 additions & 15 deletions landing/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@
href="./apple-touch-icon.png"
/>
<link rel="stylesheet" href="./styles.css" />
<!-- DataFast (cookieless build), served first-party via landing/vercel.json
rewrites and injected after the load event so a slow vendor cannot
hold page load. The queue stub keeps goals fired before it arrives. -->
<script id="datafast-queue">
window.datafast =
window.datafast ||
function () {
(window.datafast.q = window.datafast.q || []).push(arguments);
};
addEventListener(
"load",
function () {
var s = document.createElement("script");
s.async = true;
s.src = "/js/script.cookieless.js";
s.dataset.websiteId = "dfid_kcdGTJEa3xayul7fOPaip";
s.dataset.domain = "dictx.splitlabs.io";
document.head.appendChild(s);
},
{ once: true },
);
</script>
</head>
<body>
<div class="noise"></div>
Expand All @@ -31,14 +53,21 @@
<nav class="menu" aria-label="Primary">
<a href="#features">Features</a>
<a href="#pricing">Pricing</a>
<a href="/api/download/macos">Download DMG</a>
<a
href="/api/download/macos"
data-fast-goal="download_dmg"
data-fast-goal-location="nav"
>Download DMG</a
>
<a
href="https://github.com/splitlabs/dictx"
target="_blank"
rel="noreferrer"
data-fast-goal="github_click"
data-fast-goal-location="nav"
>GitHub</a
>
<a class="mini-cta" href="/buy">Get Pro</a>
<a class="mini-cta" href="/buy" data-buy-location="nav">Get Pro</a>
</nav>
</header>

Expand All @@ -56,8 +85,14 @@ <h1>Transcription you can trust in real work.</h1>
<li>Signed Pro builds</li>
</ul>
<div class="actions">
<a class="btn primary" href="/buy">Buy Dictx Pro</a>
<a class="btn soft" href="/api/download/macos"
<a class="btn primary" href="/buy" data-buy-location="hero"
>Buy Dictx Pro</a
>
<a
class="btn soft"
href="/api/download/macos"
data-fast-goal="download_dmg"
data-fast-goal-location="hero"
>Download Latest macOS DMG</a
>
</div>
Expand Down Expand Up @@ -96,7 +131,11 @@ <h2>Obsidian-ready output</h2>
</article>
</section>

<section id="pricing" class="panel pricing">
<section
id="pricing"
class="panel pricing"
data-fast-scroll="scroll_pricing"
>
<h2>Free or Pro</h2>
<p class="pricing-lead">
Free stays powerful for daily use. Pro removes setup friction and
Expand All @@ -118,21 +157,27 @@ <h2>Free or Pro</h2>
href="https://github.com/splitlabs/dictx"
target="_blank"
rel="noreferrer"
data-fast-goal="github_click"
data-fast-goal-location="pricing"
>View source</a
>
</article>
<article class="plan pro">
<p class="plan-name">Pro</p>
<p class="plan-price">$29 <span>one-time</span></p>
<p class="plan-offer">Early access: first 100 installs get Pro free</p>
<p class="plan-offer">
Early access: first 100 installs get Pro free
</p>
<ul>
<li>Signed desktop binaries</li>
<li>In-app auto-updater</li>
<li>Faster install for non-technical users</li>
<li>Professional checkout</li>
<li>Priority support contact</li>
</ul>
<a class="btn primary" href="/buy">Get Dictx Pro</a>
<a class="btn primary" href="/buy" data-buy-location="pricing"
>Get Dictx Pro</a
>
</article>
</div>
<div class="matrix-wrap" aria-label="Feature comparison">
Expand Down Expand Up @@ -185,7 +230,7 @@ <h2>Free or Pro</h2>
</div>
</section>

<section class="panel faq">
<section class="panel faq" data-fast-scroll="scroll_faq">
<h2>FAQ</h2>
<details open>
<summary>Is Dictx still open source?</summary>
Expand All @@ -194,17 +239,16 @@ <h2>FAQ</h2>
<details>
<summary>What does Pro actually add?</summary>
<p>
Pro is the convenience layer: signed installers, in-app updates,
and priority support. Free still includes the full local dictation
Pro is the convenience layer: signed installers, in-app updates, and
priority support. Free still includes the full local dictation
workflow.
</p>
</details>
<details>
<summary>How does the first-100 free Pro claim work?</summary>
<p>
The app claims it automatically on first activation. If your
install lands in the first 100, Pro is enabled instantly at no
cost.
The app claims it automatically on first activation. If your install
lands in the first 100, Pro is enabled instantly at no cost.
</p>
</details>
<details>
Expand Down Expand Up @@ -235,8 +279,16 @@ <h2>FAQ</h2>
signed installers and one-click updates.
</p>
<div class="actions">
<a class="btn primary" href="/buy">Get Dictx Pro</a>
<a class="btn soft" href="/api/download/macos">Download DMG</a>
<a class="btn primary" href="/buy" data-buy-location="final"
>Get Dictx Pro</a
>
<a
class="btn soft"
href="/api/download/macos"
data-fast-goal="download_dmg"
data-fast-goal-location="final"
>Download DMG</a
>
</div>
</div>
</section>
Expand All @@ -250,6 +302,32 @@ <h2>FAQ</h2>
document.getElementById("year").textContent = String(
new Date().getFullYear(),
);

// Buy clicks leave the page for checkout at once, and DataFast posts
// goals with a plain XHR that the browser cancels on navigation. So the
// goal is sent here (not via data-fast-goal, which would double-count)
// and a plain click waits briefly before following /buy. Modified
// clicks open a new tab and need no delay.
document.addEventListener("click", function (event) {
var link = event.target.closest("a[data-buy-location]");
if (!link) return;
window.datafast("buy_pro_click", {
location: link.getAttribute("data-buy-location"),
});
if (
event.defaultPrevented ||
event.button !== 0 ||
event.metaKey ||
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
setTimeout(function () {
window.location.href = link.href;
}, 250);
});
</script>
</body>
</html>
35 changes: 35 additions & 0 deletions landing/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { trackAICrawlerRequest } from "@datafast/ai-crawl";

// Provided by the Vercel runtime; declared so type-checking the middleware
// does not require @types/node in this dependency-free static project.
declare const process: { env: Record<string, string | undefined> };

/**
* DataFast bot traffic (datafa.st/docs/bot-traffic-tracking) as Vercel
* Routing Middleware for this static project.
*
* A local user-agent check on document requests; only known AI crawlers
* produce one background POST, scheduled with context.waitUntil and never
* awaited, so humans never trigger a network call and no response waits on
* DataFast. The request always passes through to the static file or function
* untouched. No-op until DATAFAST_WEBSITE_ID is set.
*/
// Edge runtime on purpose. Vercel warns that Edge is deprecated for Routing
// Middleware, but on this static "Other" project the Node.js runtime served
// every matched page as a 500 on preview, while Edge served 200.
export const config = {
matcher: [
"/((?!api/|js/|.*\\.(?:png|jpe?g|gif|svg|webp|avif|ico|css|js|map|woff2?|ttf)$).*)",
],
};

export default function middleware(
request: Request,
context: { waitUntil(promise: Promise<unknown>): void },
) {
const websiteId = process.env.DATAFAST_WEBSITE_ID?.trim();
if (websiteId) trackAICrawlerRequest(request, context, { websiteId });
// Pass through untouched. This is exactly what next() from @vercel/functions
// returns, so the pass-through does not depend on runtime defaults.
return new Response(null, { headers: { "x-middleware-next": "1" } });
}
6 changes: 5 additions & 1 deletion landing/package.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"type": "commonjs"
"type": "commonjs",
"private": true,
"dependencies": {
"@datafast/ai-crawl": "1.0.9"
}
}
10 changes: 10 additions & 0 deletions landing/vercel.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
{
"rewrites": [
{
"source": "/js/script.cookieless.js",
"destination": "https://datafa.st/js/script.cookieless.js"
},
{
"source": "/api/events",
"destination": "https://datafa.st/api/events"
}
],
"redirects": [
{
"source": "/buy",
Expand Down
Loading
Loading