Skip to content

Portfolio2026 edition

Portrait of María Sanjuán, smiling, with her hand on her chin.

maríasanjuán Frontend AI Developer & UX/UI Designer

I design in Figma and ship to production in React and Angular. Today I build with AI agents: the spec leads, automated checks hold the line, and I make the calls.

Bogotá, Colombia · remote

Fig. 0 Portrait in code. Each row of glyphs is a line of a program; the depth was computed with AI from a photo. Move the cursor: the designer is underneath.

Two roles,
one signature.

For eight years1 I’ve designed and built interfaces for teams in Spain, Germany and Colombia: travel, higher education, legal publishing, health. I’ve led UX teams and design systems, and I write the front-end myself, in React, Angular or Vue.

Today I work with AI agents the way a director works with a crew. I write the spec, the agents build, automated checks hold the line, and every decision gets a person’s review: mine. At Interkont it’s how the whole team works2. At Lúmina Tech, the company I founded3, it’s how I built a school platform that has been in production since August4.

This portfolio is built the same way, and you can touch everything in it. The demos are real code, recreated with fictitious data.

maríaBogotá, October 2026

Selected work.

Two products I founded, designed and built with AI agents: my company’s website and the school platform. First the real screens; then the parts that matter, running right here with fictitious data.

01 Website · 2026

Lúmina Tech, the website.

The website of my own company: AI-first, in 3D, and honest about what isn’t built yet.

Role
Founder · product · UX/UI · front-end with AI agents
Stack
Vite · TypeScript · three.js · GSAP · Lenis
01Manifesto Big type over a sphere of particles: AI doesn’t replace the teacher, it gives them time back.
02AI in action The daily-plan console (paused, fictitious data) next to the early-warning light.
03Products They scroll sideways, each one with its own shape. Campus: live.
04Trust The Colombian law behind each feature.

And on the phone

  • luminahub.com.co on a phone: Home
  • luminahub.com.co on a phone: AI in action
  • luminahub.com.co on a phone: Products

From the inside

Four pieces of the site, running on this page.

luminahub.com.co

The particle engine from luminahub.com.co. Pick a shape: the symbol keeps the proportions of the official SVG, and its lime square becomes a tunnel. Move the cursor over it.

Daily plan · teacher Fictitious data Paused

Demo with fictitious data of a teacher’s daily plan. This feature is paused.

High priority: math recovery in grade 9B. Six students are below 3.0; schedule a fractions review before Thursday.

Reminder: pending grades for grade 10A. Twelve grades from worksheet 3 are missing to close the period.

The AI daily-plan console, as it appears on the site: the real shape of the response of POST /ai/daily-plan, fictitious data, and a “paused” label, because the feature is paused while it moves to a provider that accepts educational use with minors.

  • Night blue#0D0F2BBackground. Never pure black.
  • Indigo#1E1B6E1.3:1 not for small textDepth, gradients.
  • Lime#4DFF4B14.0:1 AAOnly the primary button, headline keywords and the symbol’s square.
  • Violet#6B68B03.8:1 not for small textAccent on surfaces, not small text.
  • Light violet#A9A6E38.3:1 AAExists for small text.
  • Pearl#F4F4F617.1:1 AAText.

Small text on night blue: can you read it?

8.3:1 · passes AA for small text (4.5:1)

Education that thinks with you.Plus Jakarta Sans · headlines

AI-powered educational software for schools in Colombia.Inter · body

POST /ai/daily-plan · 3.0JetBrains Mono · figures and code

The brand system, with its contrast measured. Light violet exists because the medium violet does not reach 4.5:1 on night blue in small text. Try the four colors. Lime is scarce on purpose: primary button, headline keywords and the symbol’s square.

Section Hero

gsap.set(S, K.hero);
morph
0.00
x
0.50
y
0.30
scale
1.00
alpha
1.00
spin
0.00

