Initial commit — eLegal Software monorepo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Leon Serfaty
2026-04-26 02:42:42 -04:00
co-authored by Claude Sonnet 4.6
commit 0700d54225
160 changed files with 22771 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
import { Link } from 'react-router-dom';
import { LegalLayout, H2, P, UL } from './LegalLayout';
export default function CookiesPage() {
return (
<LegalLayout title="Cookie Policy" effectiveDate="April 2026">
<P>
This page explains the cookies eLegal Software sets, what they are for, and how to control
them.
</P>
<H2>What is a cookie?</H2>
<P>
A cookie is a small piece of data a website asks your browser to store on your device.
It can be read back later by the same site. We use a small number of cookies and
nothing else (no localStorage tracking, no fingerprinting).
</P>
<H2>Cookies we set</H2>
<table className="w-full border border-ink-200 rounded-xl overflow-hidden text-sm">
<thead className="bg-ink-50 text-left text-xs uppercase tracking-wider text-ink-500">
<tr>
<th className="px-4 py-2">Name</th>
<th className="px-4 py-2">Purpose</th>
<th className="px-4 py-2">Lifetime</th>
<th className="px-4 py-2">Type</th>
</tr>
</thead>
<tbody className="divide-y divide-ink-100">
<tr>
<td className="px-4 py-3 font-mono text-xs">sid</td>
<td className="px-4 py-3">Keeps you signed in. Holds an opaque session identifier whose hash is stored in our database.</td>
<td className="px-4 py-3">30 days (sliding)</td>
<td className="px-4 py-3">Essential</td>
</tr>
<tr>
<td className="px-4 py-3 font-mono text-xs">csrf</td>
<td className="px-4 py-3">Cross-site request forgery protection. Echoed back as a header on state-changing requests.</td>
<td className="px-4 py-3">Session</td>
<td className="px-4 py-3">Essential</td>
</tr>
<tr>
<td className="px-4 py-3 font-mono text-xs">elegal:cookie-consent</td>
<td className="px-4 py-3">
Stored in <span className="font-mono">localStorage</span>, not as a cookie. Records your cookie banner choice
so we don&apos;t ask again.
</td>
<td className="px-4 py-3">Until cleared</td>
<td className="px-4 py-3">Essential</td>
</tr>
</tbody>
</table>
<H2>Optional cookies</H2>
<P>
We do not currently set any optional analytics or advertising cookies. If we add any in
the future, we will update this page and re-prompt you for consent.
</P>
<H2>Third parties</H2>
<UL
items={[
'Payment processor — when you check out, our payments processor may set its own cookies on its own domain. Those are governed by its policy.',
'Error reporting — Sentry runs only when an error occurs and does not set cookies on your device under our domain.',
]}
/>
<H2>Controlling cookies</H2>
<UL
items={[
'You can clear or block cookies in your browser settings. Blocking the essential cookies will sign you out and may prevent you from using the service.',
'You can change your banner choice anytime from Settings → Cookie preferences while signed in.',
]}
/>
<H2>More information</H2>
<P>
For details on the broader handling of personal information, see the{' '}
<Link to="/legal/privacy" className="text-brand-600 hover:underline">
Privacy Policy
</Link>
.
</P>
</LegalLayout>
);
}
+78
View File
@@ -0,0 +1,78 @@
import type { ReactNode } from 'react';
import { Link } from 'react-router-dom';
import { AlertTriangle } from 'lucide-react';
import { PublicLayout } from '@/components/public/PublicLayout';
const LINKS = [
{ to: '/legal/privacy', label: 'Privacy Policy' },
{ to: '/legal/terms', label: 'Terms of Service' },
{ to: '/legal/cookies', label: 'Cookie Policy' },
];
export function LegalLayout({
title,
effectiveDate,
children,
}: {
title: string;
effectiveDate: string;
children: ReactNode;
}) {
return (
<PublicLayout>
<section className="container py-12 max-w-4xl">
<header className="mb-8">
<p className="text-xs uppercase tracking-wider text-brand-600 font-semibold">Legal</p>
<h1 className="mt-2 text-3xl md:text-4xl font-bold text-ink-950 font-display">{title}</h1>
<p className="mt-2 text-sm text-ink-500">Effective {effectiveDate}</p>
</header>
<div className="rounded-2xl border border-amber-200 bg-amber-50/40 p-4 mb-8 flex items-start gap-3 text-sm text-amber-900">
<AlertTriangle className="h-4 w-4 flex-none mt-0.5 text-amber-600" />
<p>
<strong className="font-semibold">Template notice:</strong> these documents are
starting points that the eLegal Software team has drafted in plain English. Before you put
them on a production site, have a licensed attorney in your jurisdiction review and
adapt them to your business and applicable law.
</p>
</div>
<nav className="mb-10 flex flex-wrap gap-2">
{LINKS.map((l) => (
<Link
key={l.to}
to={l.to}
className="rounded-full border border-ink-200 px-3 py-1.5 text-xs font-medium text-ink-600 hover:border-brand-200 hover:bg-brand-50/30 hover:text-brand-700 transition"
>
{l.label}
</Link>
))}
</nav>
<article className="prose-style space-y-5">{children}</article>
</section>
</PublicLayout>
);
}
export function H2({ children }: { children: ReactNode }) {
return <h2 className="mt-10 text-xl md:text-2xl font-bold text-ink-950 font-display">{children}</h2>;
}
export function H3({ children }: { children: ReactNode }) {
return <h3 className="mt-6 text-lg font-semibold text-ink-900 font-display">{children}</h3>;
}
export function P({ children }: { children: ReactNode }) {
return <p className="text-ink-800 leading-relaxed">{children}</p>;
}
export function UL({ items }: { items: ReactNode[] }) {
return (
<ul className="list-disc pl-6 space-y-2 text-ink-800">
{items.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
);
}
+139
View File
@@ -0,0 +1,139 @@
import { Link } from 'react-router-dom';
import { LegalLayout, H2, H3, P, UL } from './LegalLayout';
export default function PrivacyPage() {
return (
<LegalLayout title="Privacy Policy" effectiveDate="April 2026">
<P>
This policy explains what information eLegal Software collects, why we collect it, and the
choices you have. We aim for plain language. Where a term has a specific legal meaning,
we say so.
</P>
<H2>1. Who we are</H2>
<P>
eLegal Software (&ldquo;we,&rdquo; &ldquo;us&rdquo;) provides practice-management software for
law firms. When you use the service we are the data controller for the information you
provide about yourself and your firm. For information your firm uploads about its
clients, your firm is the controller and we act as a processor.
</P>
<H2>2. Information we collect</H2>
<H3>2.1 Information you give us</H3>
<UL
items={[
'Account information — your name, email address, password (stored only as an argon2id hash), and firm name.',
'Practice data — clients, cases, documents, time entries, invoices, and notes you create or upload.',
'Communications — messages you send through the contact form, support requests, and email replies.',
'Payment information — handled by our payments processor; we never see or store your full card number.',
]}
/>
<H3>2.2 Information we collect automatically</H3>
<UL
items={[
'Log data — IP address, user agent, requested URL, response status, and timestamp. Used for security and debugging.',
'Cookies — see the Cookie Policy.',
'Aggregate usage — anonymous counts of feature use to help us prioritize improvements.',
]}
/>
<H2>3. How we use information</H2>
<UL
items={[
'To operate the service — let you sign in, store your data, generate documents, send invoices.',
'To keep accounts secure — rate limiting, anomaly detection, audit logging of privileged actions.',
'To support you — respond to questions and resolve issues you report.',
'To improve — understand what is working and what is not, in aggregate.',
'To comply with law — respond to legal requests, prevent fraud, and enforce our Terms.',
]}
/>
<P>
We do not sell your information. We do not use your firm&apos;s practice data to train
machine-learning models.
</P>
<H2>4. Where data is stored</H2>
<P>
Your data is stored on infrastructure operated by DigitalOcean in the region you
select. Database backups are encrypted at rest and retained for 30 days. We use TLS for
all data in transit.
</P>
<H2>5. Sharing</H2>
<P>We share information only with the parties listed below, and only as needed to operate the service:</P>
<UL
items={[
'Hosting and database — DigitalOcean (managed Postgres, app hosting, Spaces object storage).',
'Email — our transactional email provider, used to deliver verification, password resets, and invoices.',
'Payments — our payments processor, for subscription billing.',
'Error monitoring — Sentry, used to capture crashes; we do not send personal practice data to Sentry.',
]}
/>
<P>
We may share information when required by law, valid legal process, or to protect the
rights, safety, or property of eLegal Software, our users, or others.
</P>
<H2>6. Your rights</H2>
<P>
Depending on where you live, you may have the right to access, correct, port, or delete
your personal information, and to object to or restrict certain processing. You can
exercise most of these rights directly inside the app:
</P>
<UL
items={[
'Access and portability — go to Settings → Export your data to download a JSON file with everything tied to your account.',
'Deletion — go to Settings → Delete account. We will permanently remove your account, your firm, and the firms practice data.',
'Correction — edit your profile, clients, cases, time entries, invoices, and documents directly.',
]}
/>
<P>
For requests we cannot satisfy in-app, email <a href="mailto:privacy@elegalsoftware.com" className="text-brand-600 hover:underline">privacy@elegalsoftware.com</a>.
</P>
<H2>7. Retention</H2>
<UL
items={[
'Account and practice data: kept until you delete it, or up to 30 days after account deletion (in encrypted backups), then purged.',
'Audit log: kept for 24 months.',
'Payment records: kept as required by tax and accounting laws (typically 7 years).',
'Server logs: kept for 30 days.',
]}
/>
<H2>8. International transfers</H2>
<P>
If you access the service from a country other than where the data is hosted, your
information may be transferred to and stored in that hosting region. We use standard
contractual clauses with our processors where required.
</P>
<H2>9. Children</H2>
<P>
The service is not directed to children under 16, and we do not knowingly collect
personal information from them.
</P>
<H2>10. Changes to this policy</H2>
<P>
We will post material changes here and update the effective date. If a change is
significant we will notify account holders by email at least 14 days before it takes
effect.
</P>
<H2>11. Contact</H2>
<P>
Questions or requests: <a href="mailto:privacy@elegalsoftware.com" className="text-brand-600 hover:underline">privacy@elegalsoftware.com</a>.
For details on the cookies we set, see the{' '}
<Link to="/legal/cookies" className="text-brand-600 hover:underline">
Cookie Policy
</Link>
. For the contract that governs your use of the service, see the{' '}
<Link to="/legal/terms" className="text-brand-600 hover:underline">
Terms of Service
</Link>
.
</P>
</LegalLayout>
);
}
+134
View File
@@ -0,0 +1,134 @@
import { Link } from 'react-router-dom';
import { LegalLayout, H2, P, UL } from './LegalLayout';
export default function TermsPage() {
return (
<LegalLayout title="Terms of Service" effectiveDate="April 2026">
<P>
These Terms govern your access to and use of eLegal Software. By creating an account or using
the service, you agree to them. If you are using eLegal Software on behalf of a firm, you
represent that you have authority to bind that firm to these Terms.
</P>
<H2>1. The service</H2>
<P>
eLegal Software is software that helps law firms manage cases, track billable hours, store
documents, and produce invoices. We provide the software; you remain responsible for
the legal work and the relationships with your own clients.
</P>
<H2>2. Your account</H2>
<UL
items={[
'You are responsible for safeguarding your password and for any activity under your account.',
'Notify us promptly if you suspect unauthorized access.',
'You must provide accurate registration information and keep it current.',
'One person, one account. Sharing accounts is not permitted.',
]}
/>
<H2>3. Acceptable use</H2>
<P>You agree not to:</P>
<UL
items={[
'Use the service to violate any law or the rights of another person.',
'Attempt to access accounts, data, or systems you are not authorized to access.',
'Reverse engineer, scrape, or interfere with the service or its security features.',
'Upload malware or content that is illegal, infringing, or harmful.',
'Resell or sublicense the service without our written consent.',
]}
/>
<H2>4. Plans, fees, and trials</H2>
<UL
items={[
'Paid plans renew automatically until canceled. You can cancel anytime from billing settings.',
'Fees are charged in advance for each subscription period and are non-refundable except where required by law.',
'We may change pricing with at least 30 days notice. Existing paid periods are honored at the prior price.',
'Trial accounts and the free Starter plan have feature and usage limits. Limits may change as the product evolves.',
]}
/>
<H2>5. Your content</H2>
<P>
You retain ownership of everything you upload (clients, cases, documents, time
entries, invoices). You grant us a limited license to host, process, and display that
content solely to operate the service for you. We do not use your content to train
machine-learning models, and we will not disclose it except as described in our{' '}
<Link to="/legal/privacy" className="text-brand-600 hover:underline">
Privacy Policy
</Link>
.
</P>
<H2>6. Confidentiality of your clients data</H2>
<P>
We understand that information about your clients is confidential, often privileged,
and subject to professional ethics rules. We treat it accordingly: encrypted in transit
and at rest, scoped to your firm by our access-control system, and accessible to our
staff only as strictly needed to operate the service or respond to a support request
you initiate.
</P>
<H2>7. Suspension and termination</H2>
<UL
items={[
'You may terminate your account anytime from Settings → Delete account.',
'We may suspend or terminate accounts that violate these Terms, present a security risk, or are inactive for an extended period (we will notify you first where reasonably possible).',
'On termination, you can export your data for up to 30 days; after that, your data is permanently deleted from our active systems and from backups within the following 30 days.',
]}
/>
<H2>8. Service availability</H2>
<P>
We aim for high availability but do not guarantee uninterrupted service. We schedule
maintenance during low-traffic windows and post notices for significant changes.
</P>
<H2>9. Disclaimer</H2>
<P>
The service is provided &ldquo;as is.&rdquo; To the maximum extent permitted by law, we
disclaim all warranties, express or implied, including merchantability, fitness for a
particular purpose, and non-infringement. eLegal Software is software, not a substitute for
professional legal judgment. Use of the service does not create an attorneyclient
relationship between you and eLegal Software.
</P>
<H2>10. Limitation of liability</H2>
<P>
To the maximum extent permitted by law, our total liability for any claim arising out
of or related to the service is limited to the amount you paid us in the 12 months
preceding the event giving rise to the claim. We are not liable for indirect,
incidental, special, consequential, or punitive damages, or for lost profits or
revenues.
</P>
<H2>11. Indemnification</H2>
<P>
You agree to indemnify and hold us harmless from any claims, losses, or expenses
arising out of (a) your use of the service in violation of these Terms or applicable
law, or (b) your content.
</P>
<H2>12. Changes to the Terms</H2>
<P>
We may update these Terms from time to time. Material changes take effect 30 days after
we post them, or sooner if required by law. Continued use after the effective date
means you accept the updated Terms.
</P>
<H2>13. Governing law and disputes</H2>
<P>
These Terms are governed by the laws of the jurisdiction stated in your account region
without regard to conflict-of-laws rules. The parties will attempt to resolve any
dispute in good faith. Where that fails, disputes will be resolved by the courts
located in that jurisdiction unless applicable law requires otherwise.
</P>
<H2>14. Contact</H2>
<P>
Questions about these Terms: <a href="mailto:legal@elegalsoftware.com" className="text-brand-600 hover:underline">legal@elegalsoftware.com</a>.
</P>
</LegalLayout>
);
}