Technology Stack
Next.js 16 (App Router), React 19, TypeScript strict, Tailwind CSS 4, shadcn/ui, Base UI, class-variance-authority, tailwind-merge, Lucide, dotLottie, Wistia embeds, self-hosted webfonts, ESLint, Docker, GitHub Actions, Vercel
Overview
Duration: 7/2026 - 8/2026
Easytools is a commerce suite for creators selling digital products — one-page checkout, an AI site builder, email campaigns, a course player, testimonial collection — all settling directly onto the seller's own Stripe account. Its product surface is correspondingly large: a page per tool, a page per capability, a page per thing a creator might sell, plus resources, comparisons, and legal.
This project delivers that surface end to end on a modern stack, together with the authenticated seller dashboard behind it: 194 components, two distinct design systems, and a full commerce information architecture.
The engineering story is the process. A product surface this wide cannot be built by eye — the twentieth section drifts from the first, and by the time anyone notices, the drift is everywhere. So the work was made measured rather than estimated, and that is what made it converge.
Specification Before Implementation
The pipeline runs the browser first and the editor second. Every screen is opened under automation, captured, swept for interaction states — scroll, click, hover, and each responsive breakpoint — and interrogated for computed style, so what lands in the repository is measurements rather than impressions.
Those measurements become specification files. Fifty-eight of them, one per section, and they read like this:
H1 — font "Borna Webfont" (bold 700), 56px, line-height 64.4px, base colour
#0E534C, accent span#00A18B. Media shell — background#fff,border-radius: 12px,box-shadow: 0 0 0 8px rgba(0,0,0,0.05)(a soft ring, not a drop shadow).
Each spec carries DOM structure, exact values, interaction model, multi-state content, responsive behaviour, and asset inventory — enough that a section can be built without consulting anything else. Sections were then built in parallel, one worker per spec in an isolated branch, and merged back.
The specs also record what not to build. One hero spec closes its interaction note with an explicit instruction against reproducing a live element as a static mockup, because the correct behaviour is a poster swap after load. Writing the trap down is what stops a parallel build from walking into it.
This is a QA method as much as a build method: for any section, the spec is the acceptance criteria, and "does it match" has a numeric answer rather than an opinion.
Architecture Planning
Before each batch of pages, a topology document worked out what was genuinely new. The one covering the cart, player, and site-builder pages opens by confirming through structural comparison that all three share the homepage's header and footer exactly, then sorts every remaining section into three buckets: reuse unchanged, reuse with page-specific data, or build new.
The result is a small component set behind a wide surface. Shared sections were parameterised with their homepage content as the default value, so pages needing different content pass props and the homepage keeps working untouched. Per-product accent colours stayed scoped rather than being promoted to global tokens, matching the convention already established in the design system.
Product Surface
- Homepage — hero, tool-suite grid, product demo, integrations marquee, testimonial wall, resource tabs, FAQ, and conversion block
- Product pages — the full tool suite, current and legacy
- Capabilities — thirteen pages: one-click purchase, pricing models, checkout recovery, customer portal, digital delivery, gated content, global tax and invoicing, QR ticketing, sales automation, and more
- Solutions — twelve pages framed by what a creator sells (courses, ebooks, SaaS licences, events, subscriptions, templates) or what they want (higher checkout conversion, automated sales, global selling, compliance)
- Pricing — a billing-period toggle lifted into shared context so the plan cards and the full comparison table switch together
- Resources and legal — blog, guides, case study, competitor comparison, contact, about, FAQ, and three legal documents behind one shared layout
The Seller Dashboard
The second half of the project is everything behind the login: products, orders, customers, discount codes, campaigns and audiences, courses, testimonials, waitlists, automations, analytics, reports, partners, store settings, and the legacy tool editors.
The dashboard runs a different design system from the public surface — its own greys, its own radius scale, its own inset-panel shell — so it received its own token extraction, captured and written down as a utility-to-value map before anything was built. Every observed screen was a fresh account, which made empty states the primary state to design for rather than an afterthought — the right priority, since an empty dashboard is exactly what every new seller sees first.
One decision from that build is representative. The analytics screen draws its charts on canvas through a charting library; on a fresh account, every series is flat at zero. The implementation draws inline vector instead — gridlines and a single stroke — with the reasoning recorded: shipping a charting runtime to render a straight line is weight without value. Matching an appearance and matching an implementation are different goals, and the spec-driven approach makes it explicit which one is being pursued.
Build Characteristics
- Server-first — 29 of 194 components are client components; everything else renders on the server
- Animation without SSR breakage — the Lottie runtime touches browser globals on import, so it is loaded dynamically inside a client effect with a poster image holding the layout until it mounts
- Fully self-contained — batch scripts pull every image, icon, animation, and font into the repository, so the build has no runtime tether to any external origin
- Self-hosted typography through the framework's local font pipeline
- Typed design tokens — the palette declared once and consumed as utilities, with the radius scale derived from a single value
- Standalone output with a multi-stage container build and a compose file covering both production and development
- CI as the gate — lint, typecheck, and a full production build on every push and pull request
The takeaway from building at this width: leverage is not in writing components faster. It is in refusing to start one until the thing it must match has been measured, written down, and checked for what it does not need.