BackInternal tool

MT Colectivo

An internal operations platform to quote trips, assign vehicles, generate service orders and track payments, rebuilt from a single-workflow tool into the system the business runs on.

MT Colectivo orders dashboard and new order screen on desktop and tablet
My role

Software & Cloud Engineer · Aug 2025 – Present

Designed and built the whole system: the AWS serverless backend and its Terraform, the Next.js app, the PDF generation and the migration from the first version.

Context

Context

MT Colectivo is a transportation company running school routes, events and private group trips across Guadalajara and nearby destinations.

Where It Started

The first version automated a single workflow: Google Forms submissions became priced service orders exported as PDFs, built with Vite and FastAPI.

The Rebuild

That tool proved the value, but quotes, payments, vehicles and clients still lived in spreadsheets and chats. Version two rebuilt it as a full operations platform.

The Value

One place to quote a trip, assign a vehicle, generate the service order and track every payment, on desktop or on the phone.

Orders

Quote, assign
and collect.

The order screen is the core of the product. Client, service, passengers, route and payment are captured in one flow, and the service order is ready to download the moment it is saved.

Live Preview

Every field updates the real service order as it is typed. The preview is drawn in the browser with the same code that renders the final PDF, so what operators see is exactly what the client receives.

Automatic Unit

The passenger count picks the smallest vehicle where everyone fits, and shows how many seats are left. Operators can still switch units by hand.

Pricing on the Spot

The price comes from the service's rate table plus extras like additional hours, extra moves or discounts. The recommended price can be overridden when a different amount was agreed.

Payments & Status

Deposits and payments are recorded with their method and date. The order status follows the money: quote, deposit, paid, with overdue balances flagged automatically.

New order form with the live service order preview
Price and payment step with extras, discount and deposit
Order detail with assigned vehicle and document versions

Editing an order generates a new version of its PDF while previous versions are kept. The orders dashboard summarizes what was quoted, collected and still owed each month, next to a calendar of upcoming services.

Orders dashboard with monthly totals and a calendar of upcoming services
Platform

Everything the
operation runs on.

Around the orders, every part of the business that used to live in spreadsheets became its own module. Prices, vehicles, templates and forms are all data the team can change without touching code.

Pricing

No hardcoded services

Each service defines its own variables (schedule, rate, destination), a price table for every combination of options and vehicle, and extra charges that are either manual or applied automatically. Services can be duplicated for the next year or adjusted by a percentage. Orders keep the lines they were created with, so changing prices never alters past orders.

Pricing screen with service variables and options
Fleet

Vehicles as data

Each unit has a passenger range and a vehicle type. Ranges can be shared but never overlap, which is what lets the order screen assign a unit on its own. Every card shows how many services the unit has this month and when it is next booked.

Fleet overview with registered units
Add vehicle dialog with passenger range and vehicle type
Clients

Who owes what

Clients are created from orders and remembered for the next one. The list shows how many services each client has booked, the total contracted, their next trip and the balance still to be collected.

Clients list with services, totals and balances
Documents

Templates without a developer

Service orders are built from templates the team edits themselves: written in a rich text editor with {variables} and conditional blocks, or uploaded as an existing PDF where any text can be turned into a field. The assigned template prints with every new order.

PDF template editor turning existing text into fields
Document templates list
Surveys

Clients quote themselves

Public forms replace the old Google Form. Each one gets a link and a printable QR code, asks only the questions its services need, and every response lands in the orders list as a quote ready to price.

Public quote request form, step by step
Survey QR code ready to print or download
Mobile

Built for
the road, too.

Quotes rarely happen at a desk. The app installs to the home screen as a PWA, and on a phone the order form becomes a six-step flow with large controls, a bottom navigation bar and a full-screen preview of the service order before it is generated.

Mobile order flow, from client to generated service order
Architecture

Serverless,
by design.

The first version ran on a FastAPI server. For a small company with uneven traffic, version two moved to a fully serverless backend on AWS that costs almost nothing when idle and needs no servers to maintain. Every piece is defined in Terraform, and the diagrams below were checked against the live account.

The browser loads a static app from CloudFront, signs in with Cognito and calls an HTTP API. API Gateway validates the token and hands the request to one of nine Lambda functions, which read and write a single DynamoDB table and store templates and PDFs in S3.

A closer look

A static app on the edge

The Next.js app is exported as plain files. CloudFront serves them from a private S3 bucket that only this distribution can read, so there is no web server at all.

  • A CloudFront Function rewrites /ordenes to /ordenes/index.html, because S3 does not resolve index files on its own.
  • A missing file in a private bucket returns 403, so CloudFront maps both 403 and 404 to the app's own 404 page.
  • Deploys upload hashed assets first with a one-year immutable cache, then the pages, then invalidate the CDN. A new page never points at a file that is not there yet.
By the numbers

< $1

AWS per month

Estimated from 30 days of usage; Lambda, API Gateway, DynamoDB and CloudFront stay inside the free tier.

0

Server errors

Across 2,320 API requests in the last 30 days.

67 ms

API latency, p50

Measured by API Gateway; p90 is about 1 s when a Lambda starts cold.

8 ms

DynamoDB reads

Average GetItem latency; queries average 12 ms.

Result

Runs a transport company's daily operations, from quotes to service-order PDFs and payments, for under a dollar a month, with zero server errors across 2,320 API calls in the last 30 days.

Usage, errors and latencies from CloudWatch for the last 30 days (October 2026). Cost estimated from that usage at AWS list prices, since Cost Explorer is not enabled on this account.

Design decisions

Serverless over a server

Traffic is low and uneven. Paying per request means near-zero cost when idle, nothing to patch and scaling that happens on its own.

Static site, direct API calls

There is no server-side rendering to host. CloudFront serves files and the browser talks to Cognito and the API itself.

PDFs without a browser

pdfmake and pdf-lib run inside Lambda, replacing the first version's headless LibreOffice container with a small, fast bundle.

One shared core

Pricing, folios and templates are a pure TypeScript package with 58 tests, used both by the Lambdas and by the browser preview.

Outcomes

MT Colectivo went from a tool that automated one document to the system the business runs on every day.

Quoting a trip, assigning a vehicle, generating the service order and following up on payments now happen in a single flow instead of across spreadsheets, Word files and chats. The team can see at a glance what was quoted, what was collected and who still owes.

Clients can also request quotes on their own through a link or a QR code, and those requests arrive already structured, priced against the same rules the team uses.

For me, the rebuild was about designing software the business can change without me. Prices, vehicles, templates and forms are data edited from the app, the infrastructure is reproducible from Terraform, and the same codebase could run another transport company by swapping a single configuration file.