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
32 changes: 32 additions & 0 deletions public/llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Tech for Palestine

> Tech for Palestine is a 501(c)(3) nonprofit (EIN 99-3441367) that incubates and scales tech and advocacy projects for Palestinian liberation. It is a coalition of thousands of founders, engineers, product marketers, investors, and other professionals in the tech industry supporting Palestinian liberation.

Tech for Palestine's mission is to harness technology and human innovation for a free and truly sovereign Palestine. It operates primarily as an incubator: it provides mentorship, tech volunteers, marketing support, and community connections to help early-stage Palestinian-advocacy projects start, grow, and scale. Tech for Palestine is not itself a single product — it is the organization behind an independent portfolio of tools (news coverage, boycott and accountability tools, protest-finding tools, datasets, and more) built and run by the movement.

## Key pages

- [About](https://techforpalestine.org/about): Mission, founder, and organizational background.
- [Donate](https://techforpalestine.org/donate): Support Tech for Palestine's work; donations are generally tax-deductible in the US.
- [Incubator](https://techforpalestine.org/incubator): How the T4P Incubator supports early-stage advocacy projects with mentorship, volunteers, and funding.
- [Projects](https://techforpalestine.org/projects): Directory of active Incubator projects.
- [Ideas](https://techforpalestine.org/ideas): Project ideas available for advocates to pick up and lead.
- [Membership](https://techforpalestine.org/membership): Paid membership program — suggested dues, fee waivers, and benefits.
- [Volunteer](https://techforpalestine.org/volunteer): How to volunteer skills and time to Incubator projects.
- [Mentorship](https://techforpalestine.org/mentorship): How to become a mentor for Incubator projects.
- [Get Involved](https://techforpalestine.org/get-involved): Overview of every way to contribute — volunteering, mentoring, membership, and building.
- [Events](https://techforpalestine.org/events): Community webinars, workshops, and in-person gatherings.
- [FAQ](https://techforpalestine.org/faq): Answers to common questions about T4P's mission and programs.
- [Team](https://techforpalestine.org/team): Board and staff leadership.
- [Media](https://techforpalestine.org/media): Press coverage, interviews, and brand/press-kit assets.
- [Tools](https://techforpalestine.org/tools): Directory of Palestinian-advocacy tools built by the movement.
- [Entrepreneurs for Palestine](https://techforpalestine.org/e4p): A global community of founders and CEOs pledging to steer hiring, sourcing, and fundraising in support of Palestinian liberation.
- [Legal & Financial Notice](https://techforpalestine.org/legal): 501(c)(3) status, EIN, and financial transparency.

## Organization facts

- Legal name: Tech for Palestine
- Entity type: 501(c)(3) nonprofit
- EIN: 99-3441367
- Registered address: 548 Market St #266950, San Francisco, CA 94104-5401, US
- Website: https://techforpalestine.org
24 changes: 24 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
User-agent: *
Allow: /

# Explicit allow rules for major AI crawlers/answer engines (redundant with
# the wildcard above, but keeps intent explicit if narrower rules are ever
# added for other bots).
User-agent: GPTBot
Allow: /

User-agent: ChatGPT-User
Allow: /

User-agent: OAI-SearchBot
Allow: /

User-agent: ClaudeBot
Allow: /

User-agent: Claude-User
Allow: /

User-agent: PerplexityBot
Allow: /

User-agent: Google-Extended
Allow: /

Sitemap: https://techforpalestine.org/sitemap-index.xml
24 changes: 13 additions & 11 deletions src/components/events/EventsNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ function HeroEvent({ event }: HeroEventProps) {
{/* Content side */}
<div className="flex flex-col gap-4 p-8 min-[810px]:p-10">
{/* Date block */}
<div>
<p className="ts-stat leading-none text-brand">{day}</p>
<p className="ts-overline text-ink-secondary">
<time dateTime={event.date}>
<span className="ts-stat block leading-none text-brand">{day}</span>
<span className="ts-overline block text-ink-secondary">
{month} {year}
</p>
</div>
</span>
</time>

{/* Title */}
<h2 className="ts-editorial text-ink">{event.title}</h2>
Expand Down Expand Up @@ -232,12 +232,12 @@ function LineupTile({ event }: LineupTileProps) {
{/* Content */}
<div className="flex flex-1 flex-col gap-2 p-5">
{/* Date */}
<div>
<p className="ts-heading leading-none text-brand">{day}</p>
<p className="ts-overline text-ink-secondary">
<time dateTime={event.date}>
<span className="ts-heading block leading-none text-brand">{day}</span>
<span className="ts-overline block text-ink-secondary">
{month} {year}
</p>
</div>
</span>
</time>

{/* Title */}
<h3 className="ts-eyebrow mt-1 line-clamp-2 text-ink">{event.title}</h3>
Expand Down Expand Up @@ -311,7 +311,9 @@ function PastEventCard({ event }: { event: EventItem }) {
</div>
<h2 className="ts-subheading break-words text-ink">{event.title}</h2>
<div className="flex flex-wrap gap-x-5 gap-y-1">
<span className="ts-body-small text-ink-secondary">{full}</span>
<time dateTime={event.date} className="ts-body-small text-ink-secondary">
{full}
</time>
{event.time && <span className="ts-body-small text-ink-secondary">{event.time}</span>}
{event.location && (
<span className="ts-body-small text-ink-secondary">{event.location}</span>
Expand Down
2 changes: 2 additions & 0 deletions src/components/home/FooterSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const socials: { name: string; url: string; icon: string }[] = [
alt="Tech for Palestine"
width="352"
height="112"
loading="lazy"
class="h-14 w-auto"
/>
</a>
Expand All @@ -106,6 +107,7 @@ const socials: { name: string; url: string; icon: string }[] = [
<img
src={s.icon}
alt={s.name}
loading="lazy"
class="h-5 w-5 opacity-40 transition-opacity duration-200 hover:opacity-100"
/>
) : (
Expand Down
37 changes: 24 additions & 13 deletions src/components/membership/MembershipDues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,41 @@ function QgivEmbed() {
}

export default function MembershipDues() {
const [showCalculator] = useState<boolean>(() => {
// Default to the no-calculator variant so this renders identically during
// SSR (no window/localStorage access) before the A/B assignment runs below.
const [showCalculator, setShowCalculator] = useState(false);

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const urlParam = urlParams.get("calculator");
if (urlParam === "yes") return true;
if (urlParam === "no") return false;

const stored = localStorage.getItem("membership_ab_variant");
if (stored === "Calculator") return true;
if (stored === "No Calculator") return false;
let assigned: boolean;
if (urlParam === "yes") {
assigned = true;
} else if (urlParam === "no") {
assigned = false;
} else {
const stored = localStorage.getItem("membership_ab_variant");
if (stored === "Calculator") {
assigned = true;
} else if (stored === "No Calculator") {
assigned = false;
} else {
assigned = Math.random() < 0.5;
localStorage.setItem("membership_ab_variant", assigned ? "Calculator" : "No Calculator");
}
}

const assigned = Math.random() < 0.5;
localStorage.setItem("membership_ab_variant", assigned ? "Calculator" : "No Calculator");
return assigned;
});
setShowCalculator(assigned);

useEffect(() => {
if (typeof window.plausible !== "undefined") {
window.plausible("Membership Page", {
props: {
membership_variant: showCalculator ? "Calculator" : "No Calculator",
membership_variant: assigned ? "Calculator" : "No Calculator",
},
});
}
}, [showCalculator]);
}, []);

return (
<div>
Expand Down
18 changes: 14 additions & 4 deletions src/layouts/HomeLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,35 @@ interface Props {
description?: string;
image?: string;
noindex?: boolean;
canonicalUrl?: string;
}

const {
title,
description = "T4P is an incubator for Palestine advocacy projects.",
image = "https://techforpalestine.org/t4p-social-logo.png",
noindex = false,
canonicalUrl: canonicalUrlOverride,
} = Astro.props;

const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";

const canonicalUrl = new URL(
Astro.url.pathname,
Astro.site || "https://techforpalestine.org"
).toString();
// Site-wide internal links never use a trailing slash, so the canonical tag
// shouldn't either — otherwise /page and /page/ resolve to the same content
// with two different self-referential canonicals.
const normalizedPathname =
Astro.url.pathname.length > 1 && Astro.url.pathname.endsWith("/")
? Astro.url.pathname.slice(0, -1)
: Astro.url.pathname;

const canonicalUrl =
canonicalUrlOverride ||
new URL(normalizedPathname, Astro.site || "https://techforpalestine.org").toString();

const organizationSchema = {
"@context": "https://schema.org",
"@type": "NonprofitOrganization",
"@id": "https://techforpalestine.org/#organization",
name: "Tech for Palestine",
url: "https://techforpalestine.org",
logo: "https://techforpalestine.org/t4p-social-logo.png",
Expand Down
8 changes: 6 additions & 2 deletions src/pages/about-new.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ const founderSchema = {
"@type": "Person",
name: "Paul Biggar",
jobTitle: "Founder",
image: "https://techforpalestine.org/paul-biggar.webp",
worksFor: {
"@type": "NonprofitOrganization",
name: "Tech for Palestine",
"@id": "https://techforpalestine.org/#organization",
},
sameAs: ["https://blog.paulbiggar.com/", "https://circleci.com", "https://darklang.com"],
};
Expand Down Expand Up @@ -45,7 +46,10 @@ const founderSchema = {
>
</h1>
<p class="ts-body-large mb-4 max-w-[65ch] text-ink-secondary">
Technology should disrupt the status quo — not serve it.
<strong class="font-medium text-ink"
>Tech for Palestine is a 501(c)(3) nonprofit that incubates and scales tech and
advocacy projects for Palestinian liberation.</strong
> Technology should disrupt the status quo — not serve it.
</p>
<p class="ts-body-large mb-4 max-w-[65ch] text-ink-secondary">
For decades, the narrative about Palestine has been shaped by selective historical
Expand Down
86 changes: 76 additions & 10 deletions src/pages/contact-new.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
type="application/ld+json"
set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "ContactPoint",
contactType: "customer support",
email: "contact@techforpalestine.org",
"@type": "NonprofitOrganization",
"@id": "https://techforpalestine.org/#organization",
contactPoint: {
"@type": "ContactPoint",
contactType: "customer support",
email: "contact@techforpalestine.org",
},
})}
/>
</Fragment>
Expand All @@ -30,11 +34,17 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
<h1 class="ts-editorial mb-6 text-ink">Contact Us</h1>
<p class="ts-body max-w-[65ch] text-ink-secondary">
Have a question, media inquiry, or want to request an endorsement? We'd love to hear
from you.
from you. Tech for Palestine is a volunteer-powered 501(c)(3) nonprofit, so most inboxes
below are staffed part-time — we aim to respond to general and media inquiries within
5-7 business days, and endorsement requests follow the same timeline. If your question
is about how to get involved, donate, or join the Incubator, check our <a
href="/faq-new"
class="text-brand underline hover:text-brand-hover">FAQ</a
> first — it covers the most common questions we receive.
</p>
</div>

<div class="grid grid-cols-1 gap-8 sm:grid-cols-3">
<div class="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4">
<div class="page-animate rounded-xl border border-butter bg-cream p-8">
<div class="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-sand">
<svg
Expand All @@ -54,7 +64,9 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
</div>
<h2 class="ts-heading mb-2 text-ink">General Questions</h2>
<p class="ts-body-small mb-4 text-ink-secondary">
For general inquiries about Tech for Palestine, our projects, or how to get involved.
For general inquiries about Tech for Palestine, our Incubator projects, membership,
volunteering, or how to get involved. This is also the right inbox for accessibility
requests or if you're not sure which team to reach.
</p>
<a
href="mailto:contact@techforpalestine.org"
Expand Down Expand Up @@ -83,8 +95,9 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
</div>
<h2 class="ts-heading mb-2 text-ink">Media &amp; Press</h2>
<p class="ts-body-small mb-4 text-ink-secondary">
Journalists and media professionals can find press resources and contact information
on our media page.
Journalists and media professionals can find our press kit, past coverage, and
interview contact information on our media page. For time-sensitive press inquiries,
mention your deadline in the subject line.
</p>
<a
href="/media-new"
Expand Down Expand Up @@ -113,8 +126,8 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
</div>
<h2 class="ts-heading mb-2 text-ink">Endorsements</h2>
<p class="ts-body-small mb-4 text-ink-secondary">
Seeking a T4P endorsement for your campaign or organization? Learn what we look for
and submit a request.
Seeking a T4P endorsement for your campaign or organization? We review requests within
5-7 days — learn what we look for and submit a request.
</p>
<a
href="/endorsements-new"
Expand All @@ -123,7 +136,60 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
Request an endorsement &rarr;
</a>
</div>

<div class="page-animate rounded-xl border border-butter bg-cream p-8">
<div class="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-sand">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-6 w-6 text-brand"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15 10.5a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z"
></path>
</svg>
</div>
<h2 class="ts-heading mb-2 text-ink">Registered Address</h2>
<p class="ts-body-small mb-4 text-ink-secondary">
Tech for Palestine is a registered 501(c)(3) nonprofit (EIN 99-3441367). Our full
financial and legal details are on our <a
href="/legal-new"
class="text-brand underline hover:text-brand-hover">Legal &amp; Financial Notice</a
> page.
</p>
<p class="ts-body font-medium text-ink">
548 Market St #266950, San Francisco, CA 94104-5401, US
</p>
</div>
</div>

<p class="page-animate ts-body-small mt-10 max-w-[65ch] text-ink-secondary">
Prefer social media? We're active on <a
href="https://www.instagram.com/techforpalestine"
class="text-brand underline hover:text-brand-hover"
target="_blank"
rel="noopener noreferrer">Instagram</a
>, <a
href="https://twitter.com/tech4palestine"
class="text-brand underline hover:text-brand-hover"
target="_blank"
rel="noopener noreferrer">X/Twitter</a
>, and <a
href="https://www.linkedin.com/company/techforpalestine/"
class="text-brand underline hover:text-brand-hover"
target="_blank"
rel="noopener noreferrer">LinkedIn</a
>, though email remains the fastest way to reach the right team.
</p>
</div>
</section>
</main>
Expand Down
7 changes: 4 additions & 3 deletions src/pages/donate-2-new.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ const membershipLive = getEnv("MEMBERSHIP_LIVE", Astro.locals) === "true";
---

<HomeLayout
title="Donate (Alternate Form) | Tech for Palestine"
description="Support Tech for Palestine. Your donation helps us hire professionals, strengthen existing projects, and launch new initiatives for a free Palestine."
title="Support Our Work | Tech for Palestine"
description="Alternate donation form for Tech for Palestine. Use this page if the primary donate form doesn't load in your browser."
noindex={true}
canonicalUrl="https://techforpalestine.org/donate"
>
<Fragment slot="head">
<script
type="application/ld+json"
set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "NonprofitOrganization",
name: "Tech for Palestine",
"@id": "https://techforpalestine.org/#organization",
potentialAction: {
"@type": "DonateAction",
name: "Donate to Tech for Palestine",
Expand Down
Loading
Loading