Initial draft of Simple Heart site

Simple Next.js marketing site for placement.savethedogs.io — home, about,
privacy, terms. 501(c)(3) validation page for Twilio/ads/social.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
John Boland 2026-04-14 12:41:07 -05:00
commit 0c27cd93c4
12 changed files with 579 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
node_modules
.next
.env*
!.env.example
*.log
.DS_Store
next-env.d.ts
.vercel

56
README.md Normal file
View File

@ -0,0 +1,56 @@
# The Simple Heart Initiative — website (draft)
Draft marketing site for The Simple Heart Initiative, a 501(c)(3) public charity (EIN 88-2248389)
registered in Santa Cruz, California.
**Purpose:** a simple, credible web presence Simple Heart can point to for Twilio, ad-platform,
and social-media organizational validation while the main simpleheart.org remains a Substack
redirect. Hosted at **placement.savethedogs.io** for now.
## Stack
- Next.js 16 App Router + React 19
- Tailwind CSS v4
- TypeScript
Matches the `savethedogs/` repo conventions (same Next/React/Tailwind versions, same navy/gold
palette) so deployment follows a familiar pattern.
## Pages
- `/` — home
- `/about` — mission, founder, board, legal/contact
- `/privacy` — privacy policy (covers SMS consent language for Twilio registration)
- `/terms` — terms of service
- External: blog → https://blog.simpleheart.org, campaign → https://savethedogs.io
## Run locally
```bash
npm install
npm run dev # http://localhost:3004
```
## Deploy target
`placement.savethedogs.io`. The `savethedogs/` repo deploys via rsync + PM2 to the AWS box at
52.24.116.127. Options for this subdomain:
1. **Same box, new PM2 app on port 3004** + nginx server block for `placement.savethedogs.io`
proxying to `127.0.0.1:3004`. Cleanest for a draft.
2. **DO droplet (165.227.187.95)** alongside `rescuer-database` (port 3000) and
`mobilization-crm` (port 3002) on port 3004, systemd unit, nginx server block.
DNS: add an A record for `placement.savethedogs.io` pointing at whichever box is chosen.
Deploy scripts are not wired up yet — this is a scaffold only. The closest reference deploy is
`savethedogs/deploy-prod.sh`.
## TODO before calling this production
- Real photos (beagles, Wayne, Ridglan imagery) — currently one placeholder on the home page
- Favicon / og-image
- Confirm board members' full names with Wayne (currently "Dean" and "Priya" — first names only)
- Confirm official mailing address for Santa Cruz registration
- Deploy script + nginx + DNS
- Verify Twilio / Meta / TikTok requirements for the privacy policy SMS-consent language

69
app/about/page.tsx Normal file
View File

