Back to blog Building Out Loud · Entry 10

I built a product that won't post for you

Trellis writes social posts in your voice, but a human reads every batch and nothing auto-posts. Here's the build and the philosophy behind it.

· 11 min read

As I’ve talked about in this blog in the past, I build websites for small local businesses out of our home in Petersburg. We specifically service real small businesses, people we actually know or could know, the kind you’d run into at the auto shop or the farmers market. While doing this, we keep noticing the same thing. A business gets a nice website from us, they’re proud of it, but after the initial launch and congratulations, their social media is a ghost town.

Not because they don’t care or they’re not trying but because nobody has time to sit down and think up posts and write them and figure out what to say on social media. Posting on social media is a part-time job that small businesses don’t have the margin to hire for.

There’s a whole other group of people too. Businesses that already have a website, so they’re never coming to us for a build, but they’ve seemingly got the exact same problem. They don’t need a new site. They just need some help with their social profiles but they have no idea where to start. We’ve all seen the AI social media managers for a $500-$1500 yearly subscription. Those aren’t built for small businesses, those don’t tap into your voice, what you care about, they’re AI generated posts based on what you do as a service, and not based on what you want your customers to hear from you, so even those very expensive AI managers are missing the mark. (I know because I’ve used several for Keiter & Co.)

So I built Trellis for both of those groups.

what it actually is

Trellis is an AI social media manager, but it’s different from most in very specific ways. First, you sit down with us and we learn how you and your business talks. That’s the part that matters and it’s the part nobody else is doing. We read your site, we talk to you, we figure out your voice, the way you’d actually say something to a customer. Then every month you get a batch of social posts written the way you would write them, for whatever platforms you use. You log in, you see your posts, you copy the ones you like, change them if you want and post them. That’s it. Never staring at a blank box again trying to decide if you need to run a free promotion to get some business, cause hey, everyone loves free shit right?

A bit on the name. A trellis is that wooden frame you put in a garden, so a climbing plant has something to grow up. The plant still does the growing. The trellis just holds it up and helps it reach the sun. And that’s the whole idea behind Trellis. The business already has a voice and a story. Trellis is the support that helps it grow where people can see it.

We went back and forth on names. Wisteria was in the running because wisteria grows fast and gets prettier every year, which I loved. (Being a swiftie may have played into the Wisteria thing a bit 😉 ) But wisteria is also kind of an aggressive takeover vine, and that felt wrong for what this is. Trellis is gentler. It supports, it doesn’t take over. Turns out the name ended up describing the entire build philosophy, which I’d love to say I planned, but it’s really just kismet.

a real human reads every batch before you do

This is the thing I care most about, and I’m most proud of.

A real person looks at every single batch before a client ever sees it. Me or Alex, maybe one day a Keiter & Co. employee (wishful thinking?) We read it, we make sure it sounds like them, we catch anything that’s off. My robots don’t get to talk to our clients without one of us checking in first, that’s our whole philosophy.

I’ll never be cagey about the fact that AI writes the drafts. I’ll tell you straight if you ask. But the part I say out loud, the part that really matters, is that a real human who knows your business reads it before it reaches you. That’s not a feature I tacked on. That’s the whole promise.

Here’s how that promise turned into code. When a batch gets generated, it lands in a “pending” state that clients literally cannot see. It is only in their Keiter & Co. dashboard. One of us must review it, approve it, and manually send it to the client. And I enforce that at the database level, not by hiding it in the interface. A pending batch is invisible to the client even at the data layer. There’s no path, accidental or otherwise, where unreviewed posts reach a client.

A human pushes go, turned into a rule the system physically cannot break.

nothing auto-posts, ever

On principle. I’m not going to have a machine publishing on your behalf to your customers and your community while you’re not looking. In many of these social media apps, that seems to be a feature you pay for, but to me, you’ll be paying in credibility, not cash.

If you don’t spend the time reviewing your own posts, how can your clients trust you to hire you, give you their money, do work for them? And that’s why you post your own stuff. I just hand you good stuff to post, I make sure the ideas are sound and relevant and you choose which ones to feed to your customers. The tools that auto-post for you, that’s exactly the thing I didn’t want to build.

This shaped a real engineering choice. There’s a “Post” button on each post, but it can’t and won’t publish for you. What it does is copy your text and open the platform so you paste it. On X we can pre-fill the text through their share link. On LinkedIn, Facebook, and Instagram you can’t pre-fill text from a link, that’s their rule, so we copy it and open the site for you.

your data is yours and only yours

This was the hardest decision and it was a security one, so this is the most technical the entry gets.

