The dominant factor is not the technology stack — it is uncertainty. Every open question in the requirements is converted into padding inside the number you receive.
Last, plan for the end of the engagement while the relationship is still good. Insist that the repository lives in your organisation from the first commit, and that a readme and architecture notes are kept current as the code changes.
The mix of people behind the number changes the arithmetic. An hourly rate says almost nothing on its own: a senior engineer at twice the price is often cheaper overall than two juniors who require constant review.
The requirements nobody writes down quietly rewrite the number. A tool used by twenty people has almost nothing in common with the same functionality handling thousands of external customers.
The biggest cost driver is not the choice of framework — it is unclear scope. Each unanswered question in the specification becomes padding in the estimate. A team that cannot see what happens on the unhappy path must assume a pessimistic case.
Say what done means for each item. Acceptance criteria need not use formal language: a short paragraph stating the expected behaviour is enough.
Three simple questions generally decide the matter. First: is the system the product itself, or internal plumbing? Then: over what horizon will you need this capacity — one project or a permanent roadmap? Third: who will maintain it in two years?
The requirements nobody writes down quietly rewrite the number. A tool used by a small internal team has almost nothing in common with the same idea serving public traffic.