Amanuel Tadesse's Work | ContraWork by Amanuel TadesseAmanuel Tadesse
Senior Full-Stack Engineer · TypeScript, React, Node
A scroll animation that shows QuoteKit working. A messy client email is read, the small talk gets crossed out, and each request turns into a line of a fixed-price proposal. Built with GSAP and ScrollTrigger in React. QuoteKit - From client brief to fixed-price proposal
QuoteKit turns a short client brief into a fixed-price proposal in under a minute, with scope, exclusions, and a timeline. Clients accept through a private page without an account.
The problem
Writing a solid proposal can take hours. When the scope is unclear, clients question the price, and freelancers end up doing work they did not plan for. Most quoting tools focus on nice PDFs or invoice tracking. They do not help you decide what is included, what is not, and what the work should cost.
How it works
You paste in a short client brief and choose a service type: Rescue, Audit, Build Sprint, or Custom.
QuoteKit generates a complete proposal with:
A project summary
In-scope work
Out-of-scope work
Assumptions
A delivery timeline
A fixed price
Everything can be reviewed and edited before the proposal is sent.
What I focused on
Reliable AI output
AI responses are validated against a schema before they are saved. If the model returns incomplete or broken data, the response is rejected instead of creating a broken proposal.
Controlled pricing
The model gets a price range for each service type, and the user reviews every price before sending.
Simple client acceptance
Every proposal has a private client link. The client can review and accept it with their name and an optional note, without creating an account. Acceptance is recorded only once, and later attempts are ignored.
Clear scope boundaries
The out-of-scope section helps with requests like "one more small thing." The proposal already shows what was not included, so the extra work becomes a change order.
Server-side plan limits
Free accounts can create up to three proposals per month. The limit is enforced on the server, so it cannot be bypassed through the browser. The Pro plan costs $19 per month and includes Stripe Checkout, a customer billing portal, and webhook-based subscription syncing.
AI agent access
QuoteKit can also be used by AI tools such as ChatGPT, Claude, and Cursor through an OAuth-protected MCP connection. Agents can list, read, and draft proposals for the signed-in user, and they can only access that user's data.
Security
Every table uses row-level security, so users can only access their own records. The public proposal page does not read directly from the proposals table. It uses a database function that returns a fixed set of safe fields. Uploads are stored in separate folders for each user, and payment redirects are restricted to the app's own domain. A pre-launch security review found a profile permission issue and an open redirect. Both were fixed before release.
How I built it
I built QuoteKit with Lovable. Then I did what a prototype usually skips before real users arrive: I added row-level security on every table, enforced the plan limits on the server, validated the AI output, and fixed the issues the security review found.
Stack
Built with Lovable. React 19, TypeScript, TanStack Start, Tailwind CSS v4, shadcn/ui, PostgreSQL with row-level security, Stripe.
Skills: React, TypeScript, PostgreSQL, Stripe, Lovable, AI Integration, SaaS Development Afrotribe is for creators who want to connect, grow, and thrive in a supportive community. Whether you're an artist, musician, writer, or content creator, Afrotribe provides a space where you can share your work, collaborate with others, and access opportunities that help you reach a wider audience and monetize your talent. If you're passionate about creativity and looking for a platform that genuinely supports your journey, Afrotribe is for you.
Afrotribe offers a range of benefits for creators, including access to a supportive community, tools for boosting visibility, and multiple ways to monetize your work. You'll find opportunities for collaboration, growth, and promotion, all within a platform that's dedicated to helping creators succeed in the digital space. With exclusive features and community-driven support, Afrotribe is here to help you take your creative career to the next level.
The client. Kerbside Auto. Marcus, a solo mobile mechanic working out of one van across Brisbane's southside: Carindale, Mount Gravatt, Sunnybank, Springwood and Ipswich.
His quirks are what shaped the build. Jobs run 30 to 150 minutes, so a fixed slot grid doesn't fit. He drives between suburbs, and Ipswich to Carindale is 55 minutes. Enquiries arrive by text while he's under a car, so he replies after 7pm, by which time half have booked someone else. About one no-show a week, and for him that's a wasted trip across the city, not an empty hour. Tuesday and Wednesday mornings sit empty while Fridays overflow.
The insight. Most booking tools assume the business sits still. Marcus doesn't, he's in a van. A 9am job in Ipswich makes a 10am job in Carindale impossible even though the calendar shows both as free. So the rule isn't "is this hour taken", it's "can he physically get there".
The front door. The customer picks a service, a suburb and a day, and only sees times Marcus can actually make. A time is offered only if the whole job fits the working day, nothing overlaps, there's enough travel time either side plus 10 minutes for parking, and a lunch gap survives. When a time is blocked, it says why: "Marcus is in Ipswich until 11:20, cannot reach Carindale before 12:25." Hiding it would have been easier. Explaining it makes the business look competent rather than full.
When a whole day is booked out, it doesn't dead-end. It offers the quiet mornings that would otherwise sit empty.
A $40 deposit holds the slot and comes off the bill, so a no-show costs the customer instead of Marcus. Then it's confirmed on the spot. No callback.
The follow-through. Marcus does nothing. Confirmations, a reminder 24 hours out, another when he's on his way, self-service rescheduling that re-checks the travel rules, a thank-you afterwards with the next service date, and a nudge to anyone who picked a slot but didn't finish. An inbound text gets an instant reply with a booking link, so a lead never waits until evening.
On his side: today's jobs in route order with the drive time between each, the day's revenue and total driving, and one button for "running 30 minutes late" that moves the whole day and texts everyone affected. Empty time is highlighted across the week.
Before and after. 45 minutes a day of texting, gone. Roughly one no-show a week at about $180 a wasted trip, now covered by the deposit. Quiet mornings offered first instead of sitting empty.
A note on the demo. The owner dashboard has no login so you can click straight in. In production it sits behind auth with Marcus as the only user. The payment step is clearly marked as a test.
Built in Lovable, with Supabase for data.