Lina Prints
A bilingual gallery marketplace for the art scene in Portugal — real checkout, real shipping, and a fee structure the artist can audit line by line.
- StatusLaunching summer 2026
- ScopeSolo — sourcing, UX, and build
- TimelineLate 2025 → summer 2026
- UseArtists onboarding via /for-artists
Full product walkthrough coming soon.
The work is here. It's on Instagram, behind a DM, or in a shop in Porto you'd have to fly to find. Discovery is a travel plan.
Portugal's art scene is extraordinary. The way you buy from it is not. Discovery happens on Instagram, payment happens over DM, and “shipping to Madeira” is a conversation, not a checkout step. The existing marketplaces take 40–50% and bury the work in a feed of generic prints. Buyers lose the plot. Artists lose the margin. And the money that should be recirculating in that ecosystem — studio rent, the next series, a reason for interesting people to keep making interesting things where they already are — leaks out to platforms built somewhere else.
A proper gallery, a real checkout, and a payout ladder the artist can audit.
Lina is a bilingual marketplace for art from Portugal. For artists, it handles print fulfilment through a local partner who takes the craft of printing seriously, EU-wide shipping, VAT, and automated payouts via Stripe Connect — at a 30% fee that sits well below the 40–50% the bigger marketplaces charge, and shown to the artist line by line. For buyers, it's a gallery experience: size and paper visualised before purchase, Apple Pay / Google Pay / MB WAY at checkout, real shipping rates for mainland Portugal, Azores, Madeira, Spain, and two EU zones, and a Portuguese interface that isn't an afterthought translation.
Built with- Next.js 16
- Sanity (dual-client)
- Stripe Connect
- NextAuth v4
- Upstash Redis
- Pino (PII redaction)
Preview panels will live here once the full case study is authored.
Three decisions did more work than anything else.
The split is a pure function, not a column.
calculatePaymentSplit() takes sale price, size, and paper type. It subtracts VAT at 23%, the print cost from the printer's rate card (€9.59 to €87.85), Stripe's card fee, Connect's payout fee, then splits the remainder 70/30. A €52 print yields the artist €15.65 and the platform €6.70 — and every step is visible.
Making this deterministic and auditable is the product's social licence to exist. Artists trust numbers they can read. And the platform fee sits well under the 40–50% the bigger marketplaces take, on purpose — so more of the money stays in the ecosystem the work came from, the reason someone has to keep making it where they already are.
Compliance as a design concern.
GDPR export and delete endpoints with their own rate limits. Cookie-free Umami analytics. Server-side price verification on every checkout — every line item re-queried from Sanity before the Stripe session is created, so client price tampering isn't a patch, it's a non-starter by architecture. Pino with a central redact list so the moment an engineer logs “the whole error object” under pressure, the logs stay clean.
None of this lives in a checklist at the end. It's the default shape of the code.
- 1 Server-side price verification. The checkout endpoint re-queries every line item from Sanity before creating the Stripe session. Client-tampered prices don't survive the request boundary — it's architecture, not a patch.
- 2 PII redaction at the logger, not the call site. One central redact list covers passwords, emails, addresses, tokens, session IDs. Defensive logging doesn't depend on an engineer remembering under pressure.
- 3 Idempotent webhooks. Stripe retries. Orders create once. The ledger reconciles to the cent.
Editors at marketing speed; the origin doesn't notice.
A dual Sanity client setup — CDN-backed read client for public pages, non-CDN write client for mutations — solves the classic headless-CMS footgun where a user writes data and then reads stale cache on the next request. ISR revalidates on a 3600s background timer, but a Sanity webhook hits /api/revalidate the instant content changes, so editors see updates in seconds, not an hour.
The effect is that the journal, new prints, and artist updates all feel live without the origin taking the beating of revalidate-on-every-request.
Launching summer 2026 — bilingual, GDPR-compliant, Stripe Connect payouts running, with a roster of artists sourced in person. The fee structure is the stance: keep more of the money in the ecosystem the work came from, so the artist making the thing has a reason to keep making it where they are.
§ Stack and specifics for the builders in the room
Littelist
A family gift-giving coordinator where Grandma doesn't need an account — one source of truth for who's buying what, and no more duplicate Lego sets at Christmas.
Start a project
No deck, no commitment. Just a conversation about what's going on.