diff --git a/apps/frontend/src/features/waitlist/components/WaitlistModal.test.tsx b/apps/frontend/src/features/waitlist/components/WaitlistModal.test.tsx
deleted file mode 100644
index ee85ef18..00000000
--- a/apps/frontend/src/features/waitlist/components/WaitlistModal.test.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { afterEach, describe, expect, it, vi } from 'vitest';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
-import { waitlistService } from '@/shared/services/api';
-import { ApiError } from '@/shared/services/api';
-import { WaitlistModal } from './WaitlistModal';
-
-describe('WaitlistModal', () => {
- afterEach(() => {
- vi.restoreAllMocks();
- });
-
- it('submits the entered email and optional name, then shows a confirmation', async () => {
- const join = vi.spyOn(waitlistService, 'join').mockResolvedValue({ status: 'ok' });
- const onClose = vi.fn();
-
- render();
-
- fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'visitor@example.com' } });
- fireEvent.change(screen.getByLabelText(/Name/), { target: { value: 'Visitor Name' } });
- fireEvent.click(screen.getByRole('button', { name: 'Join the waitlist' }));
-
- await waitFor(() =>
- expect(join).toHaveBeenCalledWith({ email: 'visitor@example.com', name: 'Visitor Name' }),
- );
- expect(await screen.findByText("You're on the list")).toBeVisible();
- expect(onClose).not.toHaveBeenCalled();
- });
-
- it('submits without a name when the optional field is left blank', async () => {
- const join = vi.spyOn(waitlistService, 'join').mockResolvedValue({ status: 'ok' });
-
- render();
-
- fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'no-name@example.com' } });
- fireEvent.click(screen.getByRole('button', { name: 'Join the waitlist' }));
-
- await waitFor(() => expect(join).toHaveBeenCalledWith({ email: 'no-name@example.com', name: undefined }));
- });
-
- it('shows an error and does not confirm when the request fails', async () => {
- vi.spyOn(waitlistService, 'join').mockRejectedValue(
- new ApiError(422, 'Request validation failed.', null, '/waitlist'),
- );
-
- render();
-
- fireEvent.change(screen.getByLabelText('Email'), { target: { value: 'rejected@example.com' } });
- fireEvent.click(screen.getByRole('button', { name: 'Join the waitlist' }));
-
- expect(await screen.findByRole('alert')).toBeVisible();
- expect(screen.queryByText("You're on the list")).not.toBeInTheDocument();
- });
-
- it('calls onClose when Close is clicked before submitting', () => {
- const onClose = vi.fn();
- render();
-
- fireEvent.click(screen.getByRole('button', { name: 'Close' }));
-
- expect(onClose).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/apps/frontend/src/features/waitlist/components/WaitlistModal.tsx b/apps/frontend/src/features/waitlist/components/WaitlistModal.tsx
deleted file mode 100644
index ef76ac84..00000000
--- a/apps/frontend/src/features/waitlist/components/WaitlistModal.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-import { useState } from 'react';
-import { Loader2 } from 'lucide-react';
-import { useWaitlistForm } from '../hooks/useWaitlistForm';
-import { cn } from '@/shared/utils/cn';
-
-interface WaitlistModalProps {
- onClose: () => void;
- /** Landing page's own resolved theme (see LandingPage.tsx) -- this modal
- * has no theme awareness of its own, and the light-mode classes below
- * are left as literal hex rather than switched to tokens, so light-mode
- * output stays pixel-identical to before this prop existed. */
- dark?: boolean;
-}
-
-export function WaitlistModal({ onClose, dark = false }: WaitlistModalProps) {
- const [submitted, setSubmitted] = useState(false);
- const { email, setEmail, name, setName, submitting, error, submit } = useWaitlistForm(() => setSubmitted(true));
-
- return (
-
-
- {submitted ? (
-
-
- You're on the list
-
-
- PARTHA is currently in a small, invite-only beta. We'll reach out by email when there's room for you.
-
-
-
- ) : (
- <>
-
-
-
- Beta waitlist
-
-
- Join the waitlist
-
-
-
-
-
- PARTHA is invite-only while we work directly with a small group of engineering teams. Leave your email
- and we'll follow up when there's room.
-
-
- >
- )}
-
-
- );
-}
diff --git a/apps/frontend/src/features/waitlist/hooks/useWaitlistForm.ts b/apps/frontend/src/features/waitlist/hooks/useWaitlistForm.ts
deleted file mode 100644
index ea962650..00000000
--- a/apps/frontend/src/features/waitlist/hooks/useWaitlistForm.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useState, type FormEvent } from 'react';
-import { getErrorMessage, waitlistService } from '@/shared/services/api';
-
-export function useWaitlistForm(onSuccess: () => void) {
- const [email, setEmail] = useState('');
- const [name, setName] = useState('');
- const [submitting, setSubmitting] = useState(false);
- const [error, setError] = useState(null);
-
- const submit = async (event: FormEvent) => {
- event.preventDefault();
- if (submitting) return;
- setSubmitting(true);
- setError(null);
- try {
- await waitlistService.join({ email: email.trim(), name: name.trim() || undefined });
- onSuccess();
- } catch (caught) {
- setError(getErrorMessage(caught));
- } finally {
- setSubmitting(false);
- }
- };
-
- const reset = () => {
- setEmail('');
- setName('');
- setError(null);
- };
-
- return { email, setEmail, name, setName, submitting, error, submit, reset };
-}
diff --git a/apps/frontend/src/shared/services/api/index.ts b/apps/frontend/src/shared/services/api/index.ts
index 572f2e8c..df0b2661 100644
--- a/apps/frontend/src/shared/services/api/index.ts
+++ b/apps/frontend/src/shared/services/api/index.ts
@@ -12,7 +12,6 @@ export { reviewService } from './review';
export { dependencyService } from './dependencies';
export { aiService } from './ai';
export { documentationService, exportService } from './documentation';
-export { waitlistService } from './waitlist';
export type * from './types';
export type * from './generated';
diff --git a/apps/frontend/src/shared/services/api/waitlist.test.ts b/apps/frontend/src/shared/services/api/waitlist.test.ts
deleted file mode 100644
index 176dc341..00000000
--- a/apps/frontend/src/shared/services/api/waitlist.test.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { describe, expect, it, vi } from 'vitest';
-import { api } from './client';
-import { waitlistService } from './waitlist';
-
-vi.mock('./client', () => ({
- api: { get: vi.fn(), post: vi.fn(), put: vi.fn(), patch: vi.fn(), delete: vi.fn() },
-}));
-
-describe('waitlistService', () => {
- it('join posts the request body to /waitlist', async () => {
- const request = { email: 'a@b.com', name: 'A' };
- const response = { status: 'confirmed' };
- vi.mocked(api.post).mockResolvedValue(response);
-
- const result = await waitlistService.join(request as never);
-
- expect(api.post).toHaveBeenCalledWith('/waitlist', request, undefined);
- expect(result).toBe(response);
- });
-
- it('propagates a rejected request (e.g. a duplicate signup) rather than swallowing it', async () => {
- const error = new Error('already on the waitlist');
- vi.mocked(api.post).mockRejectedValue(error);
-
- await expect(waitlistService.join({} as never)).rejects.toBe(error);
- });
-});
diff --git a/apps/frontend/src/shared/services/api/waitlist.ts b/apps/frontend/src/shared/services/api/waitlist.ts
deleted file mode 100644
index aaadaef0..00000000
--- a/apps/frontend/src/shared/services/api/waitlist.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { api } from './client';
-import type { RequestConfig } from './client';
-import type { WaitlistSignupRequest, WaitlistSignupResponse } from './types';
-
-export const waitlistService = {
- join(request: WaitlistSignupRequest, config?: RequestConfig): Promise {
- return api.post('/waitlist', request, config);
- },
-};