@ -0,0 +1,69 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "About",
description:
"The Simple Heart Initiative is a 501(c)(3) nonprofit founded by Wayne Hsiung to build a mass movement for open rescue.",
};
export default function About() {
return (
<article className="max-w-3xl mx-auto px-6 py-16">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight text-[var(--color-primary-dark)]">
About The Simple Heart Initiative
</h1>
<p className="mt-6 text-lg text-[var(--color-text-secondary)] leading-relaxed">
The Simple Heart Initiative is a 501(c)(3) public charity building a mass movement
of compassion for animals. We believe that the emotions we share with other species
joy, fear, grief, love are the foundation of a more humane world.
</p>
<h2 className="mt-12 text-2xl font-semibold text-[var(--color-primary-dark)]">Our Mission</h2>
<p className="mt-3 text-[var(--color-text-secondary)] leading-relaxed">
To build a mass movement for open rescue the nonviolent, transparent tradition of bringing
suffering animals to safety and accepting the legal consequences. We support activists,
tell stories the industry tries to bury, and organize campaigns that let ordinary people
take part in extraordinary acts of courage.
</p>
<h2 className="mt-12 text-2xl font-semibold text-[var(--color-primary-dark)]">Our Founder</h2>
<p className="mt-3 text-[var(--color-text-secondary)] leading-relaxed">
The Simple Heart was founded by Wayne Hsiung, a former law professor and civil rights
attorney who has spent more than two decades organizing on behalf of animals. In October
2022, Wayne was acquitted by a Utah jury after rescuing two sick piglets from the largest
pig farm in the country a historic verdict that affirmed the legal and moral case for
open rescue. He writes the newsletter <em>The Simple Heart</em>, which is read by more
than 73,000 subscribers.
</p>
<h2 className="mt-12 text-2xl font-semibold text-[var(--color-primary-dark)]">Board of Directors</h2>
<ul className="mt-3 space-y-2 text-[var(--color-text-secondary)] leading-relaxed">
<li><strong className="text-[var(--color-text)]">Wayne Hsiung</strong> Founder & President</li>
<li><strong className="text-[var(--color-text)]">Dean</strong> Director</li>
<li><strong className="text-[var(--color-text)]">Priya</strong> Director</li>
</ul>
<h2 className="mt-12 text-2xl font-semibold text-[var(--color-primary-dark)]">Our Programs</h2>
<p className="mt-3 text-[var(--color-text-secondary)] leading-relaxed">
We run public-education campaigns, support legal defense for rescuers, and organize
direct-action mobilizations. Our flagship campaign,{" "}
<a href="https://savethedogs.io" className="text-[var(--color-accent)] underline">Save the Dogs</a>,
is working to rescue beagles from Ridglan Farms in Wisconsin a facility where a judge has
already found probable cause of felony animal cruelty.
</p>
<h2 className="mt-12 text-2xl font-semibold text-[var(--color-primary-dark)]">Legal & Contact</h2>
<p className="mt-3 text-[var(--color-text-secondary)] leading-relaxed">
The Simple Heart Initiative is a 501(c)(3) public charity, EIN{" "}
<strong className="text-[var(--color-text)]">88-2248389</strong>, registered in Santa Cruz,
California. Contributions are tax-deductible to the fullest extent permitted by law.
</p>
<p className="mt-3 text-[var(--color-text-secondary)] leading-relaxed">
For press, partnerships, or general inquiries:{" "}
<a href="mailto:info@simpleheart.org" className="text-[var(--color-accent)] underline">
info@simpleheart.org
</a>
</p>
</article>
);
}

21
app/globals.css Normal file
View File

@ -0,0 +1,21 @@
@import "tailwindcss";
:root {
--color-primary: #1e3a5f;
--color-primary-light: #2a4d7a;
--color-primary-dark: #0f1a2e;
--color-text: #2c2c2c;
--color-text-secondary: #6b7280;
--color-surface: #faf8f4;
--color-surface-muted: #efeae0;
--color-border: #e4ded1;
--color-accent: #c4952a;
--color-accent-hover: #b0842a;
}
html { scroll-behavior: smooth; }
body {
background: var(--color-surface);
color: var(--color-text);
font-family: inherit;
}

83
app/layout.tsx Normal file
View File

@ -0,0 +1,83 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
const inter = Inter({
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
display: "swap",
});
export const metadata: Metadata = {
metadataBase: new URL("https://placement.savethedogs.io"),
title: {
default: "The Simple Heart Initiative",
template: "%s | The Simple Heart Initiative",
},
description:
"The Simple Heart Initiative is a 501(c)(3) nonprofit building a mass movement of compassion — through open rescue, investigation, and storytelling.",
openGraph: {
title: "The Simple Heart Initiative",
description:
"Lessons in compassion, taught by the animals. A 501(c)(3) nonprofit building a mass movement for open rescue.",
type: "website",
siteName: "The Simple Heart Initiative",
locale: "en_US",
},
};
function Header() {
return (
<header className="border-b border-[var(--color-border)] bg-[var(--color-surface)]">
<nav className="max-w-5xl mx-auto px-6 py-5 flex items-center justify-between">
<Link href="/" className="text-[var(--color-primary-dark)] font-semibold tracking-tight text-lg">
The Simple Heart
</Link>
<ul className="flex gap-6 text-sm text-[var(--color-text)]">
<li><Link href="/" className="hover:text-[var(--color-accent)]">Home</Link></li>
<li><Link href="/about" className="hover:text-[var(--color-accent)]">About</Link></li>
<li><a href="https://blog.simpleheart.org" className="hover:text-[var(--color-accent)]">Blog</a></li>
<li><a href="https://savethedogs.io" className="hover:text-[var(--color-accent)]">Save the Dogs</a></li>
</ul>
</nav>
</header>
);
}
function Footer() {
return (
<footer className="border-t border-[var(--color-border)] bg-[var(--color-surface-muted)] mt-24">
<div className="max-w-5xl mx-auto px-6 py-10 text-sm text-[var(--color-text-secondary)]">
<div className="flex flex-wrap gap-6 justify-between">
<div>
<div className="font-semibold text-[var(--color-primary-dark)] mb-1">The Simple Heart Initiative</div>
<div>A 501(c)(3) public charity EIN 88-2248389</div>
<div>Registered in Santa Cruz, California</div>
<div className="mt-2"><a href="mailto:info@simpleheart.org" className="underline">info@simpleheart.org</a></div>
</div>
<div className="flex flex-col gap-1">
<Link href="/about" className="hover:text-[var(--color-accent)]">About</Link>
<a href="https://blog.simpleheart.org" className="hover:text-[var(--color-accent)]">Blog</a>
<a href="https://savethedogs.io" className="hover:text-[var(--color-accent)]">Save the Dogs</a>
<Link href="/privacy" className="hover:text-[var(--color-accent)]">Privacy Policy</Link>
<Link href="/terms" className="hover:text-[var(--color-accent)]">Terms of Service</Link>
</div>
</div>
<div className="mt-8 text-xs">© {new Date().getFullYear()} The Simple Heart Initiative. All rights reserved.</div>
</div>
</footer>
);
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body className="antialiased min-h-screen flex flex-col">
<Header />
<main className="flex-1">{children}</main>
<Footer />
</body>
</html>
);
}

