This commit is contained in:
pj committed 2026-06-22 16:42:03 -04:00
1 parent fb6f14165f
commit 9acb3aae3c
5 files changed
+305 -15

No files matched your search

+31 -9
View File
@@ -17,16 +17,16 @@ const cols = [
{ {
title: "Product", title: "Product",
links: [ links: [
{ label: "Features", href: "#features" }, { label: "Features", href: "/#features" },
{ label: "Publishing", href: "#publish" }, { label: "Publishing", href: "/#publish" },
{ label: "Compare", href: "#compare" }, { label: "Compare", href: "/#compare" },
{ label: "Pricing", href: "#pricing" }, { label: "Pricing", href: "/#pricing" },
], ],
}, },
{ {
title: "Help", title: "Help",
links: [ links: [
{ label: "Questions", href: "#faq" }, { label: "Questions", href: "/#faq" },
{ label: "Email us", href: `mailto:${site.supportEmail}` }, { label: "Email us", href: `mailto:${site.supportEmail}` },
], ],
}, },
@@ -50,14 +50,14 @@ const cols = [
<p class="footer__title">{col.title}</p> <p class="footer__title">{col.title}</p>
<ul> <ul>
{col.links.map((l) => { {col.links.map((l) => {
const isAnchor = l.href.startsWith("#") || l.href.startsWith("mailto:"); const isExternal = l.href.startsWith("http");
return ( return (
<li> <li>
<a <a
href={l.href} href={l.href}
data-download-os={(l as { os?: string }).os} data-download-os={(l as { os?: string }).os}
target={isAnchor ? undefined : "_blank"} target={isExternal ? "_blank" : undefined}
rel={isAnchor ? undefined : "noopener"} rel={isExternal ? "noopener" : undefined}
> >
{l.label} {l.label}
</a> </a>
@@ -73,6 +73,10 @@ const cols = [
<div class="container footer__base"> <div class="container footer__base">
<span>© {site.name}. Built with <span class="heart">♥</span> in NYC</span> <span>© {site.name}. Built with <span class="heart">♥</span> in NYC</span>
<nav class="footer__legal" aria-label="Legal">
<a href="/privacy">Privacy</a>
<a href="/terms">Terms</a>
</nav>
</div> </div>
</footer> </footer>
@@ -136,10 +140,23 @@ const cols = [
.footer__base { .footer__base {
padding-top: 22px; padding-top: 22px;
border-top: 1px solid var(--line); border-top: 1px solid var(--line);
text-align: center; display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
font-size: 0.82rem; font-size: 0.82rem;
color: var(--ink-faint); color: var(--ink-faint);
} }
.footer__legal {
display: flex;
gap: 18px;
}
.footer__legal a {
color: var(--ink-faint);
}
.footer__legal a:hover {
color: var(--ink);
}
.heart { .heart {
color: var(--danger); color: var(--danger);
} }
@@ -153,5 +170,10 @@ const cols = [
.footer__cols { .footer__cols {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
.footer__base {
flex-direction: column;
gap: 12px;
text-align: center;
}
} }
</style> </style>
+6 -6
View File
@@ -11,15 +11,15 @@ import Logo from "./Logo.astro";
</a> </a>
<nav class="nav__links" aria-label="Primary"> <nav class="nav__links" aria-label="Primary">
<a href="#features">Features</a> <a href="/#features">Features</a>
<a href="#publish">Publishing</a> <a href="/#publish">Publishing</a>
<a href="#compare">Compare</a> <a href="/#compare">Compare</a>
<a href="#pricing">Pricing</a> <a href="/#pricing">Pricing</a>
<a href="#faq">Questions</a> <a href="/#faq">Questions</a>
</nav> </nav>
<div class="nav__actions"> <div class="nav__actions">
<a class="btn nav__cta" href="#download"> <a class="btn nav__cta" href="/#download">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true">
<path d="M12 3v12m0 0 4-4m-4 4-4-4M5 21h14" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M12 3v12m0 0 4-4m-4 4-4-4M5 21h14" stroke-linecap="round" stroke-linejoin="round"></path>
</svg> </svg>
+100
View File
@@ -0,0 +1,100 @@
---
import Base from "./Base.astro";
import Nav from "../components/Nav.astro";
import Footer from "../components/Footer.astro";
import { site } from "../data/site";
interface Props {
title: string;
updated: string;
description?: string;
}
const { title, updated, description } = Astro.props;
---
<Base title={`${title} · ${site.name}`} description={description}>
<Nav />
<main class="legal">
<div class="container legal__inner">
<header class="legal__head">
<p class="eyebrow">Legal</p>
<h1>{title}</h1>
<p class="legal__updated">Last updated {updated}</p>
</header>
<div class="legal__prose">
<slot />
</div>
</div>
</main>
<Footer />
</Base>
<style>
.legal {
padding-block: clamp(48px, 7vw, 96px);
}
.legal__inner {
max-width: 760px;
}
.legal__head {
padding-bottom: clamp(28px, 4vw, 44px);
margin-bottom: clamp(28px, 4vw, 44px);
border-bottom: 1px solid var(--line);
}
.legal__head h1 {
font-family: var(--font-book);
font-weight: 560;
letter-spacing: -0.012em;
line-height: 1.08;
font-size: clamp(2.1rem, 1.4rem + 2.8vw, 3.2rem);
}
.legal__updated {
margin-top: 16px;
color: var(--ink-faint);
font-size: 0.92rem;
}
.legal__prose {
color: var(--ink-soft);
font-size: 1.04rem;
line-height: 1.7;
}
.legal__prose :global(h2) {
font-size: clamp(1.3rem, 1.05rem + 0.9vw, 1.6rem);
color: var(--ink);
margin: 44px 0 14px;
}
.legal__prose :global(h2:first-child) {
margin-top: 0;
}
.legal__prose :global(p) {
margin: 0 0 16px;
}
.legal__prose :global(ul) {
margin: 0 0 16px;
padding-left: 22px;
display: flex;
flex-direction: column;
gap: 8px;
}
.legal__prose :global(li) {
padding-left: 4px;
}
.legal__prose :global(li::marker) {
color: var(--ink-faint);
}
.legal__prose :global(strong) {
color: var(--ink);
font-weight: 600;
}
.legal__prose :global(a) {
color: var(--ink);
text-decoration: underline;
text-underline-offset: 3px;
text-decoration-color: var(--line-strong);
}
.legal__prose :global(a:hover) {
text-decoration-color: var(--ink);
}
</style>
+76
View File
@@ -0,0 +1,76 @@
---
import Legal from "../layouts/Legal.astro";
import { site } from "../data/site";
---
<Legal
title="Privacy Policy"
updated="June 22, 2026"
description={`How ${site.name} handles your data. The short version: your book never leaves your machine, and we keep no copy.`}
>
<h2>The short version</h2>
<p>
Margin is an offline writing studio that runs on your own computer. Your book and everything
you write stay on your device. We never receive a copy, and nothing you write is sent away to
be read or stored by us. This page explains the few places where data is involved, so you know
exactly what happens and what does not.
</p>
<h2>What stays on your device</h2>
<p>
Your manuscript, your spelling and grammar checks, your fonts and book setup, and every print
and ebook export all happen locally on your machine. None of this requires an account, a login,
or an internet connection, and none of it passes through our servers.
</p>
<h2>No account, no tracking</h2>
<p>
You do not need to sign up, log in, or give us an email address to write with Margin. This
website does not use tracking cookies, advertising pixels, or third-party analytics. The only
thing the site stores in your browser is your light or dark theme preference, kept locally so
the page looks the way you left it.
</p>
<h2>Downloads and updates</h2>
<p>
Margin is distributed through GitHub Releases. When you download the app, or when the app checks
for a new version to keep itself up to date, a request is made to GitHub to fetch the latest
release. As with any web request, GitHub can see your IP address for that request, handled under
GitHub's own privacy policy. We do not add any tracking of our own to these requests.
</p>
<h2>Optional backup to your Google Drive</h2>
<p>
Margin can save a backup of your book to your own Google Drive, but only if you turn it on. When
you do, you connect your own Google account, and the backup is written to your Drive, in your
account, under your control. We never receive a copy of that backup and cannot read it. You can
disconnect Margin from your Google account at any time from your Google account settings, and the
app works exactly the same with the feature switched off.
</p>
<h2>Payments</h2>
<p>
If you buy Margin, the payment is handled by a third-party payment processor. We do not see or
store your full card details. The processor handles the transaction and shares with us only what
we need to confirm your purchase and provide support.
</p>
<h2>Children</h2>
<p>
Margin is a tool for writers and is not directed at children under 13. We do not knowingly
collect personal information from children.
</p>
<h2>Changes to this policy</h2>
<p>
If we update this policy, we will change the date at the top of this page. Because the app keeps
your book on your own device, the spirit of this policy is unlikely to change: your words belong
to you.
</p>
<h2>Contact</h2>
<p>
Questions about your privacy? Write to <a href={`mailto:${site.supportEmail}`}>{site.supportEmail}</a>
and a real person will answer.
</p>
</Legal>
+92
View File
@@ -0,0 +1,92 @@
---
import Legal from "../layouts/Legal.astro";
import { site } from "../data/site";
---
<Legal
title="Terms of Use"
updated="June 22, 2026"
description={`The terms for using ${site.name}: a one-time purchase, your content stays yours, used as is.`}
>
<h2>Acceptance</h2>
<p>
These terms cover your use of Margin, the offline writing app, and this website. By downloading,
buying, or using Margin, you agree to them. If you do not agree, please do not use the app.
</p>
<h2>Your license to use Margin</h2>
<p>
Margin is a one-time purchase. When you buy it, you get a personal, non-exclusive license to
install and use the app on the devices you own. You keep using the version you bought, and
updates are included at no extra cost. You may not resell, rent, or redistribute the app, or
attempt to defeat its purchase, and you may not reverse engineer it except where the law
expressly allows.
</p>
<h2>Your content is yours</h2>
<p>
Everything you write in Margin belongs to you. Your book is a file on your own computer. We claim
no ownership of it, take no license to it, and never receive a copy. You are responsible for your
own work, including keeping your own backups and making sure you have the right to publish what
you write.
</p>
<h2>Acceptable use</h2>
<p>
Use Margin lawfully. Do not use it to create or distribute material that is illegal, or that
infringes someone else's rights. What you choose to write and publish is your responsibility, not
ours.
</p>
<h2>Third-party services</h2>
<p>
Margin can connect to services you choose, such as your own Google Drive for backups, and you
download and publish through platforms like GitHub and the ebook and print stores. Your use of
those services is governed by their own terms and policies, which we do not control.
</p>
<h2>Updates and availability</h2>
<p>
We work to keep Margin reliable and to improve it over time, but we may change, pause, or
discontinue parts of the app or this website. Because Margin runs on your own machine, the copy
you have installed keeps working even if a feature that depends on an outside service changes.
</p>
<h2>The app is provided as is</h2>
<p>
Margin is provided "as is" and "as available," without warranties of any kind, whether express or
implied, including fitness for a particular purpose and non-infringement. We do not warrant that
the app will be error-free or uninterrupted, or that it will meet every need. You are responsible
for backing up your own work.
</p>
<h2>Limitation of liability</h2>
<p>
To the fullest extent permitted by law, Margin and its maker will not be liable for any indirect,
incidental, or consequential damages, or for any loss of data or content, arising from your use
of the app. Our total liability for any claim is limited to the amount you paid for Margin.
</p>
<h2>Refunds</h2>
<p>
If Margin is not working for you, write to us. We would rather make it right or refund your
purchase than have you stuck with a tool you cannot use.
</p>
<h2>Changes to these terms</h2>
<p>
We may update these terms from time to time. When we do, we will change the date at the top of
this page. Continuing to use Margin after a change means you accept the updated terms.
</p>
<h2>Governing law</h2>
<p>
These terms are governed by the laws of the State of New York, United States, without regard to
its conflict of laws rules.
</p>
<h2>Contact</h2>
<p>
Questions about these terms? Write to <a href={`mailto:${site.supportEmail}`}>{site.supportEmail}</a>.
</p>
</Legal>