Skip to content
Back to projects

Back-end · automation

Internal request management platform

A single portal for requests between departments: Flask with Supabase Auth and roles, a Kanban board with SLA and events that n8n turns into email notifications. Deployed on Render.

My role
Back-end, interface, automations and deployment
Period
2026
Status
shipped
Stack
Python · Flask · Supabase · n8n · JavaScript · Gunicorn · Render

30-second summary

Problem
Internal requests arrived by email and Discord, with no flow, no clear deadline, and the requester never knew who was handling them.
Solution
Structured request intake, a per-department Kanban with visual SLA, roles with permissions and events so n8n notifies each person at the right moment.
Outcome
The system is deployed on Render with the full flow working end to end. There are no usage metrics.

Context and problem

In many companies, a request from one department to another starts as a loose message: an email, a Discord channel. There is no single place to log it, the deadline is unclear and the requester never knows whether someone has picked it up.

The goal was a single portal for internal requests, with visual management and automatic communication between departments. This was the technical case from the hiring process I passed.

My role

I built the system end to end: the Flask API, authentication and roles in Supabase, the Kanban front-end, the notification flows in n8n and the deployment on Render.

Solution and architecture

  1. 01IntakeTitle, priority, target department and deadline
  2. 02Flask APISession, role and permission rules
  3. 03SupabaseAuth and the requests table
  4. 04Department KanbanTo do → in progress → paused → done
  5. 05n8nReceives the event and sends the right email
One request, from intake to completion.
  • Roles and permissions. Login, sessions and password recovery use Supabase Auth; each person has a profile with a department and an access level. Managers see every request, create users and delete tickets. Regular users see only their own department's requests, and only the target department can pick up or change a request. Anyone can add a note to the history.
  • Kanban with SLA. Each card shows how much of the deadline has passed, from creation to the end of the deadline day. From 75% it shows "Attention", from 90% "Critical risk", and past the deadline, "Late".
  • Handling time. Picking up, pausing and resuming a request records who is responsible and adds up the minutes actually spent.
  • Events for n8n. The API fires three events (novo_ticket, ticket_assumido and ticket_concluido, new, picked up and done) to an n8n webhook, which emails the requester and the assignee. n8n also alerts managers about idle requests.
  • Reports. A button exports the requests on screen as CSV.
  • Deployment. Gunicorn on Render, with keys in environment variables.

Try it

A recreation of the interface of the Flask, Supabase and n8n system. Open a ticket, drag the cards, switch roles and see, in the automations panel, the event the real system would send to n8n.

Demo with fictional data · no database

What matches the real system and what is simulated

  • Same as the real system: the permission rules, the SLA calculation, the handling time and the format of the events sent to n8n.
  • As in the original system, the ticket_assumido event is sent when a card is dragged to In progress. The Pick up, Resume and Pause buttons in the detail view only control the timer and send no event.
  • Simulated: the data is fictional and stays in your browser. No email is sent; the preview shows what n8n would send.
  • Not in the demo: login, password recovery and the Supabase database.

Stack

  • Back-end: Python with Flask, served by Gunicorn.
  • Database and authentication: Supabase (PostgreSQL and Auth).
  • Automation: n8n, with a webhook and email sending.
  • Front-end: HTML, CSS and JavaScript, no framework.
  • Hosting: Render.

Decisions and trade-offs

The back-end announces, n8n decides

The API only publishes what happened, with the ticket data. Who gets notified, with what text and through which channel lives in n8n, and changes without a deploy.

trade-offOne more service to run. In the deployed version, the webhook pointed to n8n on my machine, so the emails were demonstrated live rather than from Render.

Events sent in the background

The call runs on a separate thread with a 5 s timeout. A failure in the automation never blocks creating or moving a request.

trade-offIf n8n is down, the event is lost: today it is only logged, with no retry.

Permissions checked in the API

The rules for who sees and who can change each request live in one place, the back-end, and don't depend on the interface.

trade-offThe server uses Supabase's service key, which bypasses the database rules. So every route has to check session, department and role before acting.

SLA calculated from the deadline

A bar that changes color tells you faster what needs attention than a list of dates.

trade-offThe calculation happens on screen; the database stores the deadline and time spent, but not the history of when each request became at risk.

Outcome

The system is deployed on Render with the full flow: intake, per-department Kanban, permissions, SLA, export and email notifications through n8n. There are no usage metrics, so there are no numbers here.

What I learned

  • Separating what happened (the event) from who needs to know (the automation) makes both parts simpler.
  • A service key on the back-end is convenient, but it moves all the security responsibility into the API code.
  • An external integration should never be able to break the main flow.