月商3万ドル($30K)のAI履歴書アプリを立ち上げました
月商 $26,000 · 創業者1人 · 従業員0人 · Denver, CO, USA
Colin McIntosh(Founder, Sheets AI Resume Builder)· 創業 August 2024 · 記事掲載 March 21st, 2025 · sheetsresume.com · 元の記事
創業者が過去にRedditで公開した無料履歴書テンプレートが400万回以上ダウンロードされ、そこから口コミで知名度を上げた。サービスローンチ時にはこの無料テンプレート内にAIツールの案内を掲載。集客はGoogle広告、アフィリエイト、PR、インフルエンサー、YouTube/ポッドキャスト広告、SEO、Redditでのコミュニティ活動など多岐にわたる。月商は2025年3月時点の自己申告で3万ドル(約450万円)以上、従業員は創業者の他に1人の共同創業者(ソフトウェアエンジニア)
売値の出典: 記事の本文(2025年3月時点)(2026-10-14 取得)
I'm Colin McIntosh, and I'm the creator of SheetsResume.com. At SheetsResume.com, we've built a suite of free and paid AI tools to help people dramatically improve their odds of success in a job search. Our free resume template has over 4 million downloads, and our AI Resume Builder, AI Cover Letter Writer, and AI Mock Interviewer are helping thousands of job seekers every month. We also just launched a job board for employers to reach amazing candidates before anyone else – at point of resume creation. Our paid memberships are now generating $30,000+ per month. We offer $99 lifetime and $29 weekly memberships for unlimited access to our suite of AI tools – no recurring fees. We offer a full satisfaction guarantee, with same-day no-questions-asked refunds for anyone who doesn't feel like they got their money's worth. Because this is a passion project and not our full-time gig, we also give away our AI tools totally for free to anyone facing financial hardship. All they have to do is email us and ask! As former recruiters, we are intimately familiar with how tight money can be during a job hunt, and we never want finances to be a blocker for people who need our tools. We believe that there are too many tools out there designed for employers, but barely any for job seekers. Why? Because employers have money, but unemployed people don't, so they're ignored by software companies. And that's why job hunts are so often so very miserable; it can feel like you're alone on an island. But we believe that it is a gift to help people on their career journey. It can change lives, change families' trajectories for generations, and have enormous ripple effects across industries. In the US, it can even get you healthcare (yikes). We are so excited to continually build out SheetsResume.com with more and more helpful features for job seekers. "Is this resume blessed by God, or what?" – actual review by a user after getting a $20k pay raise
Skills What skills did Colin McIntosh have that led to their success? GPT Wrapper built-with-openai built-with-gemini php-laravel restapi aws Freemium and Open Source
In my early career, I used to be a recruiter (mostly tech) for some of the largest companies in the world. Back in 2018, I ended up writing the most popular resume advice on the internet via a post on Reddit on random Saturday morning that went mega-viral. Since then my resume template has been downloaded over 4M times since then – so I knew without a doubt that there is massive demand for trustworthy, straightforward, actionable resume advice. Over the years, I've maintained the reddit thread by answering thousands of comments and questions from job seekers, all for free, accidentally positioning myself as redditors' most trusted resume whisperer. With the advent of AI, I've been able to amplify my time and expertise by training the Sheets AI Resume Builder with my recruiting knowledge. We gave it away for the first week and saw thousands of excited users with great reviews, so we knew we were ready for prime time. This is very different than my past business experience as Founder and CEO of Sheets & Giggles, a sustainable bedding brand known for its Eucalyptus Sheets.
In 2023, I started doing 1:1 resume reviews in my spare time with my good friend and old recruiting colleague Nate, who is also a software engineer at EventBrite. We loved helping people 1:1 and making such a huge impact on their lives, but we just didn't have enough time to help out everyone who came to us. Plus, because each resume review took a ton of time, we had to charge $400, which was prohibitive for a lot of folks who were unemployed. In 2024, Nate asked me if maybe we should automate our reviews to help more people at a lower price, and voila! The Builder's tech stack is OpenAI, Gemini, PHP (Laravel), RestAPI, AWS, and a few other pieces. We started training an AI with our resume rules and recruiting knowledge, and it took about 4 months (working nights and weekends) before we had the UX dialed in. We let people build their resume, and then ask them if they'd like to become a lifetime member for $99 – no recurring fees, unlimited usage, and no-questions-asked refunds. We are trying to figure out how to add in a free usage tier, but for now if anyone needs it for free because of financial constraints, they just have to email me and I'll grant them a free temporary membership. The business is totally bootstrapped. My image
To launch our Resume Builder, I included a line about it in my free resume template – which is downloadable from my website and which is the most popular resume template on the internet. I called it an "easy button" vs the DIY version, and made sure folks knew they could ask me for a free membership if they needed one. We launched it in August 2024, and that first day we did $128 in sales. The next day, $500. It was a surreal feeling. As a prior physical product founder, I've learned how financially flexible software margins can be – I absolutely adore and have immense gratitude for our paid members, who enable me to give it away for free to those in need. We have people in rehab centers, prisons, universities, and all over the world using our tools for free thanks to our paid lifetime members.
We use Google Ads, affiliate marketing, PR, influencers, YouTube sponsorships, podcast sponsorships, and SEO content marketing to drive more website traffic. We have a robust organic Reddit presence, answering questions freely and often. I think my best tip is that it's important to help people first and foremost, as often as you can, asking for nothing in return... and good things will follow.
I didn't realize that once I started the AI Builder, nobody would want a 1:1 resume review anymore!! Haha I genuinely wish I still got requests for those; I really loved working with and getting to know people 1:1. For good decisions, we sponsored Ryan George recently and that is always a smart financial and brand decision. Our biggest mistake is probably the layout of the website. I wish we thought more about how to structure the site with the 1:1 reviews and the AI builder. SheetsResume.com's UI/UX really screams "side project" right now; it's definitely a huge mess that needs to be streamlined and cleaned up. As for helpful habits I possess, I'm writing this at 3am, so I can function on like 4.5 hours of sleep pretty well. I run Sheets & Giggles as my main dayjob, so I can only work on passions projects like this late at night when all my other to-do's have become to-done's. Inspo: there has never been a better time to be a solopreneur than right now. I cannot believe the AI tools that are now available to us for copy, coding, image, video, and customer care. Starting a business in 2025 is the easiest, least expensive, and least time-intensive it's ever been – what are you waiting for?!
OpenAI Platform 64 using PHP Platform 17 using Laravel Stack 43 using AWS infrastructure Other 98 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 Tech talent hiring platform · flexiple.com Platform connecting startups with top freelance developers. $250K /mo Freelance tech talent pla... · clouddevs.com Freelance tech talent platform for vetted developers and designers. $167K /mo Job search automation pla... · loopcv.pro Job search automation platform for individuals and businesses. $30.3K /mo No-code talent marketplace · codemap.io Marketplace connecting businesses with no-code experts. $7K /mo AI job application platform · aiapply.co AI-powered job application assistant for job seekers $25K /mo Ai-powered recruiting app · skillsoniq.com AI-powered recruiting app for domestic freelancers. $40K /mo Reverse job board for devs · railsdevs.com Reverse job board for Ruby on Rails developers. $13.3K /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 Sheets AI Resume Builder? When did Colin McIntosh start Sheets AI Resume Builder? How much money has Colin McIntosh made from Sheets AI Resume Builder? {"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Who is the owner of Sheets AI Resume Builder?","acceptedAnswer":{"@type":"Answer","text":"Colin McIntosh is the founder of Sheets AI Resume Builder."}},{"@type":"Question","name":"When did Colin McIntosh start Sheets AI Resume Builder?","acceptedAnswer":{"@type":"Answer","text":"2024"}},{"@type":"Question","name":"How much money has Colin McIntosh made from Sheets AI Resume Builder?","acceptedAnswer":{"@type":"Answer","text":"Colin McIntosh started the business in 2024, and currently makes an average of $312K/year."}}]}