Case study · Full-stack web application
La Marée Malouine
I designed a Click & Collect application connecting online orders to a fishmonger’s daily operations, from choosing products to collecting them in the shop.
- Click & Collect
- React
- TanStack Start
- PostgreSQL
- Stripe
- Brevo
- GitLab CI/CD
Bringing the local shop online.
- Choose
Build a basket from the catalogue and current offers.
- Book & pay
Choose a collection slot, then pay through Stripe.
- Collect
Receive confirmation, then collect the order from the shop.
- My role
- Full-stack development
Customer journey, administration, business logic and payment and email integrations.
- Scope
- Website and management tools
Catalogue, ordering, shop collection, stock and customer history in one application.
- Technical challenge
- Reliable ordering
Reserve stock and collection slots, confirm payments and handle retries without duplicates.
For the merchant: everyday management tools
Screenshots of the application running locally with fictional data. Demo orders illustrate payment on collection; the online journey integrates Stripe Checkout.
Enlarge screenshotTrack each order through to collection
Statuses and preparation actions share one screen. The merchant can find an order, mark it ready and record its collection.
Enlarge screenshotManage the catalogue and stock
Prices, quantities, availability and visibility are managed from the catalogue. Out-of-stock products are immediately identifiable.
The need: order and pay online, collect in store
The fishmonger needed to present fresh arrivals, promote special offers and receive orders for defined pickup slots. The experience had to be simple on mobile, with a catalogue the merchant could update every day without technical help.
- Browse products and place an order from a phone.
- Choose a pickup slot with capacity suited to preparation.
- Card payment through Stripe Checkout, with a final total shown before confirmation.
Sprints with a review every week
Development was organised into sprints, with a weekly review to demonstrate completed features and discuss progress. These demonstrations made the work tangible: we could walk through the screens, discuss how they worked and consider the next steps. This regular rhythm provided opportunities to check the application against the fishmonger’s needs throughout the project.
A customer journey through to collection
Visitors browse the catalogue and build their selection. Ordering has three steps: basket, pickup slot and contact details. They then pay by card on the Stripe-hosted page. Once the server verifies payment, the order moves to preparation; the merchant marks it ready, then collected.
- Filterable catalogue and promotions displayed on relevant products.
- Summary of quantities, prices and pickup location.
- Payment confirmation, ready-for-collection and cancellation emails through Brevo.
A dashboard for daily operations
A protected administration area brings routine tasks together. The merchant manages deliveries and stock movements, organises pickups, tracks payments and views customer order history.
- Create and edit products, photos, prices and availability, and track stock movements.
- Schedule promotions and generate recurring slots with limited capacity.
- Track orders and payments, cancel with a Stripe refund and retry failed refunds.
- Customer records with order history and CSV export of email addresses.
- Search and filter customer messages, reply from the dashboard, and update contact details and opening hours.
Reserved stock and server-verified payments
The server recalculates prices and promotions, then reserves stock and a pickup place within a PostgreSQL transaction for around 30 minutes. Payment is confirmed through signed Stripe events or periodic server checks. Verified expiry releases reservations; retries avoid creating a second order or repeating a payment operation.
- Webhook signature verification and handling of duplicate events.
- Refund tracking and automatic retries for pending operations.
- Notifications saved with the order and sent in the background through Brevo, with retries and delivery tracking.
Security: protecting access to administration
The merchant dashboard provides access to orders and customer data. I integrated two-step authentication: a password, followed by a temporary authenticator app code (TOTP) or a WebAuthn passkey. An administrator session is only created once the complete flow has been validated.
- TOTP replay protection and login rate limits per account and IP address.
- Management of sign-in methods and single-use recovery codes, with only their hashes stored in the database.
- Identity verification before security changes, revocation of other sessions and an audit trail of changes.
- Server-side input validation and permission checks, scrypt password hashing and HttpOnly session cookies.
Clear responsibilities and indexable pages
React, TypeScript and TanStack Start handle the interface and server rendering. Routes compose pages, services implement business rules, and data access modules use Drizzle ORM and PostgreSQL. This separation supports changes to customer and merchant workflows without mixing presentation and persistence.
- Tailwind CSS for layouts that adapt to mobile and desktop.
- Metadata, canonical URLs, sitemap and structured data for public pages.
- GitLab CI/CD pipeline: automated tests, Docker image build and scanning with Trivy, then VPS deployment for protected tags.
- Maintenance mode controlled from the dashboard, keeping merchant access available.
Testing: checking scenarios that can fail
The suite combines unit tests, PostgreSQL integration tests and a Playwright browser flow. It targets business rules, access controls and recovery after failures, including cases where two orders compete for the last available collection slot.
- Business rules: quantities, fees, collection slots and order transitions.
- PostgreSQL integration: concurrent orders, stock, collection capacity and duplicate prevention. Payment tests use the real database with simulated Stripe calls for confirmation, expiry, retries and refunds.
- Security and browser: access denied before the second factor, TOTP setup, rejection of reused codes, WebAuthn passkeys and account security management.
- Delivery: GitLab CI prepares dedicated test databases and runs migrations, tests, builds, TypeScript checks and HTML/SEO checks. The Playwright flow has a separate command.
Delivery and handover
The site is online, with management tools for the merchant to populate the catalogue and organise pickups. A user guide documents everyday operations. The project also includes an action history, backup export and a restoration procedure reserved for the operator.
- A merchant guide for daily operations.
- Backup export and a restoration procedure, with a dedicated integration test.
Visit the website · Explore the code
Explore further
Let’s start with your needs.
Your goal, your deadline, the tools you use: a few lines are enough to start the conversation.
Describe my project