02 / Full-stack application
2 min readPhotography Portfolio & Inquiry Application
I built and maintain a photography application that connects browsing a body of work with a reliably stored client inquiry.
Problem
Let visitors start an inquiry without requiring a finalized session plan, and retain it even if email fails.
My contribution
Portfolio structure, the inquiry flow, server validation, durable storage, and notification recovery.
Engineering focus
A successful receipt means the inquiry was stored. It does not mean a session was booked.

A real product for my photography practice
Visitors browse a series, optionally carry a visual reference into an inquiry, and start a conversation with a name and email. Dates and detailed plans can stay open.
I maintain both the photography and the application. The documented revision was developed with AI assistance; the work includes choosing the product behavior, reviewing implementation, and validating it. Next.js, libSQL, and Resend provide the underlying framework, database transactions, and email transport.
Store the inquiry before depending on email
The documented implementation validates input on the server and stores the inquiry together with pending notification state in a database transaction. A receipt represents durable storage, while email notification is tracked separately.
The handler makes a bounded initial notification attempt. Private operator tooling supports pending work and explicit retries. Accepted, failed, and uncertain outcomes remain distinct; provider acceptance alone does not establish inbox delivery.
Handle a retry as a retry
A submission carries a request ID. Database uniqueness provides duplicate protection, and normalized-content comparison distinguishes a repeated request from changed details using the same ID.
This makes uncertain responses a product concern as well as a backend concern: the interface preserves context so a visitor can understand whether they are retrying or deliberately starting a new inquiry. It is not an exactly-once email guarantee.
Give images and inquiry data separate lifecycles
A typed photo catalog and reusable series pages organize the portfolio. WebP exports and Vercel Blob handle public image delivery; Turso stores transactional inquiry and notification data.
The image delivery manifest records URLs and dimensions. This supports content-driven page generation without making a database query part of browsing the gallery. Image processing is described as an asset pipeline, not as a measured page-speed improvement.
Validation with explicit boundaries
The published engineering notes describe automated checks for malformed input, duplicate and concurrent submissions, storage failure, notification failure, and uncertain outcomes. They also document browser checks and a separately controlled email test.
These are the photography project's recorded checks, not tests rerun by this portfolio. The linked notes contain the test context and limitations; no test count or coverage percentage is claimed here.
What the application does not do
This application starts an inquiry. It does not provide payments, client accounts, live availability, or a complete booking system.
There is no automatic retry schedule in the documented implementation. Pending, failed, and uncertain notifications require operator review. Session details are confirmed separately with the client.