
How “Your CFPs Aren’t Good” Became Five Approvals at RubyConf
Table of Contents
In April 2025, Tropical on Rails, the Rails conference in São Paulo, said yes to one of our talks for the first time. A few months later, one of its organizers and I ended up talking off the record – nothing official, just two people catching up before he had to run.
He told me straight: the CFPs we’d sent back in 2024 hadn’t been good.
He wasn’t being unkind. He’s a friend, not just an organizer, and he was just finally telling me something I’d already spent a year finding out on my own.
Getting rejected is already a sign, sure — a stack of no’s paints a picture. But hearing it straight, by someone who actually reads these proposals for a living, hits different. It’s real and no longer leaves you pondering. It’s objective.
I lead a small group at Codeminer42 built around content production. Talks are the end of that pipeline – and CFPs are the gate you don’t get past without writing well. This is the playbook I share with the group for that part, and it’s the same thing I’d tell you.
A group with a boring name
In January 2024, we started an internal group at Codeminer42 called producao-de-conteudo – "content production." I know. We’re better at writing software than naming groups.
The idea behind it was simple: everybody’s got a message to pass. Every developer has lived through something worth sharing – a bug that taught them humility, a pattern that saved a project. Conferences are one of the best mediums for those messages. The group existed so we could support each other in sending them.
We had no structure to speak of. We picked a handful of Ruby and JavaScript conferences and started applying. We tracked everything in a shared Git repo where each person got a folder and dumped their submissions – commit straight to main, no merge, rebase always. The README promised that "if everybody does it right, there will never be a conflict." Welcome to trunk-based development.
That year we sent around 40 proposals. Most of them bounced. A few landed: two at TDC Floripa, one at Nerdearla (mine), Talysson at RailsConf 2024 in Detroit, and Sammy at RubyConf 2024 in Chicago.
Roughly one acceptance for every eight proposals. That sounds bad, and it was. But in the beginning, incentive mattered more than quality. The goal was to build the habit of submitting, not to write perfect proposals. Getting things done, then getting them right.
Two different skills
At the end of 2024, I became the company’s DevRel (still part-time back then) and took over the group. One in eight wasn’t a number I could keep getting away with.
So I started studying. Not how to give talks – how to get them accepted. Because here’s the thing I hadn’t understood yet:
Writing a good CFP and delivering a good talk are two different skills.
We already knew how to present. Miners run brown bags and internal presentations all the time; putting someone in front of an audience was never our bottleneck. But none of that stage skill shows up in a 300-word abstract read by a committee that has never seen you speak – and, at conferences like RubyConf, doesn’t even see your name in the first round.
A CFP is a pitch, not a syllabus
The material that helped me most wasn’t about conferences at all. It was about copywriting.
Copywriters have known for a century that people don’t buy features, they buy benefits. Nobody at a street market shouts the ingredient list; they shout what the thing does for you.
Now look at how developers write CFPs. We go straight to the features of the talk: "I will cover the actor model, Erlang, Elixir, and message passing." That’s an ingredient list. The committee reads hundreds of those, and none of them answer the only question that matters: why would the audience care?
Some conferences don’t even hide it. Sessionize, the tool most of them use to collect proposals, has a field literally called "Pitch" – not "abstract," not "description." Pitch. They’re telling you outright what the form is for.
The framework
In February 2025, I turned that realization into an actual process and shared it with the group. Three steps, always in this order.
1. Features vs benefits, side by side
Write two columns. Left side, every feature of the talk. Right side, force yourself to answer: what does this actually do for the person watching? You’re not allowed to leave the right column empty and call the CFP done.
Here’s the table I built for my PWA talk:
| Feature | Benefit |
|---|---|
| Just Rails and a bit of JavaScript | You already have every tool you need |
| Offline-capable pages | The app still works on a bad connection, or no connection at all |
| Push notifications | You reach the user again after they’ve closed the app |
| No App Store, no Play Store | Ship a fix today, not after a review queue |
The left column is what I know. The right column is what the room gets. Most CFPs never leave the left column.
The first few times you do this, expect to get stuck on the right side. That’s normal – talk it through with someone else in the group. Saying the feature out loud to another person is usually enough to find the benefit hiding behind it.
But if you talk it through and the benefits still won’t come, take that seriously. It’s not the exercise failing you. It’s the exercise telling you the truth: you don’t have a talk yet.
2. The need: who’s in the room, and why would they care
A benefit list still assumes the audience already wants what you’re selling. The real work is naming who’s in that seat and what’s bothering them before they’ve heard a word of your talk.
For the PWA talk, the need was concrete: publishing to Apple’s App Store is painful, and most Rails developers don’t need a native app at all – they just don’t know it yet. That pain is the hook. The topic is just the delivery mechanism.
The room changes the need. TDC in Brazil draws PMs and managers alongside developers, so the need is business-shaped: ship faster, spend less on native maintenance. At a Ruby-only conference, the need is technical: stop compromising on concurrency. Same benefits table, different sentence about why anyone in that specific room should care.
3. Satisfying the need
The last step is writing the line that closes the loop you just opened. Not "you’ll learn about Ractors" – that’s coverage. "You’ll write concurrent Ruby without fear of race conditions" answers the need directly. Committees pick talks their audience will thank them for, so tell them exactly what they walk away with.
Skip either of the first two steps, and this line falls apart. You can’t satisfy a need you never named, and you can’t turn a feature into an outcome you haven’t already translated into a benefit.
Where AI fits
I use it for the mechanical part: turning that features column into candidate benefit phrasings, drafting the pain sentence three different ways, cutting an abstract down to whatever character limit a pitch field enforces without losing the point. That work is real, and refusing to touch the tools available to you is its own kind of arrogance.
I don’t use it for naming the actual need. Einar Høst, who sits on the NDC Oslo agenda committee, called AI tools mediocrity machines: competent, plausible, built to produce the average of what’s already out there. A committee that skims fast gets very good at spotting average, because average is what they read five hundred times in a row.
There’s a line he quoted from Matthias Freis, who organizes DDD Europe, that stuck with me:
Writing is thinking. If you outsource your thinking to a machine, I’m not interested in hearing what you have to say.
Naming the need is you working out why this talk, for this room, right now. That part doesn’t outsource. Skip it, and it shows – not in the grammar, in the mediocrity.
Here’s why all three steps matter more than they sound like they should. A committee doesn’t get to read carefully. Høst put real numbers on that: NDC Oslo got roughly 1,700 submissions competing for just over 100 slots in 2024, an acceptance rate of 6.6%. His committee reviews proposals three at a time, side by side, spending something like 30 seconds per pass.
Nobody is reading your abstract closely. They’re skimming it the way an attendee skims a program, deciding in seconds whether to keep reading or move on. If the need and the benefit aren’t in the first couple of lines, the table you built never gets read.
Before and after
The difference is easier to show than to explain. Here’s the opening of a CFP I sent to TDC in 2024:
Ever wondered how the most popular frontend library actually works?
In this talk we’ll cover React’s internals and, believe it or not, we’ll get into the most basic concepts of functional programming.
A rhetorical question, then a list of what I’d cover. It describes a talk. It doesn’t pitch one.
Here’s the opening of the CFP that got accepted at RubyConf 2026:
Concurrency in Ruby has always been a compromise. Threads are error-prone. Fibers are complex. The GVL limits true parallelism. We accepted that concurrent Ruby is hard.
I came from Erlang and Elixir, where concurrency is the default. […] When Ruby introduced Ractors in 3.0, I was skeptical. The API was clunky. The limitations were severe. It felt like Ruby trying to be something it wasn’t.
Ruby 4.0 changed my mind.
It opens with a pain every Rubyist knows, stakes a personal position, and leaves you wanting to find out what changed my mind. Then five concrete outcomes and a timed outline. There’s no ingredient list anywhere in it.
2025: the loop closes
I didn’t run a workshop on any of this at first. I tried it on my own CFPs, because advice you haven’t tested yourself is just an opinion.
2025 was the year it started working. I got accepted at Tropical on Rails in São Paulo – my first big conference. It’s also the conversation I opened this post with: a few months after that acceptance, one of its organizers told me our old CFPs hadn’t been good. By then, I already knew. I’d spent a year rewriting how I wrote them. His comment wasn’t a warning anymore. It was confirmation.
The talk that got me in was the PWA pitch I showed you above. That same pitch later carried the talk to RailsConf 2025 in Philadelphia, the final RailsConf ever.
And the talk paid off the promise the CFP made. Joe Masilotti, the creator of Hotwire Native, was in the room:
Edy Silva’s talk lit a fire under me. As I watched, I wondered: could I get this working in a Hotwire Native app? After the talk I opened my laptop and two hours later had offline access working natively.
So it stopped being just my technique. Talysson took the stage at Rails World with the "XY Problem" in the AI era, and spread DDD across three countries – Nerdearla in Argentina, Explore DDD in the USA, and DDD Brasil. At TDC, three of us got approved: me on Node.js DX, Talysson with two talks, and João Vogler on frontend resiliency. We wrapped up the whole thing in our 2025 year in review.
Each acceptance did something the studying alone couldn’t: it raised the whole group’s confidence. We’d been sharing CFPs since the beginning – the git repo saw to that – but now there was a reason to look closely at what was in front of us. Every successful proposal gets discussed, picked apart, and turned into a lesson for the next one; we review each other’s drafts before they go out. It’s the same principle as code review: more eyes on a draft before it ships catches what one person alone would miss. One person studying copywriting became a group that writes proposals together.
That’s the part I’d steal if I were you. Not the copywriting books – the ritual.
RubyConf 2026
At the end of 2025 we sent our proposals into a shrinking window. RubyConf 2026 is the first RubyConf in 20 months, and with RailsConf retired it’s now Ruby Central’s only flagship event – everyone who would have submitted to either conference funneled into one CFP. The program shrank to about 30 sessions, down from 70 in 2024, against hundreds of submissions. The first round of review is anonymous: title and abstract only, no names, no company. We had nobody on the program committee.
Four Miners got in outright: Gabriel Quaresma on why a 1990s machine learning algorithm destroys LLMs at predicting house prices, Miguel Marcondes with a hands-on workshop building an AI game engine with Ruby and genetic algorithms, Antônio Paulino on tribology – the physics of friction – applied to Rails systems, and me on Ractors in Ruby 4.0. A fifth proposal landed on the waiting list, and the call came.
Five approvals. More than any other company got, past an anonymous filter, at the most competitive RubyConf in years.
Not everyone will make it to Las Vegas – life gets in the way of conference schedules. But this post is about the writing, and the writing did its job.
RubyConf isn’t an isolated spike, either. TDC approved eight of our talks this year across four Miners. We got more slots at Node Congress too, including a first-time speaker leading a workshop.
Not every CFP fits every talk
I want to be honest about something: we don’t expect a 100% acceptance rate, and we never will. Some rejections are on us and fixable. Most of them aren’t about the writing at all – they’re about how conferences are run.
Sometimes the pitch just doesn’t fit the room. A pitch built for TDC’s mix of PMs and developers can bomb at a conference that wants the technical meat up front, and the reverse is just as true. This one’s on us, and it’s fixable: rewrite the need for the room you’re actually pitching to, and the same talk often gets in somewhere else.
Sometimes it’s a quota, not the pitch. Most conferences cap how many talks they’ll take from a single company, no matter how good the writing is. Once Codeminer42 already has two or three slots at an event, a fourth strong CFP from us isn’t competing with the rest of the world anymore. It’s competing with our own other proposals for a seat that doesn’t exist.
And sometimes it’s just who’s asking. Some conferences lean heavily on invited or well-known speakers and take very few names from the open call, no matter what the proposal says. A committee filling a program under a deadline reaches for names it already trusts. Good writing gets you into the pile that gets read. It doesn’t guarantee a seat once you’re there.
We have signals now that our CFPs are good. That doesn’t mean every one of them belongs at every conference, or that every conference has room left for them.
Which is part of why the number that means the most to me isn’t RubyConf. At the end of 2025, we also sent proposals to Tropical on Rails 2026 – the same conference, the same friend who once told me our CFPs weren’t good. Two approvals and one waiting list.
Two years ago that conference was where I heard the truth about our writing. This year, he told me straight again – our CFPs are good now. Same guy, same bluntness, opposite verdict.
If you’re at RubyConf, come say hi.
Thanks for reading!
We want to work with you. Check out our Services page!