🔗 repo: github.com/oliviakeiter/olivia-keiter-build-methodology

The engine Trellis sits on top of originally let any logged-in user read everything in the database. That was fine when the only person logging in was us, on one shared account. But the second real clients can log in, that setup would let every client read every other client’s posts. Not great. Actually, a massive disaster.

So before anything else, I rewrote the database rules so a logged-in client can only ever see their own rows. The key thing is I enforced it at the database level, not just by hiding it in the interface. Even if someone got clever and queried the database directly from their browser, they get nothing but their own data.

I proved it by simulating two different client logins and confirming one literally cannot read the other’s posts. That was the load-bearing piece. Everything else sits on top of it.

⚠️ If you build multi-tenant anything: this is the decision you cannot get wrong and cannot bolt on later. Isolation lives at the data layer or it doesn’t really exist.

Logins are per-person magic links. Email only, no passwords. You type your email, if you’re approved, you get a link, you click it, you’re in. I chose this over a single shareable secret link on purpose. A shared link leaks the moment someone forwards it into a group chat. Per-person links give real access control with nothing to forward and no password for anyone to lose or for me to store.

the calendar only ever cheers you on

There’s a gentle calendar, a soft suggestion of when to post, and you tick a box when you’ve put one up. No streaks. No guilt. No sad empty weeks staring at you. The reward is filling in a box, never the absence of one.

The last thing a busy business owner needs is another app making them feel behind. Lord knows we get enough of that from inside our own heads.

This sounds like a copy choice but it’s truly baked into how the calendar is built. The only states it can render are neutral or positive. There is no punitive state in the code, so there’s no punitive state to accidentally ship. I removed the ability to make you feel bad. You’re welcome.

the build decisions that don’t map to a value but earned their place

A few things didn’t tie to a single promise but were the difference between this working and not.

Wrap the engine, don’t rebuild it. I already had a working engine that crawls a business’s site, learns their voice, and generates posts. I built that for Keiter & Co. because.. MARKETING IS HARD! Trellis is the client-facing layer around it. I made a rule early: don’t rebuild the engine, wrap it. So the new work was access, views, the approval gate, and the monthly loop, not regenerating what already worked.

The timeout lesson. Generating a full month, around fifteen post ideas with copy for four platforms each, is a lot of back-and-forth with the model. The serverless functions that run this have a thirty-second limit, and the work blows right past it. The first version timed out and silently did nothing, which is the worst kind of bug. The fix was two things: run the writing as a background job with a much longer window and let the screen check back for the finished batch instead of waiting on a frozen button, and run a lot of the model calls at the same time instead of one after another.

Derive voice once, save it. Rather than re-reading a client’s whole website every single time, I write a compact description of their voice one time and store it. Every generation reads that small profile instead of the raw site. It’s cheaper, it’s faster, and it gives me a plain-language voice spec a human can actually read and correct if it’s off.

Log every model call with its cost. I track tokens and dollars per client on every call. Part of that is operational, but part is the business case. It told me the real cost of serving even a heavy client is only a few dollars a month, which is what makes a low monthly price possible.

who it’s for

Local people. Real people. That’s the heart of it. I build for people I know and care about, and the work reflects on me and on my community. When you hire us you’re getting a real couple from a small homestead in upstate New York, not a faceless dashboard in some other country. Someone you can call. Someone you run into at the grocery store.

That’s the thing a software company can’t copy. Anybody can wire up a robot to a posting calendar. Not everybody will sit down and learn how your business actually talks, and not everybody will care enough to read your posts before they ever even make it to you.

the feeling

The feeling I want you to walk away with is relief. The relief of someone finally taking the social media thing off your plate without taking it out of your hands and without charging you an arm and a leg and a full torso… You still sound like you. You still decide what goes out. You’re still the one in control of your business’s growing social presence. You just don’t have to invent it from nothing anymore.

And I built the whole thing. Still a little smug about it.

want in?

Trellis is $39 a month. That’s it. Not $500, not $1500, not a yearly contract you regret by March. The kind of price that’s an easy yes for a small business, because that’s who it’s built for.

And since this is brand new, the first 5 businesses to sign up get a full free month to try it. That’s a complete batch, 15 post ideas with copy for all four platforms, 60 pieces ready to go, written in your voice, no card, no catch. You try it, you see your posts laid out the way they’d actually look, and you decide.

If that sounds like the thing finally coming off your plate, come find us at keiterandco.com. You’ll be talking to a real person. Probably me.


find me on LinkedIn if the vibes feel right: linkedin.com/in/oliviakeiter

Signed,

Back to blog