Pals of Paws Society

Pals of Paws Society is a nonprofit organization headquartered in Northwest Mississippi. They specialize in arranging animal adoptions, transports, and spay and neuter services in an effort to reduce pet overpopulation in the area. My wife is very active with the organization, so I chose to build this website for the organization at no charge to build experience for myself and as a chariable contribution to the organization and its purpose. I designed, developed, deployed, and even wrote most of the copy for the website.
The website is mostly static, with some backend functionality in a couple places:

1. The animal adoptions section, which displays data pulled form Shelterluv and Petfinder.

2. The donations section, which accepts donation via Stripe's embedded Payment Element component.

3. A fundraisers section, which displays current and past events using next-mdx-remote.

Adoptions Section

As part of the organization's mission to reduce pet overpopulation, they opted to display any and all pets available for adoption on their website, in the hopes that it may help some local residents find a pet. They also have their own account with the service Shelterluv, and using that as a CMS they can add or remove any pet adoptions that they directly manage.

The Petfinder and Shelterluv APIs predictably do not follow the same schema. Additionally, the data coming from Petfinder is a bit messy, driven by the local organizations that post their animals through the service. For example, some may be listed multiple times, some in all caps, some with asteriks or HTML character codes in the name. Therefore I chose to hardcode some logic that "fixes" a lot of those inconsistencies, giving the website a cleaner look.

I used the adapter pattern with Typescript to combine both services into a common "Animal" type interface, with which I could then display the animals side-by-side.

For the adoptions page itself, I opted to display all the animals with pagination and use shallow routing to display more images and details about a particular animal when a user clicks on them. This meant that I only needed to make one set of API calls to fetch all the animal data and have it available on the page, with a revalidate time of one hour.

The downside of this approach is that the page has a very large file size - withover 300 animals loaded statically on the client-side. This has had a negative impacton the Lighthouse performance scores for the page.

However, due to the nature of the data (where the number of animals queried from Petfinder does not necessarily equal the number delivered to the page) and Petfinder's limit of 1000 requests per day, all the other methods I tried (including client-side rendering and serverless Redis caching) either resulted in the pages having longer loading times or the website exceeding the API request limit. Having the client statically load all the data and using shallow routing to persist that data, while slightly heavier on performance, resolved all the issues I had with managing the API requests.

One aspect of this page that I think could be improved upon is the way I solved the problem of managing scroll position. The desired behavior is for the user, after clicking an animal and then navigating back, is for them to be scrolled to the exact scroll position and page from which they left. While supposedly Next is supposed to do this out of the box (at least for scroll position) it was not working with my shallow routing solution. So they way I solved it is to include the former scroll position and page into the route query (hidden from the user using the "href" / "as" parameter in the page routing) and sending it back when the user clicks "Back to Results". This works, but it feels hacky. Also, if the user clicks "Back" in their browser rather than clicking "Back to Results", this solution does not work, so I may go back to the drawing board on this.