86
app/page.tsx Normal file
View File

@ -0,0 +1,86 @@
import Link from "next/link";
export default function Home() {
return (
<div>
<section className="max-w-4xl mx-auto px-6 pt-20 pb-16 text-center">
<p className="text-sm uppercase tracking-[0.2em] text-[var(--color-accent)] mb-4">
A 501(c)(3) Nonprofit
</p>
<h1 className="text-5xl md:text-6xl font-semibold tracking-tight text-[var(--color-primary-dark)] leading-tight">
Lessons in compassion,<br />taught by the animals.
</h1>
<p className="mt-6 text-lg text-[var(--color-text-secondary)] max-w-2xl mx-auto leading-relaxed">
The Simple Heart Initiative builds a mass movement for open rescue
through investigation, storytelling, and direct action on behalf of animals
who cannot speak for themselves.
</p>
<div className="mt-10 flex gap-4 justify-center flex-wrap">
<a
href="https://savethedogs.io"
className="inline-block bg-[var(--color-primary-dark)] text-white px-6 py-3 rounded-md font-medium hover:bg-[var(--color-primary)] transition"
>
Save the Dogs Campaign
</a>
<a
href="https://blog.simpleheart.org"
className="inline-block border border-[var(--color-primary-dark)] text-[var(--color-primary-dark)] px-6 py-3 rounded-md font-medium hover:bg-[var(--color-surface-muted)] transition"
>
Read the Blog
</a>
</div>
</section>
<section className="bg-[var(--color-surface-muted)] py-16">
<div className="max-w-4xl mx-auto px-6 grid md:grid-cols-3 gap-10">
<div>
<h3 className="font-semibold text-lg text-[var(--color-primary-dark)] mb-2">Open Rescue</h3>
<p className="text-[var(--color-text-secondary)] text-sm leading-relaxed">
Nonviolent action to bring suffering animals to safety out in the open, with a camera rolling,
and with the willingness to answer for it in a court of law.
</p>
</div>
<div>
<h3 className="font-semibold text-lg text-[var(--color-primary-dark)] mb-2">Investigation</h3>
<p className="text-[var(--color-text-secondary)] text-sm leading-relaxed">
Documenting the conditions inside factory farms and research facilities so the public can
see what industry works hard to hide.
</p>
</div>
<div>
<h3 className="font-semibold text-lg text-[var(--color-primary-dark)] mb-2">Storytelling</h3>
<p className="text-[var(--color-text-secondary)] text-sm leading-relaxed">
Sharing the stories of individual animals and the humans who love them
to build a movement rooted in the simple heart we all share.
</p>
</div>
</div>
</section>
<section className="max-w-4xl mx-auto px-6 py-20">
<div className="grid md:grid-cols-2 gap-12 items-center">
<div>
<h2 className="text-3xl font-semibold text-[var(--color-primary-dark)] tracking-tight">
Save the Dogs at Ridglan Farms
</h2>
<p className="mt-4 text-[var(--color-text-secondary)] leading-relaxed">
On April 19, 2026, hundreds of activists, veterinarians, and faith leaders will gather
in Wisconsin to rescue beagles from one of the largest dog-breeding facilities in the United States.
A judge has already found probable cause of felony animal cruelty. Zero dogs have been freed.
</p>
<Link
href="https://savethedogs.io"
className="inline-block mt-6 text-[var(--color-accent)] font-medium hover:text-[var(--color-accent-hover)]"
>
Learn more & take action
</Link>
</div>
<div className="aspect-[4/3] bg-[var(--color-surface-muted)] rounded-lg border border-[var(--color-border)] flex items-center justify-center text-[var(--color-text-secondary)] text-sm">
{/* Photo placeholder — swap for rescue imagery */}
Photo: beagle rescue
</div>
</div>
</section>
</div>
);
}

