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
38 changes: 26 additions & 12 deletions web/apps/marketing/src/app/_components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import { DOCS_URL } from "../_lib/urls";
import Link from "next/link";

import { DOCS_URL, GITHUB_URL } from "../_lib/urls";
import { GithubLink } from "./GithubLink";

/** Two groups, which is the information: the fine print (who holds the
* copyright, the licence that qualifies it, the two legal pages) on the
* left in the quiet tone, and the places to go next (docs, the code) on
* the right. On a phone the groups
* stack, links first and fine print last, in their order of importance
* rather than their DOM order. No "all rights reserved": the software is
* Apache 2.0 and the line would say otherwise. */
export function Footer() {
const quiet = "transition-colors hover:text-ink dark:hover:text-paper";
return (
<footer className="mt-auto border-t border-ink/10 dark:border-paper/10">
<div className="mx-auto flex w-full max-w-6xl flex-wrap items-center justify-between gap-3 px-6 py-8 text-sm text-ink/50 dark:text-paper/50">
<p>&copy; {new Date().getFullYear()} OpenBower. All rights reserved.</p>
<div className="mx-auto flex w-full max-w-6xl flex-col-reverse gap-y-4 px-6 py-8 text-sm text-ink/50 dark:text-paper/50 sm:flex-row sm:items-center sm:justify-between sm:gap-x-8">
<div className="flex flex-wrap items-center gap-x-6 gap-y-1">
<p>&copy; {new Date().getFullYear()} Obris LLC</p>
<a href={`${GITHUB_URL}/blob/main/LICENSE`} target="_blank" rel="noreferrer noopener" className={quiet}>
Apache 2.0
</a>
<Link href="/privacy" className={quiet}>
Privacy
</Link>
<Link href="/terms" className={quiet}>
Terms
</Link>
</div>
<div className="flex gap-6">
<a
href={DOCS_URL}
target="_blank"
rel="noreferrer noopener"
className="transition-colors hover:text-ink dark:hover:text-paper"
>
<a href={DOCS_URL} target="_blank" rel="noreferrer noopener" className={quiet}>
Docs
</a>
<GithubLink className="inline-flex items-center gap-1.5 transition-colors hover:text-ink dark:hover:text-paper">
GitHub
</GithubLink>
<GithubLink className={`inline-flex items-center gap-1.5 ${quiet}`}>GitHub</GithubLink>
</div>
</div>
</footer>
Expand Down
38 changes: 38 additions & 0 deletions web/apps/marketing/src/app/_components/LegalPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ReactNode } from "react";

import { Footer } from "./Footer";
import { Navbar } from "./Navbar";

/** The shell the two legal pages share: the site chrome around a
* narrow reading measure. Sections are plain h2 + paragraphs so the
* text, not the layout, carries the page. */
export function LegalPage({ title, effective, children }: { title: string; effective: string; children: ReactNode }) {
return (
<>
<Navbar />
<main className="mx-auto w-full max-w-3xl px-6 py-24">
<h1 className="text-3xl font-bold text-ink dark:text-paper">{title}</h1>
<p className="mt-3 text-sm text-ink/60 dark:text-paper/60">Effective {effective}</p>
<div className="legal mt-10 space-y-5 text-base leading-7 text-ink/80 dark:text-paper/80">{children}</div>
</main>
<Footer />
</>
);
}

export function Section({ title, children }: { title: string; children: ReactNode }) {
return (
<section className="space-y-4 pt-4">
<h2 className="text-xl font-semibold text-ink dark:text-paper">{title}</h2>
{children}
</section>
);
}

export function Mail({ address }: { address: string }) {
return (
<a href={`mailto:${address}`} className="text-signal hover:underline">
{address}
</a>
);
}
131 changes: 131 additions & 0 deletions web/apps/marketing/src/app/privacy/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import type { Metadata } from "next";
import Link from "next/link";

import { LegalPage, Mail, Section } from "../_components/LegalPage";

export const metadata: Metadata = {
title: "Privacy policy",
description: "What OpenBower collects, what it does with it, and what it never does.",
};

export default function PrivacyPage() {
return (
<LegalPage title="Privacy policy" effective="October 16, 2026">
<Section title="1. Who this covers">
<p>
OpenBower is operated by Obris LLC (&quot;we&quot;). This policy covers the website at openbower.ai, the
hosted app at app.openbower.ai, and the account service at auth.openbower.ai that signs you into both
(together, the &quot;Service&quot;).
</p>
<p>
A self-hosted install of OpenBower is your own. It runs on your machine, and we receive nothing from it
except the sign-in described below. Everything else it holds, your sheets, your keys, your results, stays
with you.
</p>
</Section>

<Section title="2. What we collect">
<p>
<strong>Your account.</strong> Your email address and, if you choose a password, a hash of it. If you sign in
with Google or GitHub, the stable identifier that provider assigns you and the email address it reports as
verified. We never see your password at the provider.
</p>
<p>
<strong>Your content in the hosted app.</strong> The sheets, rows, columns, agent configurations and webhook
settings you create there.
</p>
<p>
<strong>Keys you add.</strong> API keys for the model and data providers you connect are stored to run your
own work and nothing else. We never pool them, share what they return with other accounts, or build anything
on what a provider returned through your key.
</p>
<p>
<strong>Operational records.</strong> Request logs with IP address, browser type and timestamps, kept to
operate and secure the Service.
</p>
<p>
<strong>Updates you ask for.</strong> The email address you give us to hear from us, and nothing else about
you.
</p>
</Section>

<Section title="3. How we use it">
<p>
To sign you in, run the research you ask for, deliver the webhooks you configure, keep the Service working,
and reply when you write to us. We do not sell your information and we do not use your content to train
models.
</p>
</Section>

<Section title="4. Where your rows go">
<p>
When an agent fills a column, the rows it works on are sent to the model and search providers you have
configured, under your keys and their terms. The hosted company universe behind look-alike discovery is
built from data licensed to us; nothing you add to it comes from another user&apos;s keys.
</p>
</Section>

<Section title="5. Who else sees it">
<p>
The infrastructure providers that host the Service and deliver its email, under contracts that limit them to
providing that service to us; and authorities when the law requires it. No one else.
</p>
</Section>

<Section title="6. Cookies">
<p>
The Service sets the cookies sign-in needs: a session cookie at auth.openbower.ai and one at the app. Your
theme preference and a remembered email live in your browser alone. There is no advertising or cross-site
tracking.
</p>
</Section>

<Section title="7. Keeping and deleting">
<p>
We keep your account and content for as long as you use the Service. Write to{" "}
<Mail address="privacy@openbower.ai" /> to delete your account; we remove your content and sign-in records
within 30 days, and operational logs age out on their own.
</p>
</Section>

<Section title="8. Security">
<p>
Traffic to the Service is encrypted in transit. Passwords are stored as salted hashes, and the tokens that
sign you into the hosted app are encrypted at rest. Report a concern to{" "}
<Mail address="security@openbower.ai" />.
</p>
</Section>

<Section title="9. Your rights">
<p>
You can see, correct, export or delete what we hold about you. Where the law gives you rights beyond these,
you have them. Write to <Mail address="privacy@openbower.ai" />.
</p>
</Section>

<Section title="10. Children">
<p>
The Service is not for anyone under 13, and we do not knowingly collect their information. If we learn that
we have, we delete it.
</p>
</Section>

<Section title="11. Changes">
<p>
When this policy changes, the date at the top changes with it. A change that matters to you is announced in
the app before it takes effect.
</p>
</Section>

<Section title="12. Contact">
<p>
<Mail address="privacy@openbower.ai" /> for anything about this policy. The{" "}
<Link href="/terms" className="text-signal hover:underline">
terms of service
</Link>{" "}
cover the rest.
</p>
</Section>
</LegalPage>
);
}
7 changes: 6 additions & 1 deletion web/apps/marketing/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { MetadataRoute } from "next";

export default function sitemap(): MetadataRoute.Sitemap {
return [{ url: "https://openbower.ai", lastModified: new Date() }];
const now = new Date();
return [
{ url: "https://openbower.ai", lastModified: now },
{ url: "https://openbower.ai/privacy", lastModified: now },
{ url: "https://openbower.ai/terms", lastModified: now },
];
}
141 changes: 141 additions & 0 deletions web/apps/marketing/src/app/terms/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import type { Metadata } from "next";
import Link from "next/link";

import { GITHUB_URL } from "../_lib/urls";
import { LegalPage, Mail, Section } from "../_components/LegalPage";

export const metadata: Metadata = {
title: "Terms of service",
description: "The terms for the hosted OpenBower service and the open-source software behind it.",
};

export default function TermsPage() {
return (
<LegalPage title="Terms of service" effective="October 16, 2026">
<Section title="1. What these terms cover">
<p>
These terms are between you and Obris LLC (&quot;we&quot;), the operator of OpenBower, and cover the website
at openbower.ai, the hosted app at app.openbower.ai and the account service at auth.openbower.ai (together,
the &quot;Service&quot;). Using the Service means you accept them.
</p>
<p>
The OpenBower software itself is open source under the Apache License, Version 2.0, in{" "}
<a href={GITHUB_URL} className="text-signal hover:underline" target="_blank" rel="noreferrer noopener">
its repository
</a>
. A self-hosted install is governed by that license, not by these terms.
</p>
</Section>

<Section title="2. The Service">
<p>
OpenBower is a spreadsheet for prospecting whose columns are filled by AI research agents you configure. The
hosted app runs that for you on our infrastructure. Access to it is granted per account; an account you
create on your own install signs into the hosted app only once it has been granted.
</p>
</Section>

<Section title="3. Your account">
<p>
You must be 13 or older. You are responsible for what happens under your account and for keeping its
credentials to yourself; tell us at <Mail address="security@openbower.ai" /> if you think someone else has
them.
</p>
</Section>

<Section title="4. Your keys and the providers behind them">
<p>
The model, search and data providers you connect are your relationships, under their terms and at their
prices. What a provider returns through your key is licensed to you and stays in your account; we never pool
it or pass it to anyone else.
</p>
</Section>

<Section title="5. Acceptable use">
<p>You agree not to use the Service to:</p>
<ul className="list-disc space-y-2 pl-6">
<li>break the law, or contact people in ways the law or their consent does not allow;</li>
<li>collect or process personal data you have no right to;</li>
<li>interfere with the Service, probe it for weaknesses without permission, or evade its limits;</li>
<li>resell access to the hosted app or present its output as your own product.</li>
</ul>
</Section>

<Section title="6. Your content">
<p>
Your sheets, rows and configurations are yours. You give us only the permission needed to store them and run
the work you ask for. You are responsible for having the right to the data you bring in and for what you do
with what comes out.
</p>
</Section>

<Section title="7. Our content">
<p>
The hosted company universe behind look-alike discovery, and the Service&apos;s name and marks, are ours. You
may use the universe through the Service for your own prospecting and not to rebuild or redistribute it.
</p>
</Section>

<Section title="8. Availability and changes">
<p>
The hosted app is early. We change it often, and we may suspend or withdraw it. We give notice in the app for
changes that affect how you use it, and you can export your sheets at any time.
</p>
</Section>

<Section title="9. Disclaimers">
<p>
The Service is provided as is. Research agents are wrong sometimes, and sources can be stale; check what
matters before you act on it. We do not promise that the Service will be uninterrupted or error free.
</p>
</Section>

<Section title="10. Limitation of liability">
<p>
To the fullest extent the law allows, we are not liable for indirect or consequential loss, lost profits or
lost data arising from the Service, and our total liability to you is limited to the amount you paid us for
the Service in the twelve months before the claim, or one hundred US dollars if you paid nothing.
</p>
</Section>

<Section title="11. Indemnification">
<p>
You will defend and indemnify us against claims arising from your content, your use of the Service, or your
breach of these terms.
</p>
</Section>

<Section title="12. Ending the agreement">
<p>
You can leave at any time by asking us to delete your account at <Mail address="privacy@openbower.ai" />.
We can suspend or end an account that breaks these terms. Sections 6, 7, 9, 10 and 11 survive.
</p>
</Section>

<Section title="13. Governing law">
<p>
These terms are governed by the laws of the Commonwealth of Massachusetts, without regard to its conflict of
law rules. Nothing in them limits rights you have under the law where you live.
</p>
</Section>

<Section title="14. Changes to these terms">
<p>
When these terms change, the date at the top changes with it, and a change that matters to you is announced
in the app before it takes effect. Using the Service after that is acceptance.
</p>
</Section>

<Section title="15. Contact">
<p>
<Mail address="support@openbower.ai" /> for anything about these terms. How we handle your information is in
the{" "}
<Link href="/privacy" className="text-signal hover:underline">
privacy policy
</Link>
.
</p>
</Section>
</LegalPage>
);
}
Loading