Partner
Agilico GmbH
Case study03
An end-to-end platform for media price lists, quotations, publication planning and production-ready ad orders

Partner
Agilico GmbH
Industry
Media & Advertising
Core technologies
Next.js · Express · PostgreSQL
At a glance
DuoByte built a platform for Agilico GmbH that covers the path from a publisher's price list to a paid, print-ready advertisement in one system. Price lists are fetched from publisher websites and extracted with AI, quotations are pushed to Bexio, and public campaign shops let customers design and pay for their own ads.
Our role: DuoByte set up the platform and continues to develop it, covering architecture, backend and frontend, the Bexio, Stripe, OpenAI and Microsoft integrations, and deployment and operations.
Project work
How the project came together: from the context and requirements through implementation to where it stands today.
Context
The platform serves teams that plan, quote and book advertising in newspapers and digital channels on behalf of companies and agencies. Every quotation starts from the publishers' rate cards: per-millimeter column rates, fixed formats, circulation figures, publication days, volume discounts and surcharges.
Publishers release these rates as PDF price lists, each with its own layout, often typeset in multiple columns and renewed every year. The setting is Swiss: billing is in francs including VAT, accounting runs in Bexio, and ads appear in German, French and Italian language titles.
Two groups use the system. The internal team works in a protected back office and signs in with Microsoft accounts. Customers order through public campaign shops without creating an account.
Challenge
Prices, formats and discounts used to be copied by hand from publisher PDFs into quotations, calendars and third-party systems. An automated extraction has to cope with very different layouts, attribute each price table to the right newspaper and edition, and tell inserts and other special products apart from regular placements.
At the same time, the import must never destroy data. An empty or faulty result must not overwrite a complete record, and settings the team has maintained by hand have to survive every new price list.
The public ordering flow comes with its own requirements. Prices must be calculated on the server from the rate card, never in the browser. The print file must match the booked column width while keeping the line breaks the customer approved. And a paid booking in a running campaign must stay unchanged when rates are updated later.
Solution
All product data comes together in the back office. A price monitor checks registered publisher websites for new PDFs on a schedule, determines whether a document is a price list, and imports confirmed rates as structured print and digital products. The team follows running imports live and can cancel any of them.
Quotations are built from that catalog with customer, contact person and agency. Contacts come from Bexio, and each quotation is created there as an offer and updated when it changes. Publication dates are planned in a calendar that only offers the newspaper's actual publication days and blocks Swiss public holidays.
In a campaign shop, customers pick a template, add their text and image, choose newspaper, edition and dates, and pay through Stripe Checkout, including Google Pay. The order only exists once payment succeeds, and the print file is then ready in the back office.
Implementation
The frontend runs on Next.js with TypeScript, Tailwind CSS and shadcn/ui, the backend on Express with Prisma and PostgreSQL. Every request is validated with Zod. Document analysis runs as a separate Python process: PyMuPDF reads even multi-column price lists cleanly, pdfplumber handles the tables, and an OpenAI model returns the rates as structured output against a fixed schema. Large PDFs are split into overlapping chunks, processed in parallel and merged again.
Data quality is enforced by rules in code rather than by trusting the model. Several filter stages keep unrelated content out of the catalog, a newspaper is identified by title, edition and combination, and when two versions exist the newer price list wins. An import without placements never overwrites a complete record, and a job writes its results only at the end, in a single transaction.
Print files are generated on the server. The renderer turns the stored template document into PDF/X-4 with pdf-lib, including a CMYK color profile, embedded fonts and trim and bleed boxes. If the booked column is wider than the template, the artwork is centered rather than enlarged, so the line breaks stay exactly as approved. Payment runs against an immutable pricing snapshot, and VAT is rounded in whole Swiss centimes.
Back-office access requires a Microsoft account or email and password, new accounts are confirmed by code and limited to approved company domains, and public endpoints are rate limited. Backend and frontend are tested with Jest, Supertest and Vitest; a dedicated test fails whenever a new editor control lacks an entry in the built-in help. Delivery runs on Docker Compose behind Caddy, GitHub Actions deploys every push to the development or production branch, and the database and uploads are backed up daily.
Outcome
The team no longer copies rates by hand; it reviews what the import delivers. Quotations are built from the same catalog and reach Bexio as offers without retyping, and the publication plan is generated from the same dates.
Customers book their ads in the campaign shops themselves, pay immediately and receive a confirmation by email. The platform is in production use and keeps growing, most recently with digital campaigns for social media graphics.
System architecture
Technologies were combined to suit the task, operating model and long-term maintainability.
Related services
API integrations, ERP and accounting connections, PDF imports and automated jobs that move data reliably between your systems.
Learn moreInternal tools, dashboards and SaaS products that follow your processes instead of bending them. Designed and coded by the founders themselves.
Learn moreKeep exploring
Next case study

Your project
Tell us what your system needs to do. We bring structure to requirements, architecture and delivery.