The scroll choreography, from the inside. Each section of the site has a state, and the scroll interpolates between the previous one and its own, always with explicit from/to values. x and y are fractions of the visible screen, so it works at any aspect ratio. Turn on the delayed scrub and jump: that bug happened.

  • Content first

    All the text lives in the HTML; JavaScript only animates. Without JavaScript or WebGL the page still reads complete, and that is what Google indexes.

  • Never promise more

    Insight says “Coming”; the AI plan says “Paused”. A clients section would only exist if it were true.

02 Platform · live since Aug 3, 2026

Lúmina Campus, the platform.

A school platform built on Colombian law, for leadership, teachers, students and families.

Role
Founder and product owner · UX/UI · front-end architecture · development with AI agents
Stack
React 19 · TypeScript · Tailwind CSS v4 · shadcn/ui · Node.js · Express · PostgreSQL (Supabase) · Playwright
Here
Recreated on a demo school with fictitious data. No real school, student or minor.
  • 5 roles with their own permissions
  • 13 core modules, included in every plan
  • 3 paid modules, already built
  • 80+ accessibility checks on every pull request
01Risk observatory Who is in red and why, with the notice to the parent one click away.
02Social service Resolution 4210 as a table: the 80 hours each 11th grader needs to graduate.
03School coexistence Cases with their Law 1620 protocol: a type II case, open, on step 4 of 7.
04Family What the parent sees: each child’s performance by subject and period, on the Decree 1290 scale.

And on the phone

  • Lúmina Campus on a phone: Sign in
  • Lúmina Campus on a phone: Leadership
  • Lúmina Campus on a phone: Parent

From the inside

Four pieces of the platform, rebuilt from its code with fictitious data.

Early Warning SystemFictitious data