97
app/privacy/page.tsx Normal file
View File

@ -0,0 +1,97 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Privacy Policy",
description: "How The Simple Heart Initiative collects, uses, and protects your information.",
};
export default function Privacy() {
return (
<article className="max-w-3xl mx-auto px-6 py-16 prose prose-neutral">
<h1 className="text-4xl font-semibold tracking-tight text-[var(--color-primary-dark)]">Privacy Policy</h1>
<p className="text-sm text-[var(--color-text-secondary)] mt-2">Last updated: April 14, 2026</p>
<section className="mt-8 space-y-6 text-[var(--color-text)] leading-relaxed">
<p>
The Simple Heart Initiative (&ldquo;Simple Heart,&rdquo; &ldquo;we,&rdquo; &ldquo;our,&rdquo; or
&ldquo;us&rdquo;) respects your privacy. This Privacy Policy explains what information we collect,
how we use it, and the choices you have. It applies to simpleheart.org and any subdomain operated
by The Simple Heart Initiative, including placement.savethedogs.io while that site is hosted by
Simple Heart.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Information We Collect</h2>
<p>
We collect information you provide directly such as your name, email address, phone number,
and mailing address when you subscribe to our newsletter, make a donation, sign a petition,
volunteer for a campaign, or contact us. We also collect limited technical information
automatically, including your IP address, browser type, device type, referring pages, and pages
viewed, using standard server logs and privacy-respecting analytics.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">How We Use Information</h2>
<p>We use the information we collect to:</p>
<ul className="list-disc pl-6 space-y-2">
<li>Send newsletters, campaign updates, and mobilization alerts you have requested.</li>
<li>Process donations and provide tax receipts.</li>
<li>Coordinate volunteers, events, and rescue actions.</li>
<li>Respond to messages you send us.</li>
<li>Understand how our site is used so we can improve it.</li>
<li>Comply with legal obligations.</li>
</ul>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">SMS &amp; Phone Communications</h2>
<p>
If you provide your phone number, you consent to receive SMS messages and calls from Simple Heart
related to our programs and campaigns. Message and data rates may apply. Reply STOP at any time
to opt out. We do not sell or share phone numbers with third parties for their marketing
purposes.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Sharing of Information</h2>
<p>
We do not sell your personal information. We share information only with service providers who
help us operate (for example, email, SMS, and payment processors), and only to the extent
necessary for them to perform that work. We may disclose information when required by law or to
protect the rights, safety, or property of Simple Heart, our supporters, or the public.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Cookies</h2>
<p>
We use essential cookies and minimal analytics to run the site. You can disable cookies in your
browser settings; parts of the site may not work without them.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Your Choices</h2>
<p>
You may unsubscribe from emails at any time using the link in any message, or by contacting us.
You may request access to, correction of, or deletion of your personal information by emailing{" "}
<a href="mailto:info@simpleheart.org" className="text-[var(--color-accent)] underline">
info@simpleheart.org
</a>
.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Children</h2>
<p>
Our site is not directed to children under 13, and we do not knowingly collect information from
children under 13.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Changes</h2>
<p>
We may update this Privacy Policy from time to time. We will post the revised policy here with a
new &ldquo;Last updated&rdquo; date.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Contact</h2>
<p>
The Simple Heart Initiative, Santa Cruz, California.{" "}
<a href="mailto:info@simpleheart.org" className="text-[var(--color-accent)] underline">
info@simpleheart.org
</a>
</p>
</section>
</article>
);
}

