私のCRMツールを年間180万ドル($1.8M)に成長させた方法
月商 $150,000 · 創業者3人 · 従業員25人 · Paris, France
Simo LEMHANDEZ(Founder, Folk)· 創業 April 2020 · 記事掲載 January 31st, 2025 · folk.app · 元の記事
創業者は既存CRMの不満に着目し、シンプルなCRMのアイデアをランディングページで検証し1万人のサインアップを獲得。2022年4月にProduct Huntで公開し、「Product of the day/month/year」を獲得した。集客はLinkedInなどのオーガニックな投稿、Product Hunt、インフルエンサーマーケティング、SEO、アフィリエイトを活用している。月商15万ドル(約2,250万円)、従業員25人は2025年1月時点の記事掲載時の情報。
売値の出典: 公式サイトの料金ページ(2026年10月取得、1ドル150円で換算)(2026-10-13 取得)
I'm Simo Lemhandez, CEO and founder of www.folk.app I'm 29 years old Moroccan guy, graduated from HEC Paris, McKinsey & Morgan Stanley, Forbes 30U30 The CRM space is the biggest sector in SaaS. Dominated by massive, legacy players like Salesforce and Pipedrive. But, ask anyone about their CRM and you’re likely to get a "oahhhhh bahhhh!"... We thought it was time for a CRM revolution. A system that would be simple to use, integrated to your world, collaborative and intelligent. Like the sales assistant your team never had. To make this mission possible, we've raised $9m in total from Accel and angels around the world and are now powering 300K users and 3K clients around the world to sell more. My image
Skills What skills did Simo LEMHANDEZ have that led to their success? custom-crm Automation Solutions
After McKinsey, I did Le Wagon, a coding bootcamp. I started freelancing for multiple clients and I was managing all my leads in a spreadsheet, juggling between conversation on LinkedIn, Whatsapp, emails and live meetings. I was overwhelmed. I started then looking for a CRM and tried Hubspot, Pipedrive. And wooooof. I felt like going back 20 years in time. The experience was daunting, slow, complex to setup, and not connected to my modern tools. Wearing my consultant hat, I was excited by the contrast between the market size (massive!) the appreciation for the current offerings (very low NPS!). I then met Thibaud Elziere, ex founder of Fotolia (sold to Adobe) and Hexa. As a SaaS entrepreneur, he dreamed about going after Salesforce, the king of SaaS. That's how it all started. We then met Jean-Yves, the CTO. We simply built a landing page that we released to validate the idea: a new kind of CRM, simple, easy-to-use, connected, intelligent. We got 10K sign ups on the landing. We knew we were onto something.
After validating the idea with a landing page, we started designing the product, first on Figma. We had raised at this time $2.5m pre-seed from Accel. We invited leads from the waitlist to have conversations with us, to deeply understand their needs. And after each conversation, we were back to coding, to implement what we learned. Here is the email we used to share: First email to waitlist The bar to challenge CRMs was super high, there was so much to build. The category is super mature, and the CRM is so central in the stack of businesses, there was no room for an MVP. We were measuring how well we were solving our users' needs by tracking engagement and retention. Only when we had metrics we were proud of, we decided to go out of waitlist & do a public launch (especially on Product Hunt) in April 2022. We've been product of the day, of the month, and nominated product of the year. At this time, we raised additional capital ($6.5m) with angels and funds, to start accelerating. The team during the first Product Hunt launch We started charging customers in september 2022, per seat model. Before that, we were doing things in a very artisanal way - using Stripe payment links to make teams pay. Payments wasn't integrated in the product. It's the moment I had the feeling we were becoming a real business, and optimizing for revenue that we were sharing on Slack every morning.
We started very organically, posting on LinkedIn to build our waitlist. We were very lucky to be a subject that was naturally generating interest - every business uses a CRM, and people hate their CRMs. But when we understood the product started being loved, we wanted to have more echo. A Product Hunt launch looked like a natural option, to announce to the world we were out of beta. We prepared the launch like crazy, every detail. Every email, every asset, and a very good video, so the world knew we were the new modern CRM. The launch was very stressful but helped us get a lot of echo.
In sept 22, we knew we had a product we could start scaling, with payment integrated and where users/teams could onboard themselves self-serve. We needed to move beyond our organic circle, and start looking at distribution strategies that could scale. We thought deeply about the way B2B buyers are choosing their tools, and especially CRMs. Our intuitions were: - People rely a lot on communities to buy. When looking for a CRM, they will look on Reddits, Slack channels, Whatsapp groups they might be part of. Having presence in these groups will help. - Reinsurance & social proof matter a lot. "You never get fired for chosing IBM", and CRM is so central in the stack of businesses. We needed to reinsure people. - People buy more from other people than from brands. We needed to have faces that will represent the business. Based on that, the channels where we invested heavily: - Influence - working with micro-influencers especially on Linkedin - SEO - to be a solution people find out when searching on Google - Affiliates - to amplify our echo with experts (eg sales coaches, sales agencies) that will share folk with their audience on owned channels We believe in distribution about having a small number of high conviction bets. It takes time before the investment in a channel start to pay-off. So you need to go for it with conviction and care. I believe it matters a lot to chose your channels intentionally, and keep investing long enough until you can see satisfying results. The metric we have always been optimizing for is CAC payback. New businesses challenge is always cash, so optimizing for how fast your reimburse your CAC makes sense. We try to be at 6 months CAC payback for the overall business, and given organic makes about 50% of our revenue, we want paid channels to be below 12 months payback.
Starting a business is an amazing, yet intense experience. I believe there are a few choices that have an outsized impact of the journey. These are one-way door decisions. 1/ People - What has the bigger impact on your day-to-day is the people you work with. You need to deeply understand the type of people that you love working with, that energize you, and find ways to structure your process to surround yourself of them. Personally, I need enthusiastic, positive people. Learning to fire fast in the case your recruitment doesn't turn out well is also a great thing. I'm the most proud of the team we've that I love working with everyday. 2/ Funding model. There are some businesses that will keep running after funding series. There are others that will stay boostrap, will be profitable businesses but will have less $$ to invest in the early days. We've gone for an intermediary choice: raising early (as we had lot of engineering costs upfront) and then going profitable. The way you decide to fund your business has a lot of impact, on governance, dilution and ability to invest. 3/ Market. Your market has an outsized impact on the outcomes you'll get. There are some markets that are simply virtuous: high growth, high retention, low competition, etc. Choose wisely. We've been fortunate to be on a very large market, with very low NPS for existing player. The category already exists so no need to convince people they need a CRM, they already know it. But that also comes with high competition. My biggest takeaway is that founding a company is a 10y journey, maybe more. So you'd rather structure in a way you'd enjoy it!
Stripe Payments 782 using Slack Productivity 822 using Figma Design 248 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 Pdf document generation API · craftmypdf.com PDF generation tool for non-coders. $15K /mo Digital planning tool · outlineplanner.com iPad digital planner for organized productivity. $3K /mo Focus-enhancing productiv... · stayinsession.com Focus-enhancement app blocking digital distractions. $8.33K /mo Email unsubscribe managem... · leavemealone.com "Tool to easily unsubscribe from unwanted emails." $10K /mo Notion form builder tool · noteforms.com Form builder integrating smoothly with Notion. $37K /mo Screen time reduction app · minimalistphone.com Screen-time reduction app prioritizing mental health. $20K /mo WC Online word counting tool · thewordcounter.com "Free online tool for word counting and writing aid." $20K /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 Folk? When did Simo LEMHANDEZ start Folk? How much money has Simo LEMHANDEZ made from Folk? {"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Who is the owner of Folk?","acceptedAnswer":{"@type":"Answer","text":"Simo LEMHANDEZ is the founder of Folk."}},{"@type":"Question","name":"When did Simo LEMHANDEZ start Folk?","acceptedAnswer":{"@type":"Answer","text":"2020"}},{"@type":"Question","name":"How much money has Simo LEMHANDEZ made from Folk?","acceptedAnswer":{"@type":"Answer","text":"Simo LEMHANDEZ started the business in 2020, and currently makes an average of $1.8M/year."}}]}