Skip to content
Open
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
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

This repository contains the source code for the official landing page of **TinyPaws.com**.

TinyPaws is an upcoming platform dedicated to helping pet parents preserve and cherish every moment of their pet's life. It offers a beautiful and private space to create a complete digital storybook for your beloved animal companions, capturing photos, videos, milestones, and memories.
TinyPaws is an upcoming platform for pet parents to keep their pet's care, memories, and trusted people in one private place. It combines a practical care page for routines, sitter instructions, medication, vet details, and emergency notes with a private timeline for photos, diary entries, milestones, and family updates.

**Key Information:**

- **Launch:** TinyPaws is scheduled to launch in **Late 2025**.
- **Launch:** TinyPaws is being rebuilt for a 2026 beta around three entry doors: the core TinyPaws hub, TinyPaws Care, and TinyPaws Share.
- **Brand:** TinyPaws is a proud brand under the [Nutrified](https://www.nutrified.com) umbrella, sharing the same commitment to thoughtful pet care.
- **Purpose:** This landing page serves to introduce TinyPaws, showcase its features, and allow interested users to join the waitlist for early access and exclusive perks.
- **Purpose:** These landing pages test which entry point converts best while keeping one product underneath:
- `index.html` - general private pet hub positioning
- `care.html` - sitter, family, travel, routine, medication, and vet-handoff intent
- `share.html` - diary, memory, milestone, family update, and recap intent

## Tech Stack

Expand Down
2 changes: 2 additions & 0 deletions _redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/care /care.html 200
/share /share.html 200
779 changes: 779 additions & 0 deletions care.html

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion functions/api/join-waitlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export async function onRequest(context) {

try {
const body = await request.json();
const { email, name, petName, petType } = body;
const { email, name, petName, petType, interest, updates } = body;

// Basic validation
if (!email || !isValidEmail(email)) {
Expand Down Expand Up @@ -107,6 +107,8 @@ export async function onRequest(context) {
name: name.trim(),
petName: petName.trim(),
petType: petType.trim(),
interest: typeof interest === "string" ? interest.trim() : "",
updates: Boolean(updates),
signupDate: new Date().toISOString(),
referer: request.headers.get("Referer"),
};
Expand Down
221 changes: 122 additions & 99 deletions index.html

Large diffs are not rendered by default.

27 changes: 9 additions & 18 deletions script.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ document.addEventListener("DOMContentLoaded", function () {
});

// Handle main form submission
const mainWaitlistForm = document.querySelector(".hero-cta .waitlist-form");
const mainWaitlistForm = document.querySelector(".waitlist .waitlist-form");
const mainFormError = document.getElementById("main-form-error");
const mainFormSuccess = document.getElementById("main-form-success");

Expand All @@ -94,6 +94,8 @@ document.addEventListener("DOMContentLoaded", function () {
const name = document.getElementById("name").value.trim();
const petName = document.getElementById("pet-name").value.trim();
const petType = document.getElementById("pet-type").value;
const interest = document.getElementById("interest")?.value || "";
const updates = document.getElementById("updates")?.checked ?? false;

// Basic validation
if (!email) {
Expand Down Expand Up @@ -133,6 +135,8 @@ document.addEventListener("DOMContentLoaded", function () {
name,
petName,
petType,
interest,
updates,
}),
});

Expand Down Expand Up @@ -171,6 +175,8 @@ document.addEventListener("DOMContentLoaded", function () {
const name = document.getElementById("popup-name").value.trim();
const petName = document.getElementById("popup-pet-name").value.trim();
const petType = document.getElementById("popup-pet-type").value;
const interest = document.getElementById("popup-interest")?.value || "";
const updates = document.getElementById("popup-updates")?.checked ?? false;

// Basic validation
if (!email) {
Expand Down Expand Up @@ -210,6 +216,8 @@ document.addEventListener("DOMContentLoaded", function () {
name,
petName,
petType,
interest,
updates,
}),
});

Expand Down Expand Up @@ -313,23 +321,6 @@ document.addEventListener("DOMContentLoaded", function () {
});
});

// We've already handled the main waitlist form above, so this is no longer needed
// If there are any other waitlist forms on the page that aren't handled yet
const otherWaitlistForms = document.querySelectorAll(
".waitlist-form:not(.hero-cta .waitlist-form)"
);

otherWaitlistForms.forEach((form) => {
if (form !== mainWaitlistForm) {
// Avoid handling the same form twice
form.addEventListener("submit", function (e) {
e.preventDefault();
// Open the popup instead
openWaitlistPopup();
});
}
});

// Helper function to validate email
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
Expand Down
Loading