月商1万ドル($10K)のECプラットフォームを構築した
月商 $10,000 · 創業者3人 · 従業員10人 · Singapore
Arnaud Touret(Founder, UPPFIRST)· 創業 July 2022 · 記事掲載 February 16th, 2025 · uppfirst.com · 元の記事
初期はファッションブランドに特化し、ファッションウィークなどのイベントと連携して露出を増やした。著名ブランドとのパートナーシップやVogue Businessなどの媒体での報道、Instagramでの発信が主な集客源。ポジティブなメディア報道後、一晩で約100件の新規登録があったため、個別にフォローアップした。月商1万ドル(約150万円)は2025年の記事時点の自己申告。
売値の出典: 記事の本文(2025年時点)(2026-10-13 取得)
I’m Arnaud Touret, the founder of UPPFIRST, a commerce platform that makes selling online easier and more effective. We help brands, creators, and businesses sell in-stock, made-to-order, and pre-sell products with a powerful, intuitive setup—no coding, no unnecessary plugins, just a smarter way to sell. What sets UPPFIRST apart is our one-step checkout, designed to remove friction and boost conversions. Nicki Minaj used UPPFIRST to launch her sneaker collection, achieving a record sales conversion rate of 8.7%—proving the impact of our model. In just six months, sellers on UPPFIRST have already done over $1 million in sales. My image
Skills What skills did Arnaud Touret have that led to their success? no-code custom-checkout
The idea for UPPFIRST came from firsthand experience with the challenges of selling online—especially for emerging brands. The industry relies on upfront inventory investment, outdated wholesale models, and high-risk production cycles, making it difficult for brands to sell efficiently and maintain cash flow. With a background in software development, I had always seen tech as the backbone of any business I was involved in. My co-founders brought direct experience in fashion, which was our first target industry. Together, we saw an opportunity to build a more adaptable, intuitive commerce platform. We validated UPPFIRST through user testing and iteration. It started as a pre-order-only platform, helping fashion brands monetize runway shows through immediate pre-orders with a two-part payment system. This approach improved cash flow and provided forward-looking consumer data without requiring upfront inventory. Continuous feedback drove our expansion. Brands loved UPPFIRST’s ease of use, intuitive design, and powerful functionality, leading us to introduce in-stock support, wholesale capabilities, and comprehensive site-building tools. Today, UPPFIRST is a full-service e-commerce solution, giving brands at all levels the ability to sell smarter and grow efficiently.
Step-by-Step Process of Building UPPFIRST Discovery & Planning (100 Hours Deep Dive) We started with a 100-hour discovery phase, going deep into market research, mapping out the platform, and challenging every assumption we had. We didn’t just want to build another e-commerce tool—we wanted to create something that actually solved real problems for sellers. Building the MVP (Outsourced Development) With a solid concept in place, we partnered with an outsourced development team to build the first version of UPPFIRST. This allowed us to move quickly while keeping costs manageable. The first iteration was pre-order focused, giving brands a two-part payment system to improve cash flow and capture demand early. Early Launch & User Testing Once we had a working MVP, we brought in launch partners and early users to test it. Their feedback shaped everything—we iterated, refined, and adapted based on real-world seller needs. Seeing brands engage and convert on UPPFIRST confirmed that we were onto something scalable. Raising a Pre-Seed Round & Bringing Tech In-House With strong early traction, we raised a pre-seed round and used that funding to bring tech in-house. This was a pivotal moment—hiring our own product team gave us more control, more speed, and the ability to scale UPPFIRST the right way. Evolving the Business Model At first, we only charged a transaction fee on successful sales to make it as easy as possible for sellers to try the platform. But after a year of testing, we introduced an affordable $9.99/month subscription model—low enough to remain accessible but sustainable for long-term growth. Expanding Beyond Pre-Orders UPPFIRST started as a pre-order-only platform, but seller demand pushed us to expand fast. We introduced in-stock selling, made-to-order, wholesale capabilities, and full storefront tools, transforming UPPFIRST into a complete e-commerce solution. What It Was Like to Build the First Version Building the first version wasn’t easy. There were countless iterations, unexpected challenges, and tough decisions. But outsourcing the MVP gave us room to make early mistakes without long-term technical debt. Once we nailed our ideal customer profile (ICP) and product-market fit, bringing everything in-house made us faster, sharper, and more effective. We self-funded up until our pre-seed round, covering development and operations through personal savings. It was a challenging but essential process—one that shaped how we build today. UPPFIRST is now built for scale, and every iteration has brought us closer to delivering the best possible experience for our sellers. My image
Our first launch partner was HEAT.io, who used UPPFIRST to pre-sell their luxury mystery boxes, for a special drop featuring pieces from the Vetements archive. To maximize impact, we paired the launch with an event, generating press and media attention that helped drive engagement. The response was immediate—the entire drop sold out within the first hour. That first sale happened right there at launch, proving that UPPFIRST could handle high-traffic, high-demand releases. From there, we built on the momentum—leveraging the credibility of our first launch to onboard more brands and continue refining the platform. The biggest lesson? You just have to start. The product will never be perfect at launch, but the sooner you put it into the world, the faster you learn and improve. Looking back, we wouldn’t change that approach. The launch gave us early authority and recognition, and when challenges came up, we learned that we could pull out all the stops to deliver—a mindset that still drives UPPFIRST today.
A key growth strategy has been aligning with fashion brands that already have engaged audiences, particularly those launching collections during high-visibility moments like fashion weeks. Partnering with brands like Chet Lo , LGN, Ahluwalia, Roksanda, Paolina Russo, Zomer and Heliot Emil helped introduce UPPFIRST to their communities when interest and content output were at their peak. We amplified these moments across social media and secured press coverage in publications like Vogue Business and 1 Granary, which led to people proactively discovering and reaching out to us. Instagram has been a highly effective channel, allowing us to engage directly with our followers and connect with new brands. Following a positive media spotlight, we had around 100 new sign-ups on the platform over night. Instead of leaving them to figure things out alone, we personally reached out to every single one, understanding their pain points and improving the product to serve them better. The biggest lesson? Persistence pays off. Don’t be afraid to hustle, reach out, follow up, and fire moonshots—some of our most valuable partnerships came from taking a chance and putting ourselves forward. If you believe in your product, punch above your perceived weight.
One of the biggest lessons we learned was to keep as much in-house as possible. Early on, we relied on agencies and external partners, assuming their expertise would accelerate growth. In reality, no one cares as much as you do—outsourcing too much slowed us down, diluted our vision, and wasted resources. Bringing key functions in-house made us faster, sharper, and more effective. The biggest mistake we see? Trying to perfect the product before launching. You’ll learn more from real users in one month of testing than in six months of planning. Another key lesson? Momentum matters. We launched before we felt “ready,” but that first launch created credibility, opportunities, and learnings we couldn’t have gained by waiting. If you believe in what you’re building, start now. We also learned the value of working with people you know and trust. Building a business is tough, and having the right team—people who are aligned, adaptable, and as invested as you are—makes all the difference. Startups require fast decisions and constant pivots, and that’s only possible when you work with people who truly understand the vision. Finally, persistence pays off—many of our biggest wins came from simply following up, taking chances, and punching above our perceived weight. Hustle, fire moonshots, and don’t underestimate what’s possible when you put yourself out there.
Custom Built Stack 232 using newDocumentReady(function () { $(".database-result-bottom").unbind().click(function() { $(this).find(".database-result-bottom-contents").toggle(); }) // Mobile DB view toggle — switch between the compact row list (default) // and the rich card view, remembered in localStorage. Instant, no reload. // Leading ';' guards against ASI: the preceding statement ends in `})`. ;(function () { var group = document.querySelector('.db-view-toggle-group'); if (!group) return; var rowsPanel = document.getElementById('db-view-rows'); var cardsPanel = document.getElementById('db-view-cards'); function applyView(view) { var isCards = view === 'cards'; if (cardsPanel) cardsPanel.classList.toggle('hidden', !isCards); if (rowsPanel) rowsPanel.classList.toggle('hidden', isCards); group.querySelectorAll('.db-view-toggle').forEach(function (b) { b.classList.toggle('db-view-toggle-active', b.dataset.view === view); }); } var saved = 'rows'; try { saved = window.localStorage.getItem('dbMobileView') || 'rows'; } catch (e) {} applyView(saved === 'cards' ? 'cards' : 'rows'); group.querySelectorAll('.db-view-toggle').forEach(function (b) { b.addEventListener('click', function () { var v = b.dataset.view; try { window.localStorage.setItem('dbMobileView', v); } catch (e) {} applyView(v); }); }); })(); // Search UX: debounced auto-submit + global "/" focus shortcut. // Server-side pg_search is GIN-indexed and returns in <50ms; combined // with the page render, total feedback after the debounce window is // ~500ms — close enough to "live" without an XHR/Turbo refactor. var searchInput = document.getElementById('search'); if (searchInput) { var debounceTimer = null; var lastSubmittedValue = searchInput.value; searchInput.addEventListener('input', function () { clearTimeout(debounceTimer); debounceTimer = setTimeout(function () { // Don't submit if the value hasn't changed (e.g. arrow keys). if (searchInput.value === lastSubmittedValue) return; lastSubmittedValue = searchInput.value; searchInput.form && searchInput.form.submit(); }, 350); }); // Enter still submits immediately — short-circuits the debounce. searchInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); clearTimeout(debounceTimer); searchInput.form && searchInput.form.submit(); } }); } // Global "/" shortcut to focus search — GitHub/Linear pattern. document.addEventListener('keydown', function (e) { if (e.key !== '/' || e.metaKey || e.ctrlKey || e.altKey) return; var t = e.target; if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable)) return; var s = document.getElementById('search'); if (s) { e.preventDefault(); s.focus(); s.select(); } }); function prettySliderValue(func, value) { var n = Math.round(Number(value)); if (func == "money") { if (n >= 1000000000) return "$" + (n / 1000000000).toFixed(n % 1000000000 === 0 ? 0 : 1) + "B"; if (n >= 1000000) return "$" + (n / 1000000).toFixed(n % 1000000 === 0 ? 0 : 1) + "M"; if (n >= 1000) return "$" + (n / 1000).toFixed(n % 1000 === 0 ? 0 : 1) + "K"; return "$" + numberWithCommas(n); } else if (func == "daystomonths") { return (n / 30) + " months"; } else if (func == "hours") { return n + " hours"; } else { return n; } } function getInitialSliderValues(el) { var initial = el.dataset.initial; var defMin = Number(el.dataset.defaultmin); var defMax = Number(el.dataset.defaultmax); if (initial) { var parts = initial.split("|"); var a = parts[0] === "" ? defMin : Number(parts[0]); var b = parts[1] === "" ? defMax : Number(parts[1]); return [a, b]; } return [defMin, defMax]; } function createTwoProngedSlider(id) { var el = document.querySelector(id); if (!el || el.noUiSlider) return; var min = Number(el.dataset.min); var max = Number(el.dataset.max); var step = Number(el.dataset.step); var cleanfunc = el.dataset.cleanfunc; var values = getInitialSliderValues(el); var container = el.closest(".range-filter") || el.parentElement; var input = container.querySelector('input[type="hidden"]'); var label = container.querySelector(".preview-label"); noUiSlider.create(el, { start: values, connect: true, step: step, range: { min: min, max: max }, behaviour: "tap-drag" }); el.noUiSlider.on("update", function(vals) { var lo = Math.round(Number(vals[0])); var hi = Math.round(Number(vals[1])); if (label) label.textContent = prettySliderValue(cleanfunc, lo) + " – " + prettySliderValue(cleanfunc, hi); if (input) input.value = lo + "|" + hi; }); el.noUiSlider.on("change", function() { var form = el.closest("form"); if (form) form.submit(); }); } createTwoProngedSlider("#revenue-slider"); createTwoProngedSlider("#starting-costs-slider"); createTwoProngedSlider("#time-to-revenue-slider"); createTwoProngedSlider("#min-hours-per-week"); createTwoProngedSlider("#market-size"); createTwoProngedSlider("#startup-costs"); createTwoProngedSlider("#case-studies"); $(".mobile-filters-applied-button").click(function() { $(".database-filters").addClass("inView") }) $(".close-mobile-filters").click(function() { $(".database-filters").removeClass("inView") }) // Explore "More filters" — reveal/hide the secondary filter pills. var moreFiltersToggle = document.getElementById("explore-more-filters-toggle"); if (moreFiltersToggle) { moreFiltersToggle.addEventListener("click", function () { var panel = document.querySelector(".explore-secondary-filters"); if (!panel) return; var nowHidden = panel.classList.toggle("hidden"); moreFiltersToggle.setAttribute("aria-expanded", String(!nowHidden)); }); } // Infinite scroll lives in its OWN init block below (initSSInfiniteScroll), // deliberately decoupled from this newDocumentReady callback. Anything that // throws above (a slider lib that didn't load from CDN, a jQuery plugin, // etc.) would otherwise abort the rest of THIS callback and silently kill // infinite scroll — the "only works on a hard reload" bug. Keeping it // separate means nothing here can take it down. }); // ---- Infinite scroll (pro/admin/free-access; table + tile views) ---- // Driven off Kaminari's next-page URL, which the partial renders into // #infinite-scroll-sentinel only when the visitor is eligible. We fetch the // next full page, lift out the children of its .database-append-target // container (<tbody> rows for the table view, tiles for the grid views), // append them, then chain to that page's own sentinel URL. DOMParser does // NOT execute the fetched page's scripts, so only content nodes are added — // sliders/search/PostHog never re-run. The sentinel is absent for non-pro // visitors, so this whole block no-ops for them and their paywall is intact. // // Idempotent: guarded by sentinel.dataset.ssInfiniteInit so re-running on // pageshow (bfcache/back-forward restore, where DOMContentLoaded never fires) // can't double-observe an already-wired sentinel. function initSSInfiniteScroll() { var sentinel = document.getElementById('infinite-scroll-sentinel'); if (!sentinel || !sentinel.dataset.nextUrl) return; if (sentinel.dataset.ssInfiniteInit === '1') return; sentinel.dataset.ssInfiniteInit = '1'; // The "database" view renders TWO append targets — the mobile card list // and the desktop table tbody (one is display:none per viewport). Append // to both so infinite scroll works no matter which is visible. Tile views // have a single target. containers[0] drives the loaded-count readout. var containers = Array.prototype.slice.call(document.querySelectorAll('.database-append-target')); if (!containers.length) { delete sentinel.dataset.ssInfiniteInit; return; } var container = containers[0]; // Infinite scroll is live — hide the prev/next fallback for JS clients. var paginate = document.querySelector('.paginate'); if (paginate) paginate.style.display = 'none'; var numResults = document.querySelector('.num-results'); var loadingEl = sentinel.querySelector('.infinite-scroll-loading'); var nextUrl = sentinel.dataset.nextUrl; var loading = false; // Item nodes only — tile partials (e.g. _video) emit a sibling <style> // per render; those are global CSS we already have, so skip them when // appending and counting. function itemNodes(root) { return Array.prototype.filter.call(root.children, function (n) { return n.tagName !== 'STYLE' && n.tagName !== 'SCRIPT'; }); } function updateCount() { if (!numResults) return; var count = itemNodes(container).length; // Keep the "of N …" suffix; just bump the leading loaded-count. numResults.textContent = numResults.textContent.replace(/Showing\s+[\d,]+/, 'Showing ' + count.toLocaleString()); } function loadMore() { if (loading || !nextUrl) return; loading = true; if (loadingEl) loadingEl.style.display = ''; fetch(nextUrl, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(function (r) { return r.text(); }) .then(function (html) { var doc = new DOMParser().parseFromString(html, 'text/html'); var srcs = doc.querySelectorAll('.database-append-target'); Array.prototype.forEach.call(srcs, function (src, i) { var dest = containers[i]; if (!dest) return; itemNodes(src).forEach(function (node) { dest.appendChild(document.importNode(node, true)); }); }); var ns = doc.getElementById('infinite-scroll-sentinel'); nextUrl = (ns && ns.dataset.nextUrl) || null; sentinel.dataset.nextUrl = nextUrl || ''; updateCount(); if (!nextUrl) { observer.disconnect(); sentinel.style.display = 'none'; } }) .catch(function () { /* leave nextUrl intact so a later scroll retries */ }) .finally(function () { loading = false; if (loadingEl) loadingEl.style.display = 'none'; }); } var observer = new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (e.isIntersecting) loadMore(); }); }, { rootMargin: '600px 0px' }); observer.observe(sentinel); } newDocumentReady(initSSInfiniteScroll); // bfcache/back-forward restore doesn't fire DOMContentLoaded; pageshow does. // Idempotency guard above makes the re-call a no-op when already wired. window.addEventListener('pageshow', initSSInfiniteScroll); .blur-row { filter: blur(4px); pointer-events: none; user-select: none; } /* Mobile view toggle (rows ↔ cards) */ .db-view-toggle { display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border: 0; border-radius: 6px; background: transparent; color: #64748b; font-size: 12px; font-weight: 600; cursor: pointer; transition: background-color 0.12s, color 0.12s; } .db-view-toggle-active { background: #0f172a; color: #ffffff; } .database-video-grid { display: grid; grid-template-columns: 1fr; gap: 18px; } @media (min-width: 768px) { .database-video-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } /* Airbnb-style range slider (uses noUiSlider) */ .range-filter { display: inline-flex; flex-direction: column; justify-content: center; gap: 4px; padding: 6px 16px 10px; border: 1px solid rgb(226 232 240); background: #fff; border-radius: 9999px; min-width: 220px; margin-bottom: 0 !important; } .range-filter .range-filter-header { display: flex; align-items: baseline; gap: 6px; line-height: 1; } .range-filter .range-filter-header label { font-size: 0.875rem; color: rgb(100 116 139); font-weight: 500; margin: 0 !important; line-height: 1.2; flex-shrink: 0; } .range-filter .range-filter-header label::after { content: "|"; margin-left: 6px; color: rgb(203 213 225); font-weight: 400; } .range-filter .preview-label { font-size: 0.875rem; color: rgb(15 23 42); font-weight: 600; line-height: 1.2; margin: 0 !important; white-space: nowrap; } .range-filter .filter-slider.noUi-target { height: 3px; background: rgb(226 232 240); border: 0; box-shadow: none; border-radius: 9999px; margin: 3px 6px 0; } .range-filter.is-active { border-color: rgb(15 23 42); background: rgb(241 245 249); } .range-filter.is-active .range-filter-header label { color: rgb(15 23 42); } .range-filter .filter-slider .noUi-connect { background: rgb(15 23 42); } .range-filter .filter-slider .noUi-handle { height: 20px; width: 20px; top: -8px; right: -10px; border-radius: 9999px; background: #fff; border: 1px solid rgb(203 213 225); box-shadow: 0 1px 2px rgba(15, 23, 42, 0.12), 0 2px 4px rgba(15, 23, 42, 0.08); cursor: grab; transition: transform 0.1s ease, box-shadow 0.1s ease, border-color 0.1s ease; outline: none; } .range-filter .filter-slider .noUi-handle::before, .range-filter .filter-slider .noUi-handle::after { display: none; } .range-filter .filter-slider .noUi-handle:hover { border-color: rgb(15 23 42); transform: scale(1.05); } .range-filter .filter-slider .noUi-handle.noUi-active, .range-filter .filter-slider .noUi-handle:focus-visible { cursor: grabbing; box-shadow: 0 0 0 6px rgba(15, 23, 42, 0.08), 0 2px 6px rgba(15, 23, 42, 0.18); border-color: rgb(15 23 42); } .range-filter .filter-slider.noUi-horizontal { height: 4px; } .range-filter input[type="hidden"] { display: none; }
IDEA REVENUE Email opt-in spin tool · wheelysales.com Lucky wheel popup boosting email opt-ins for e-commerce. $600 /mo Whatsapp chat for shopify · superlemon.xyz WhatsApp chat plugin for Shopify stores. $29K /mo Smart size chart solution · kiwisizing.com E-commerce sizing plugin for accurate clothing fit. $36K /mo Shopify data tracking app · analyzify.com Shopify app for accurate data tracking. $12K /mo Creator commerce platform · gumroad.com Platform for creators to sell digital products $917K /mo Shopify bundle creator app · en.widebundle.com Shopify app for creating product bundles and offers. $55K /mo S Squarespace order automat... · superjack.app Squarespace extension streamlining eCommerce order management. $117 /mo newDocumentReady(function() { // Save-bookmark hover — delegated on document (guarded once) so rows // appended by infinite scroll get the behavior too. mouseover/mouseout // bubble (mouseenter/leave don't); closest('tr') scopes to the hovered row, // and the relatedTarget check suppresses flicker when moving cell-to-cell // within the same row. if (!window.__saveBookmarkHoverInit) { window.__saveBookmarkHoverInit = true; document.addEventListener('mouseover', function(e) { var row = e.target.closest('tr'); if (!row) return; var saveBookmark = row.querySelector('.save-bookmark'); if (saveBookmark) saveBookmark.classList.remove('invisible'); }); document.addEventListener('mouseout', function(e) { var row = e.target.closest('tr'); if (!row) return; if (e.relatedTarget && row.contains(e.relatedTarget)) return; var saveBookmark = row.querySelector('.save-bookmark'); if (saveBookmark) saveBookmark.classList.add('invisible'); }); } // ---- Tag-pill hover tooltip (LLM-generated context for each Tagging) ---- if (!window.__tagTooltipInit) { window.__tagTooltipInit = true; const tip = document.createElement('div'); tip.className = 'tag-tooltip-popover'; tip.style.cssText = [ 'position:fixed','z-index:9999','max-width:340px','display:none', 'background:#0f172a','color:#fff','font-size:12px','line-height:1.4', 'padding:8px 10px','border-radius:6px','box-shadow:0 8px 24px rgba(0,0,0,.18)', 'pointer-events:none','white-space:normal' ].join(';'); document.body.appendChild(tip); const showTip = function(e) { const target = e.currentTarget; const text = target.getAttribute('data-tag-tooltip'); if (!text) return; tip.textContent = text; tip.style.display = 'block'; const r = target.getBoundingClientRect(); const tr = tip.getBoundingClientRect(); let top = r.bottom + 8; if (top + tr.height > window.innerHeight - 8) top = r.top - 8 - tr.height; let left = r.left; if (left + tr.width > window.innerWidth - 8) left = window.innerWidth - tr.width - 8; if (left < 8) left = 8; tip.style.top = Math.round(top) + 'px'; tip.style.left = Math.round(left) + 'px'; }; const hideTip = function() { tip.style.display = 'none'; }; document.addEventListener('mouseover', function(e) { const el = e.target.closest('[data-tag-tooltip]'); if (el) showTip({ currentTarget: el }); }); document.addEventListener('mouseout', function(e) { const el = e.target.closest('[data-tag-tooltip]'); if (el) hideTip(); }); } });
Who is the owner of UPPFIRST? When did Arnaud Touret start UPPFIRST? How much money has Arnaud Touret made from UPPFIRST? {"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Who is the owner of UPPFIRST?","acceptedAnswer":{"@type":"Answer","text":"Arnaud Touret is the founder of UPPFIRST."}},{"@type":"Question","name":"When did Arnaud Touret start UPPFIRST?","acceptedAnswer":{"@type":"Answer","text":"2022"}},{"@type":"Question","name":"How much money has Arnaud Touret made from UPPFIRST?","acceptedAnswer":{"@type":"Answer","text":"Arnaud Touret started the business in 2022, and currently makes an average of $120K/year."}}]}