RED

  • Attendance 72% (critical: below 75%)
  • Average 2.6 (passing minimum 3.0)
    if (attendance < 75 || average < minimum) return 'RED'
    if (attendance < 85 || trend <= -0.5) return 'YELLOW'
    return 'GREEN'

    The early-warning traffic light, with the product’s real rules and real reason texts. Move the sliders. The school’s minimum grade is not a constant: it comes from each school’s evaluation system (Decree 1290, art. 8). With 3.0 hard-coded, a school that requires 3.5 saw in green a student its own report card failed.

    Directory and chatFictitious data

    View as

      Pick someone from the directory.

      Leadership

      • Gloria Navarro ✓
      • Álvaro Restrepo ✓
      • Nubia Castaño ✓
      • Student 07 ✓
      • Student 12 ✓
      • Student 31 ✓
      • Parent of Student 07 ✓
      • Parent of Student 31 ✓

      Teacher

      • Gloria Navarro ✓
      • Diana Rojas ✓
      • Nubia Castaño ✓
      • Student 07 ✓
      • Student 12 ✓
      • Student 31 ✕
      • Parent of Student 07 ✓
      • Parent of Student 31 ✕

      Student

      • Gloria Navarro ✓
      • Diana Rojas ✓
      • Álvaro Restrepo ✓
      • Nubia Castaño ✕
      • Student 12 ✕
      • Student 31 ✕
      • Parent of Student 07 ✕
      • Parent of Student 31 ✕

      Parent

      • Gloria Navarro ✓
      • Diana Rojas ✓
      • Álvaro Restrepo ✓
      • Nubia Castaño ✕
      • Student 07 ✕
      • Student 12 ✕
      • Student 31 ✕
      • Parent of Student 31 ✕

      Who can write to whom. The matrix is enforced on the server: the directory only lists allowed contacts, and opening a conversation outside the matrix returns a 403. Turn on minor protection: the parent can read their child’s conversations, without a voice, the student sees a permanent notice, and every read is audited. “Watching is not impersonating.”

      Report card · Decree 1290Fictitious data

      Demo school

      Academic report card

      Period 2 of 4 · School year 2026 · Scale 0.0–5.0 (Decree 1290/2009)

      Student 07Group 9A

      SubjectTeacherGradePerformance
      MathematicsÁlvaro RestrepoLow (Failed)
      Spanish LanguageNubia CastañoHigh
      EnglishYaneth PalaciosBasic
      Natural SciencesJairo MolinaSuperior
      Social StudiesNubia CastañoBasic
      Physical EducationJairo MolinaHigh
      ArtYaneth PalaciosHigh
      Ethics and ValuesÁlvaro RestrepoBasic

      Period average 3.9

      Superior ≥ 4.6 · High ≥ 4.0 · Basic ≥ 3.0 · Low < 3.0

      A report card by MEN performance levels. Edit any grade, or the school’s minimum. “Basic” falls on that minimum by definition: it is the level of someone who passes by a hair. Averages round to one decimal with half away from zero, exactly like Postgres: a CI guardian walks all 251,001 possible pairs to prove TypeScript and the database agree.

      Design systemTailwind CSS v4
      • pizarra-profunda#1C2B35 · Sidebar, focus
      • coral-cta#C93C3C · Primary action and error
      • celeste-pizarra#8BB8C8 · Borders, sub-roles
      • niebla-polar#F5F9FB · Page background
      • verde-texto#177A49 · Valid
      • ambar-texto#9A6603 · Warning

      Buttons with a wave

      Tabs with sparks

      Focus isn’t red

      Campus’s design system, rebuilt from its CSS. Every action button gets a wave, the tabs give off sparks once and stop, and the focus outline is slate, not coral: people read the coral focus as an error. Red means error, and only error.

      Process

      Research and law
      The law became screens: the 0.0–5.0 scale and MEN levels (Decree 1290), step-by-step coexistence protocols with the confidentiality of art. 44 (Law 1620, Decree 1965), PIAR adjustments printed on the report card (Decree 1421), a graduation certificate that refuses to issue without the 80 hours of social service (Resolution 4210), and versioned, revocable consent (Law 1581).
      Decisions with their why
      Never a button that lies: if a feature doesn’t exist, it says “Coming soon”. A zero while loading also lies, so an empty space waits instead. And the report card and graduation certificate are never behind a paid module, because issuing them is a legal obligation.
      Accessibility, WCAG 2.1 AA
      Required in Colombia by Resolution 1519 of 2020. Every pull request runs more than 80 automated checks: every screen of the five roles on desktop (1280 × 800) and mobile (390 × 844). A serious violation, a horizontal overflow or a clipped text fails the build.
      Responsible AI
      AI suggests, people decide: no grade, promotion or sanction is decided by an automated system. The AI runs on the server, so no key or sensitive data reaches the browser. The early-warning light works today with clear rules, not AI, and the AI daily plan is paused while it moves to a provider that accepts educational use with minors.
      • The parent reads with notice

        Not in silence. A minor who doesn’t know they’re being read talks as if they weren’t, and if the problem is at home, silent surveillance hands it to the wrong person.

      How I work
      with AI agents.

      Spec-driven development (SDD) with multi-agent flows in Claude. It isn’t a tool on the side: it is how I build, every day. The evidence below comes from the Lúmina Campus repository.

      1. Specify

        Every change starts as a written spec. In Lúmina Campus the rules live in CLAUDE.md and in a constitution of six non-negotiable principles, and the agents read them before writing a line.

        “Never a button that lies. If the feature doesn’t exist, it shows empty or “Coming soon”.”

        CLAUDE.md · Lúmina Campus · translated from Spanish

      2. Build with agents

        Claude agents implement against the spec, in looping and prompting cycles; I orchestrate. One task, one branch, one pull request. At Interkont it is the whole team’s method.

        feat(chat): supervisor mode stops being an empty promise
        
        Co-Authored-By: Claude Opus 5

        A real commit (translated from Spanish), with its co-author · Campus has more than 400 commits and more than 90 merged pull requests

      3. Guard

        Today, sixteen automated guardians run in CI, and each one exists because something broke once. And the rule that keeps them honest: break them on purpose before trusting them.

        • check-button-wave.jsfails if an action button shows up without its wave
        • check-permisos-datos.jsno table is born reachable with the public key
        • check-siee.jswalks all 251,001 possible pairs: TypeScript and Postgres round the same
      4. Verify

        More than forty end-to-end test files in Playwright and more than 80 accessibility checks on every pull request. Verifying means running the path that changed: if nobody clicked it, it isn’t verified, and it isn’t reported as such.

        AUDITORIA=1 npx playwright test e2e/auditoria.spec.ts --workers=1

        The full WCAG 2.1 AA audit: five roles, desktop and mobile

      5. People decide

        Product, UX and every sensitive decision stay human. The agents propose; I decide, and the decision is written down with its reason so the next session doesn’t undo it.

        “The decision that it be access with notice, and not a silent copy, is the CEO’s (Sep 7, 2026).”

        CLAUDE.md · on the chat’s supervisor mode · translated from Spanish

      What I know,
      and where I used it.

      Eight years, in two columns. Pick a skill to light up the jobs where I used it, or a job to see its skills.

      Code

      • JavaScript
      • LESS
      • .NET

      Design

      • Photoshop
      • Zeplin
      • Responsive design

      AI & agents

      • Cursor
      • Copilot
      • MCP
      • n8n
      • AWS Bedrock AgentCore
      • Figma Make
      • Antigravity

      Quality & delivery

      • Docker
      • Scrum
      • AWS

      Experience

      1. Multi-agent AI under SDD is the team’s end-to-end method: from user stories with the client to front-end architecture. React and Angular interfaces, documented in Storybook, with Playwright green on every pull request.

      2. Lúmina Campus, from product to production, with AI agents. Selected for the Bogotá Chamber of Commerce Startup Capital Raising Program.

      3. Advanced CSS and interface design in Figma and Ant Design, with global teams.

      4. Led the UX/UI team and the experience strategy across all products; component systems in Storybook.

      5. Digital products for a legal publishing group, with Vue, HAML, Pug and Bootstrap, in agile teams.

      6. UX, Figma prototyping and views in React, HTML5, CSS3 and Bootstrap.

      7. Angular components and RxJS flows for high-traffic education platforms, among them Universidad Siglo 21 and Areandina.

      Education

      • 2012 — 2016Bachelor’s degree in Graphic DesignUniversidad Autónoma del Caribe · Barranquilla
      • 2024 — 2026Front-end with React.js · Product & Time Management SchoolPlatzi

      Languages Spanish (native) · English (reading proficiency, actively improving)

      Colophon

      How this portfolio was made. It counts as a case too.

      Luminance channel of the portrait, in grayscale. Depth map of the portrait: the face and hand are lighter because they are closer. The cut-out mask: the silhouette in white over black.
      Light, depth and mask: the three maps the portrait is made from.
      Concept
      Two roles, one signature. Everything exists in two materials, code and design, and the switch at the top decides which one leads: the portrait, the notes in the margins and the accent color.
      Portrait
      An AI-generated photo of me. MODNet cut me out and Depth Anything V2 gave me depth, both running on my own computer: the photo never left it. Then a program is written over the photo, row by row, one character per glyph: thousands of glyphs.
      Type
      Manrope for the headlines and my name; Geist for the text and Geist Mono for the code. All under the SIL Open Font License and served from this site: no requests to third parties.
      Code
      Vite, TypeScript, three.js, GSAP and Lenis, without a framework. The particle engine is adapted from the one I built for luminahub.com.co. Every text lives in the HTML, in English and Spanish, written once side by side.
      Access
      It reads complete without JavaScript and without WebGL, it works with a keyboard, and with reduced motion there is no smooth scroll, no loader and the portrait stays still. Body text on the background passes 17:1.
      Credits
      Design and code: María Sanjuán, with AI agents (Claude). Review: María Sanjuán.

      Let’stalk.

      Tell me what it’s about and pick a channel: the message comes already written.

      What is it about?