feat(server): build axum web server for licensing, landing page, and updates
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Page Not Found — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.error-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.error-message p {
|
||||
margin-bottom: 0;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.error-hint {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.error-actions a {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text-on);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.error-actions a:hover {
|
||||
background: var(--color-accent-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-container">
|
||||
<div class="error-icon">∅</div>
|
||||
<h1>Page Not Found</h1>
|
||||
|
||||
<div class="error-message">
|
||||
<p>
|
||||
This page has been cleaned from existence. It was probably full of
|
||||
tracking parameters.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="error-hint">
|
||||
The URL you visited doesn't exist, or may have been moved.
|
||||
</p>
|
||||
|
||||
<div class="error-actions">
|
||||
<a href="/">Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,84 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Something Went Wrong — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.error-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.error-message p {
|
||||
margin-bottom: 0;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.error-hint {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.error-actions a {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text-on);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.error-actions a:hover {
|
||||
background: var(--color-accent-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-container">
|
||||
<div class="error-icon">⚠</div>
|
||||
<h1>Something Went Wrong</h1>
|
||||
|
||||
<div class="error-message">
|
||||
<p>
|
||||
Our clipboard cleaner hit an unexpected bump. This has been logged
|
||||
and we're looking into it.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="error-hint">
|
||||
If this keeps happening, please
|
||||
<a href="mailto:{{ email }}">contact support</a>.
|
||||
</p>
|
||||
|
||||
<div class="error-actions">
|
||||
<a href="/">Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,184 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/png" href="/static/favicon.png" />
|
||||
<title>{% block title %}CleanCopy{% endblock %}</title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "CascadiaCode";
|
||||
src: url("/static/fonts/CaskaydiaCoveNerdFont-Regular.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "CascadiaCode";
|
||||
src: url("/static/fonts/CaskaydiaCoveNerdFont-Bold.ttf") format("truetype");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:root {
|
||||
--color-bg-base: #1c2128;
|
||||
--color-bg-elevated: #22272e;
|
||||
--color-border-subtle: #2d333b;
|
||||
--color-border-muted: #444c56;
|
||||
--color-text-primary: #adbac7;
|
||||
--color-text-secondary: #768390;
|
||||
--color-text-emphasis: #cdd9e5;
|
||||
--color-accent: #b39cd0;
|
||||
--color-accent-hover: rgba(179, 156, 208, 0.85);
|
||||
--color-accent-text-on: #1c2128;
|
||||
--color-success: #4ade80;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: "CascadiaCode", monospace;
|
||||
background: var(--color-bg-base);
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2rem;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
ol {
|
||||
padding-left: 2.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.back {
|
||||
display: inline-block;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.topnav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.topnav-brand {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: var(--color-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.topnav-links a {
|
||||
color: var(--color-text-primary);
|
||||
text-decoration: none;
|
||||
margin-left: 1.5rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.topnav-links a:hover {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 2rem;
|
||||
padding: 1rem 0;
|
||||
border-top: 1px solid var(--color-border-subtle);
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: var(--color-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav class="topnav">
|
||||
<a href="/" class="topnav-brand">CleanCopy</a>
|
||||
<div class="topnav-links">
|
||||
<a href="/docs">Docs</a>
|
||||
</div>
|
||||
</nav>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
<div><a href="/terms">Terms</a> · <a href="/refunds">Refunds</a> · <a href="/privacy">Privacy</a></div>
|
||||
<p>© 2026 CleanCopy. All rights reserved.</p>
|
||||
</footer>
|
||||
</div>
|
||||
<!-- Simple Analytics - 100% privacy-first analytics -->
|
||||
<script async src="https://scripts.simpleanalyticscdn.com/latest.js"></script>
|
||||
<noscript><img src="https://queue.simpleanalyticscdn.com/noscript.gif" alt="" referrerpolicy="no-referrer-when-downgrade" /></noscript>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,137 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Documentation — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
code {
|
||||
background: var(--color-border-subtle);
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background: var(--color-border-subtle);
|
||||
border: 1px solid var(--color-border-muted);
|
||||
border-radius: 4px;
|
||||
padding: 0.1rem 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<a class="back" href="/">← Home</a>
|
||||
<h1>CleanCopy Documentation</h1>
|
||||
|
||||
<div class="section">
|
||||
<h2>What is CleanCopy?</h2>
|
||||
<p>
|
||||
CleanCopy is a lightweight clipboard cleaning tool for Windows. When
|
||||
triggered, it instantly sanitizes the text currently in your clipboard
|
||||
— stripping trackers, normalizing typography, and removing invisible
|
||||
characters.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Installation</h2>
|
||||
<ol>
|
||||
<li>
|
||||
Complete your purchase on the
|
||||
<a href="/">homepage</a>.
|
||||
</li>
|
||||
<li>
|
||||
Check your receipt email for the download link and your payment ID.
|
||||
</li>
|
||||
<li>
|
||||
Download and run the installer. CleanCopy will start automatically.
|
||||
</li>
|
||||
<li>The CleanCopy icon will appear in your system tray.</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>How to Use</h2>
|
||||
<p>
|
||||
Copy text to your clipboard as usual. When you're ready to clean it:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Press <kbd>Ctrl</kbd> + <kbd>C</kbd> twice quickly (default
|
||||
shortcut).
|
||||
</li>
|
||||
<li>CleanCopy processes the clipboard text in place.</li>
|
||||
<li>Paste the cleaned text wherever you need it.</li>
|
||||
</ol>
|
||||
<p>
|
||||
That's it — there's no window to interact with. CleanCopy works
|
||||
silently in the background.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>What Gets Cleaned</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Tracking parameters</strong> — Removes
|
||||
<code>utm_source</code>, <code>utm_medium</code>,
|
||||
<code>gclid</code>, <code>fbclid</code>, and other marketing
|
||||
trackers from URLs while preserving functional query parameters.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Smart quotes & dashes</strong> — Converts curly quotes
|
||||
(<code>" "</code> <code>' '</code>) to straight quotes and
|
||||
em/en-dashes to hyphens.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Line breaks</strong> — Joins single-newline wraps from chat
|
||||
apps and emails into continuous lines, while preserving paragraph
|
||||
breaks.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Invisible characters</strong> — Removes zero-width spaces,
|
||||
null bytes, and other invisible Unicode characters.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Configuration</h2>
|
||||
<p>
|
||||
Open the settings window from the system tray icon or by pressing
|
||||
<kbd>Ctrl</kbd> + <kbd>C</kbd> while no text is selected. From there
|
||||
you can:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Toggle individual cleaning rules on or off.</li>
|
||||
<li>Add custom URL tracking parameters to strip.</li>
|
||||
<li>Change the activation shortcut.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Troubleshooting</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Shortcut doesn't work</strong> — Another app may be using
|
||||
the same shortcut. Try changing it in Settings.
|
||||
</li>
|
||||
<li>
|
||||
<strong>CleanCopy won't start</strong> — Make sure it's not blocked
|
||||
by your antivirus. Add it to your allowlist if needed.
|
||||
</li>
|
||||
<li>
|
||||
<strong>License not activating</strong> — Ensure you have a stable
|
||||
internet connection and that your payment ID (starting with
|
||||
<code>pi_</code>) is correct.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,143 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}CleanCopy — Clipboard Cleaning for Windows{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.container {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.hero-logo {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.hero .tagline {
|
||||
font-size: 1.2rem;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.features {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.feature {
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.feature:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.feature h3 {
|
||||
color: var(--color-accent);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.pricing {
|
||||
margin: 2.5rem 0;
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.pricing .price {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.pricing .detail {
|
||||
color: var(--color-text-primary);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.cta {
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cta a {
|
||||
display: inline-block;
|
||||
padding: 1rem 2rem;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text-on);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.cta a:hover {
|
||||
background: var(--color-accent-hover);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="hero">
|
||||
<img src="/static/logo.png" alt="CleanCopy" class="hero-logo" />
|
||||
<h1>CleanCopy</h1>
|
||||
<p class="tagline">
|
||||
Lightweight clipboard cleaning for Windows. Silently sanitizes your
|
||||
clipboard text on trigger.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="pricing">
|
||||
<div class="price">{{ price }}</div>
|
||||
<div class="detail">
|
||||
One-time purchase · Lifetime license · Unlimited devices
|
||||
</div>
|
||||
<div class="cta">
|
||||
<a href="/api/checkout">Buy CleanCopy →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="features">
|
||||
<div class="feature">
|
||||
<h3>Tracking Parameter Stripper</h3>
|
||||
<p>
|
||||
Removes marketing trackers (utm_*, gclid, fbclid, etc.) from URLs
|
||||
while keeping functional query arguments.
|
||||
</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h3>Smart Quotes & Dash Fixer</h3>
|
||||
<p>
|
||||
Converts curly quotes and em/en-dashes to standard straight quotes
|
||||
and hyphens.
|
||||
</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h3>Line-Break Normalizer</h3>
|
||||
<p>
|
||||
Joins single-newline wraps from chat apps into continuous lines
|
||||
while preserving paragraphs.
|
||||
</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h3>Invisible Character Cleanup</h3>
|
||||
<p>
|
||||
Removes zero-width spaces, null bytes, and other invisible Unicode
|
||||
characters.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,113 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Privacy Policy — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.updated {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<a class="back" href="/">← Home</a>
|
||||
<h1>Privacy Policy</h1>
|
||||
<p class="updated">Last updated: {{ date }}</p>
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
CleanCopy is a clipboard cleaning tool that runs entirely on your
|
||||
Windows PC. We value your privacy and have designed both our website and
|
||||
software to collect only what is necessary.
|
||||
</p>
|
||||
|
||||
<h2>Website Analytics</h2>
|
||||
<p>
|
||||
This website uses
|
||||
<a href="https://simpleanalytics.com" target="_blank">Simple Analytics</a>, a
|
||||
privacy-friendly analytics service. Simple Analytics collects:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Page views and referrer information</li>
|
||||
<li>Browser type and device type</li>
|
||||
<li>Country-level geographic location (not precise location)</li>
|
||||
</ul>
|
||||
<p>
|
||||
Simple Analytics does <strong>not</strong> use cookies, does not track
|
||||
individual users across sites, and does not collect personal
|
||||
information. No consent banner is required because no personal data is
|
||||
collected. See the
|
||||
<a href="https://simpleanalytics.com/privacy" target="_blank">Simple Analytics privacy
|
||||
policy</a>
|
||||
for details.
|
||||
</p>
|
||||
|
||||
<h2>License Activation</h2>
|
||||
<p>
|
||||
When you activate CleanCopy, the app sends the following to our
|
||||
activation server:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Payment ID</strong> — the <code>pi_...</code> identifier from
|
||||
your Stripe receipt email
|
||||
</li>
|
||||
<li>
|
||||
<strong>Hardware ID (HWID)</strong> — a SHA-256 hash derived from your
|
||||
Windows machine identifiers
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
This data is used solely to verify your purchase and issue a signed
|
||||
license token. The HWID is stored in the license token to prevent
|
||||
license sharing. We do not collect your name, email address, IP address,
|
||||
or any other personal information during activation.
|
||||
</p>
|
||||
|
||||
<h2>License Storage</h2>
|
||||
<p>
|
||||
Your signed license token is stored locally on your device at
|
||||
<code><app_config_dir>/license.lic</code>. This file never leaves
|
||||
your device. It is a digitally signed JSON payload containing your
|
||||
payment ID, HWID, and license metadata.
|
||||
</p>
|
||||
|
||||
<h2>Payments</h2>
|
||||
<p>
|
||||
All payment processing is handled by
|
||||
<a href="https://stripe.com" target="_blank">Stripe</a>
|
||||
as the merchant of record. CleanCopy never sees, stores, or has access
|
||||
to your credit card number, bank details, or other payment credentials.
|
||||
Stripe's own
|
||||
<a href="https://stripe.com/privacy" target="_blank">privacy policy</a>
|
||||
governs how your payment information is handled.
|
||||
</p>
|
||||
|
||||
<h2>Data Sharing</h2>
|
||||
<p>
|
||||
We do not sell, trade, or share your data with third parties except as
|
||||
described in this policy (Simple Analytics for website analytics, Stripe
|
||||
for payment processing).
|
||||
</p>
|
||||
|
||||
<h2>Cookies</h2>
|
||||
<p>
|
||||
This website does not use cookies. Simple Analytics operates without
|
||||
cookies.
|
||||
</p>
|
||||
|
||||
<h2>Changes to This Policy</h2>
|
||||
<p>
|
||||
We may update this Privacy Policy from time to time. Changes will be
|
||||
reflected on this page with an updated date.
|
||||
</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>
|
||||
Questions about this Privacy Policy?
|
||||
<a href="mailto:{{ email }}">Contact us</a>.
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,76 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Refund Policy — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.updated {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<a class="back" href="/">← Home</a>
|
||||
<h1>Refund Policy</h1>
|
||||
<p class="updated">Last updated: {{ date }}</p>
|
||||
|
||||
<h2>30-Day Money-Back Guarantee</h2>
|
||||
<p>
|
||||
We want you to be satisfied with CleanCopy. If you're not happy with
|
||||
your purchase, you can request a full refund within 30 days of your
|
||||
purchase date.
|
||||
</p>
|
||||
|
||||
<div class="highlight">
|
||||
<strong>How to request a refund:</strong>
|
||||
<p style="margin-top: 0.5rem; margin-bottom: 0">
|
||||
Email
|
||||
<a href="mailto:{{ email }}">{{ email }}</a> with
|
||||
your payment ID (the <code>pi_...</code> value from your receipt
|
||||
email) and a brief reason for the refund. We'll process it within 2–3
|
||||
business days.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2>What happens after a refund</h2>
|
||||
<ul>
|
||||
<li>Your license will be deactivated on our servers.</li>
|
||||
<li>
|
||||
CleanCopy will stop working on your device after the next license
|
||||
check.
|
||||
</li>
|
||||
<li>You must delete the software and all copies from your devices.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Exceptions</h2>
|
||||
<p>Refunds may be denied in the following cases:</p>
|
||||
<ul>
|
||||
<li>Requests made more than 30 days after purchase.</li>
|
||||
<li>Refund requests for the same purchase made previously.</li>
|
||||
<li>Requests from users who have violated the Terms of Service.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Processing</h2>
|
||||
<p>
|
||||
Refunds are processed through Stripe to the original payment method.
|
||||
Depending on your bank, it may take 5–10 business days for the refund to
|
||||
appear on your statement.
|
||||
</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>
|
||||
Questions about refunds?
|
||||
<a href="mailto:{{ email }}">Contact us</a>.
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,186 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Payment Successful — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.success-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
text-align: left;
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.instructions h3 {
|
||||
color: var(--color-accent);
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.instructions ol {
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
|
||||
.instructions li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.instructions code {
|
||||
background: var(--color-border-subtle);
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.note {
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
font-size: 0.9rem;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.note strong {
|
||||
color: var(--color-text-emphasis);
|
||||
}
|
||||
|
||||
.download {
|
||||
text-align: center;
|
||||
background: var(--color-bg-elevated);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.download h3 {
|
||||
color: var(--color-accent);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.download .version {
|
||||
color: var(--color-text-primary);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.download .version strong {
|
||||
color: var(--color-text-emphasis);
|
||||
}
|
||||
|
||||
.download-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: var(--color-accent);
|
||||
color: var(--color-accent-text-on);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
min-width: 280px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.download-btn:hover {
|
||||
background: var(--color-accent-hover);
|
||||
}
|
||||
|
||||
.download-btn-secondary {
|
||||
background: transparent;
|
||||
color: var(--color-accent);
|
||||
border: 1px solid var(--color-accent);
|
||||
}
|
||||
|
||||
.download-btn-secondary:hover {
|
||||
background: var(--color-bg-elevated);
|
||||
border-color: var(--color-accent-hover);
|
||||
}
|
||||
|
||||
.download-hint {
|
||||
font-size: 0.8rem;
|
||||
font-weight: normal;
|
||||
opacity: 0.8;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.download .placeholder {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="success-container">
|
||||
<div class="checkmark">✓</div>
|
||||
<h1>Payment Successful</h1>
|
||||
<p>Thank you for purchasing CleanCopy!</p>
|
||||
</div>
|
||||
|
||||
<div class="download">
|
||||
<h3>Download CleanCopy</h3>
|
||||
{% if has_download %}
|
||||
<p class="version">Latest version: <strong>{{ download_version }}</strong></p>
|
||||
<div class="download-options">
|
||||
<a href="{{ exe_url }}" class="download-btn">
|
||||
Download for Windows (.exe)
|
||||
<span class="download-hint">Portable — no installation required</span>
|
||||
</a>
|
||||
{% if has_msi %}
|
||||
<a href="{{ msi_url }}" class="download-btn download-btn-secondary">
|
||||
Download Installer (.msi)
|
||||
<span class="download-hint">Traditional Windows installer</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="placeholder">No releases available yet. Check back soon or contact support.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="instructions">
|
||||
<h3>How to activate your license</h3>
|
||||
<ol>
|
||||
<li>Open CleanCopy on your Windows PC</li>
|
||||
<li>Go to the <strong>License</strong> tab</li>
|
||||
<li>
|
||||
Find the payment ID in your receipt email — it starts with
|
||||
<code>pi_</code>
|
||||
</li>
|
||||
<li>Paste it into the license key field</li>
|
||||
<li>Click <strong>Activate</strong></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="note">
|
||||
<strong>Can't find your payment ID?</strong> Check your email inbox (and
|
||||
spam folder) for the receipt from CleanCopy. The payment ID is in the
|
||||
receipt subject line or body.
|
||||
</div>
|
||||
|
||||
<p>Need help? <a href="mailto:{{ email }}">Contact support</a></p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,136 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Terms of Service — CleanCopy{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
.updated {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<a class="back" href="/">← Home</a>
|
||||
<h1>Terms of Service</h1>
|
||||
<p class="updated">Last updated: {{ date }}</p>
|
||||
|
||||
<h2>1. Acceptance of Terms</h2>
|
||||
<p>
|
||||
By purchasing, downloading, or using CleanCopy ("the Software"), you
|
||||
agree to be bound by these Terms of Service. If you do not agree, do not
|
||||
use the Software.
|
||||
</p>
|
||||
|
||||
<h2>2. License Grant</h2>
|
||||
<p>
|
||||
CleanCopy is licensed, not sold. Upon successful payment, you are
|
||||
granted a non-exclusive, non-transferable, perpetual license to install
|
||||
and use the Software on devices you own or control, for personal or
|
||||
commercial purposes.
|
||||
</p>
|
||||
|
||||
<h2>3. Usage Restrictions</h2>
|
||||
<ul>
|
||||
<li>You may not redistribute, sell, or sublicense the Software.</li>
|
||||
<li>
|
||||
You may not reverse engineer, decompile, or disassemble the Software.
|
||||
</li>
|
||||
<li>You may not use the Software for any unlawful purpose.</li>
|
||||
<li>
|
||||
You may not remove or alter any proprietary notices or labels on the
|
||||
Software.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>4. Intellectual Property</h2>
|
||||
<p>
|
||||
The Software and all intellectual property rights therein are and remain
|
||||
the exclusive property of CleanCopy. These Terms do not grant you any
|
||||
rights to use CleanCopy's trademarks, logos, or other brand features.
|
||||
</p>
|
||||
|
||||
<h2>5. Payment</h2>
|
||||
<p>
|
||||
CleanCopy is a one-time purchase. Payment is processed securely through
|
||||
<a href="https://stripe.com" target="_blank">Stripe</a>, which
|
||||
acts as the merchant of record for all transactions. This means:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Stripe is the seller of record and is responsible for processing your
|
||||
payment, handling disputes, and managing chargebacks.
|
||||
</li>
|
||||
<li>
|
||||
CleanCopy never sees, stores, or has access to your credit card
|
||||
number, bank details, or other payment credentials.
|
||||
</li>
|
||||
<li>
|
||||
Stripe's own
|
||||
<a href="https://stripe.com/legal/ssa" target="_blank">Stripe Services Agreement</a>
|
||||
and
|
||||
<a href="https://stripe.com/privacy" target="_blank">Privacy Policy</a>
|
||||
govern how your payment information is collected and processed.
|
||||
</li>
|
||||
<li>
|
||||
You are responsible for any taxes associated with your purchase.
|
||||
Prices are in USD unless otherwise stated.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>6. Updates</h2>
|
||||
<p>
|
||||
We may release updates to the Software from time to time. Your license
|
||||
includes access to updates for the version of CleanCopy you purchased.
|
||||
We reserve the right to modify or discontinue features in future
|
||||
versions.
|
||||
</p>
|
||||
|
||||
<h2>7. Disclaimer of Warranty</h2>
|
||||
<p>
|
||||
The Software is provided "as is" without warranty of any kind, express
|
||||
or implied, including but not limited to the warranties of
|
||||
merchantability, fitness for a particular purpose, and noninfringement.
|
||||
We do not warrant that the Software will be uninterrupted, error-free,
|
||||
or free of harmful components.
|
||||
</p>
|
||||
|
||||
<h2>8. Limitation of Liability</h2>
|
||||
<p>
|
||||
To the maximum extent permitted by law, CleanCopy shall not be liable
|
||||
for any indirect, incidental, special, consequential, or punitive
|
||||
damages, or any loss of profits or revenue, whether incurred directly or
|
||||
indirectly, or any loss of data, use, goodwill, or other intangible
|
||||
losses resulting from your use of the Software.
|
||||
</p>
|
||||
|
||||
<h2>9. Termination</h2>
|
||||
<p>
|
||||
Your license is effective until terminated. We may terminate your
|
||||
license at any time if you fail to comply with these Terms. Upon
|
||||
termination, you must cease all use of the Software and destroy all
|
||||
copies.
|
||||
</p>
|
||||
|
||||
<h2>10. Governing Law</h2>
|
||||
<p>
|
||||
These Terms shall be governed by and construed in accordance with the
|
||||
laws of the United States, without regard to conflict of law principles.
|
||||
</p>
|
||||
|
||||
<h2>11. Changes to Terms</h2>
|
||||
<p>
|
||||
We reserve the right to update these Terms at any time. Continued use of
|
||||
the Software after changes constitutes acceptance of the new Terms. We
|
||||
will notify users of material changes through the Software or our
|
||||
website.
|
||||
</p>
|
||||
|
||||
<h2>12. Contact</h2>
|
||||
<p>
|
||||
Questions about these Terms?
|
||||
<a href="mailto:{{ email }}">Contact us</a>.
|
||||
</p>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user