This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle
What I Built
Enquiry to Quote helps Australian trade businesses turn customer messages into organised, editable drafts.
A customer enquiry might arrive as an email, text message or notes from a phone call. Before preparing a quote, the business owner needs to understand the job, identify missing details and write a reply.
My app takes that message and generates four sections:
Job summary: the key facts from the enquiry.
Missing information: questions to help assess the work.
Customer reply: an editable response to the customer.
Quote scope: a provisional starting point for a quote.
Each section has its own text box and Copy button. The business owner reviews and edits everything before using it.
The first version focuses on electricians. For example, someone might request three ceiling fan installations, mention that they have already purchased the fans, and ask about next Friday. The app organises those details without confirming a booking or inventing a price.
Who would pay for it? My target customer is a small trade business handling its own enquiries and quoting. The value I want to test is whether reducing this repetitive admin makes a paid service worthwhile.
Demo
Click Try an example, then Generate draft. Review the four sections, edit the wording and copy what you need.
The public demo allows five generation requests per IP address every 15 minutes. The backend uses Renderâs free hosting, so the first request after a period of inactivity may take longer.
Please use sample enquiries and avoid entering sensitive information. Generation uses hosted third-party AI providers.
Code
The project has two main folders:
client: React interface built with Vite.
server: Express API, model request and response validation.
How I Built It
The AI at the core is Metaâs open-weight Llama 3.3 70B Instruct, accessed through OpenRouter.
The application flow is:
React sends the enquiry to my Express backend.
Express validates the input and checks the request limit.
The backend sends the enquiry and task instructions to the model.
A JSON schema defines the four expected output fields.
The backend parses and validates the response.
React displays the drafts for editing and copying.
The model does the central work: interpreting an unstructured message, identifying gaps and drafting useful text.
I wrote the instructions around Australian English and the practical limits of the product. The model is told not to invent prices, promise availability, confirm bookings or provide electrical installation instructions. Unconfirmed work should be marked as subject to confirmation.
The idea grew out of my work building a website for AVP Electrical, a small electrical business in Forster, NSW. I wanted to explore a tool that could help a business like theirs spend less time organising enquiries and preparing replies.
AVP is the first business Iâd like to test it with. The app is working, but its usefulness and willingness to pay still need to be validated with real users.
The frontend is deployed on Netlify, and the backend runs on Render. The API key stays on the backend.
Why Does Open Innovation Matter?
For this project, the benefit is choice and a path to running the model elsewhere.
Using an open-weight model means I can evaluate the same model through different hosting arrangements, or explore self-hosting later, subject to its licence and hardware requirements. Iâm not limited to accessing the model through one companyâs closed API.
The model name is configured through an environment variable. The appâs interface works with four defined fields, so I can test another compatible model without redesigning the frontend. Any replacement would still need testing for output quality and instruction-following.
That matters for a small side hustle. Inference costs, response quality and provider availability all affect whether the service is practical to sell.
This version uses hosted inference: it isnât offline, it isnât free to operate, and enquiries leave the userâs device. Open weights give me more options for how the product could evolve.
My Agent Session
One useful debugging lesson came when the interface appeared to be generating forever. A direct request using curl showed that the backend and model were workingâthe draft returned in around 11 seconds.
Chromeâs console revealed the actual problem: my React handler referenced data before it was defined. The error occurred outside the requestâs error-handling block, leaving the loading state active.
Fixing the handler taught me more than simply getting the button working. I learned to trace a request across the frontend, backend and model provider, and to use evidence to isolate the failure.
We also refined the model instructions after an early draft assumed existing light fittings would be removed. That was a reminder that correctly formatted AI output still needs human review.
Top comments (0)