103
app/terms/page.tsx Normal file
View File

@ -0,0 +1,103 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Terms of Service",
description: "Terms of Service for The Simple Heart Initiative websites.",
};
export default function Terms() {
return (
<article className="max-w-3xl mx-auto px-6 py-16">
<h1 className="text-4xl font-semibold tracking-tight text-[var(--color-primary-dark)]">Terms of Service</h1>
<p className="text-sm text-[var(--color-text-secondary)] mt-2">Last updated: April 14, 2026</p>
<section className="mt-8 space-y-6 text-[var(--color-text)] leading-relaxed">
<p>
These Terms of Service (&ldquo;Terms&rdquo;) govern your use of the websites operated by The
Simple Heart Initiative (&ldquo;Simple Heart,&rdquo; &ldquo;we,&rdquo; &ldquo;our,&rdquo; or
&ldquo;us&rdquo;), including simpleheart.org and placement.savethedogs.io. By using our sites,
you agree to these Terms.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">About Simple Heart</h2>
<p>
The Simple Heart Initiative is a 501(c)(3) public charity (EIN 88-2248389) registered in Santa
Cruz, California. Our mission is to build a mass movement of compassion for animals through
investigation, storytelling, and open rescue.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Use of the Site</h2>
<p>
You agree to use our sites only for lawful purposes. You agree not to attempt to disrupt or
interfere with the sites, circumvent security, harvest data, or use the sites to harass,
threaten, or defraud others.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Donations</h2>
<p>
Donations made to Simple Heart are tax-deductible to the fullest extent permitted by law. Unless
otherwise specified, donations are unrestricted and support our general programs. Donations are
non-refundable except where required by law or at our sole discretion in the case of a
demonstrated processing error.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Communications</h2>
<p>
By providing your email address or phone number, you consent to receive communications from
Simple Heart. You can opt out at any time. See our{" "}
<a href="/privacy" className="text-[var(--color-accent)] underline">Privacy Policy</a> for
details.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Intellectual Property</h2>
<p>
The content on our sites text, photos, videos, and graphics is owned by Simple Heart or
used with permission, and is protected by copyright and other laws. You may share and link to
our content with attribution, but you may not reproduce it commercially without written
permission.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Third-Party Links</h2>
<p>
Our sites link to third-party websites, including blog.simpleheart.org and savethedogs.io.
We are not responsible for the content or practices of sites we do not control.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Disclaimers</h2>
<p>
Our sites and content are provided &ldquo;as is&rdquo; without warranties of any kind. To the
fullest extent permitted by law, Simple Heart disclaims all warranties, express or implied. We
do not warrant that the site will be uninterrupted, error-free, or free of harmful components.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Limitation of Liability</h2>
<p>
To the fullest extent permitted by law, Simple Heart and its directors, officers, employees,
and volunteers will not be liable for any indirect, incidental, special, consequential, or
punitive damages arising from your use of the sites.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Governing Law</h2>
<p>
These Terms are governed by the laws of the State of California, without regard to its
conflict-of-laws principles.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Changes</h2>
<p>
We may update these Terms from time to time. We will post the revised Terms here with a new
&ldquo;Last updated&rdquo; date. Continued use of the sites after changes constitutes
acceptance.
</p>
<h2 className="text-2xl font-semibold text-[var(--color-primary-dark)]">Contact</h2>
<p>
The Simple Heart Initiative, Santa Cruz, California.{" "}
<a href="mailto:info@simpleheart.org" className="text-[var(--color-accent)] underline">
info@simpleheart.org
</a>
</p>
</section>
</article>
);
}

7
next.config.ts Normal file
View File

@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactStrictMode: true,
};
export default nextConfig;

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "simpleheart-site",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 3005",
"build": "next build",
"start": "next start -p 3005"
},
"dependencies": {
"next": "16.1.7",
"react": "19.2.3",
"react-dom": "19.2.3"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"tailwindcss": "^4",
"typescript": "^5"
}
}

5
postcss.config.mjs Normal file
View File

@ -0,0 +1,5 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};

21
tsconfig.json Normal file
View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] }
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}