Ricardo Rojas

Backend / Full-Stack Engineer

Full-Stack · APIs · Automation · System Design

Selected Projects

toggle display

KanbAnpp logo KanbAnpp — Kanban Web Application
Python (Django, DRF) · React · WebSockets · JWT · SQLite (tentative) · React

Context

A web-based Kanban application designed to support collaborative task management with real-time updates and role-based access control.

Architecture Overview

kanbanpp architecture diagram

Features

  • Real time updates
  • Attachments
  • Tag
  • Roles
  • JWT authentication

System Key Decisions

  • Django + DRF for backend, and quick REST API development
  • Serializers for data validation and transformation
  • JWT authentication for stateless API usage
  • WebSockets for collaborative real-time updates
  • Daphne chosen for simplicity; Nginx + Uvicorn planned when horizontal scaling becomes necessary.
  • React as frontend for dynamic user interfaces
  • TanStack Query for data fetching and caching
  • Pytest for testing
  • Employed SQLite for quick prototyping

Screenshot

KanbAnpp screenshot

Status

Under development

GitHub Repository

SessionBook logo SessionBook — Clean Architecture REST API
Java · Spring Boot · JWT · DTOs · MySQL

Context

Inpired by my hobby as a guitarist when practicing songs. It's used to track progress of song you want to learn. A web application exposing a REST API designed following clean architecture principles, with strong separation between domain, application, and infrastructure layers.

Architecture Overview

sessionbook architecture diagram

Features

  • Guitar tab scraping.
  • Song practice catalogue
  • JWT authentication

System Key Decisions

  • Spring Boot for a robust and scalable backend framework
  • Explicit layering to enforce separation of concerns
  • DDD for clear domain modeling
  • DTO pattern to decouple domain models from API representations
  • Async for scraping guitar tabs and heavy lifting tasks
  • JWT authentication for stateless clients
  • MySQL for relational data storage
  • React for building user interfaces
  • TypeScript for frontend development

Status

Under development

GitHub Repository

DevEnvCheck logo DevEnvCheck — Windows Developer Environment Auditor
Java 8 · PicoCLI · Windows Internals · Maven · CI/CD (GitHub Actions)

Context

A lightweight Java-based CLI tool built after a real recovery incident to diagnose, audit, and validate Windows developer environments. Designed to quickly identify missing tools, broken PATHs, and misconfigured environment variables during onboarding or incident response.

Features

  • Detect installed developer tools and SDKs
  • Version detection via CLI or file metadata
  • Recursive project type scanning (Node, Java, .NET, Python)
  • Safe cleanup of node_modules directories
  • Environment variable diagnostics
  • Exportable audit reports

Key Decisions

  • Java 8 for maximum compatibility with enterprise environments
  • PicoCLI for composable subcommands and argument parsing
  • Windows-native tooling (where, wmic, filesystem probing) instead of fragile heuristics
  • File metadata inspection for GUI tools without CLI version flags (Visual Studio, SSMS)
  • Defensive execution model, avoids launching GUI applications or modifying system state

Usage


clean-node-modules path #asks for confirmation y/N before deleting
clean-node-modules path --silent #no confirmation
clean-node-modules path --dry-run #lists what would be deleted but doesn't delete
check-installation
scan-projects path
env-check path


Status

Complete

GitHub Repository

KeyScala logo KeyScala — Secure CLI Password Manager
Scala · CLI · AES/GCM · JSON Persistence

Context

Type-safe CLI password manager focused on security and correctness, using modern cryptographic methods.

Architecture Overview

keyscala architecture diagram

Features

  • Simple CLI usage
  • AES/GCM Encryption
  • Custom Serialization

Key Decisions

  • AES/GCM for authenticated encryption
  • Secure key management practices
  • Domain-driven modeling to avoid invalid states
  • Minimal dependencies for portability

Usage


# Add an entry
sbt "run --add example.com mykey"

# Edit an entry, you will be prompted for a password again
sbt "run --edit example.com mykey"

# Delete an entry
sbt "run --del example.com mykey"

# List all entries
sbt "run --list"

# Search for an entry (password copied temporarily to clipboard)
sbt "run --search mykey"

# Display help
sbt "run --help"


Status

Complete

GitHub Repository

AssetFLOW logo AssetFLOW — Asset Transformation Library
Scala · Image Processing · OCR Preprocessing

Context

Scala library focused on scalable image transformations, including format conversion, thumbnail generation, palette extraction and preprocessing for OCR pipelines.

Architecture Overview

AssetFLOW architecture diagram

Features

  • Thumbnail generation
  • OCR preprocessing fixes
  • Image transformations
  • Palette extraction
  • Web image guidelines reference

Key Decisions

  • Strong DDD principles for clear domain modeling
  • Functional programming principles for composable transformations
  • Modular design for easy extension with new transformations

Usage



//helpers
  Pipe()
  .from("in")
  .to("out")
  .inspect("after load") { img =>
    println(img.width, img.height)
  }
  .step(TransformationStep("grayscale", OCR.grayscale))
  .inspect("after grayscale") { img =>
    println("ok")
  }
  .dryRun()

Batch()
  .from("in")
  .to("out")
  .foreach("convert") { (file, out, in) =>
    ImageTransforms.convertTo(file, out, ImageTransforms.Webp)
  }.dryRun()


//folders setup
val inputDir = new File("input")
val outputDir = new File("output")
outputDir.mkdirs()

//listing images
val images = ImageTransforms.listImages(inputDir)
println(s" ${images.size} found ${inputDir.getPath}:")
images.foreach(f => println(s"  - ${f.getName}"))

//converting to webp
val webpResults = ImageTransforms.convertTo(images, outputDir, Webp)
webpResults.foreach {
  case Right(f) => println(s"WebP at: ${f.getName}")
  case Left(err) => println(s"Error: $err")
}

//making thumbnails
val thumbsDesktop = ImageTransforms.createThumbnail(images, outputDir, Desktop)
val thumbsMobile = ImageTransforms.createThumbnail(images, outputDir, Mobile)

println("Thumbnails desktop:")
thumbsDesktop.foreach {
  case Right(f) => println(s"  - ${f.getName}")
  case Left(err) => println(s"  - Error: $err")
}

println("Thumbnails mobile:")
thumbsMobile.foreach {
  case Right(f) => println(s"  - ${f.getName}")
  case Left(err) => println(s"  - Error: $err")
}

//now placeholders
val placeholders = ImageTransforms.generatePlaceholders(
  number = 3,
  width = 200,
  height = 200,
  fillColor = Some(Color.RED),
  applyBlur = true,
  outputDir = outputDir
)

placeholders.foreach {
  case Right(f) => println(s"placeholder generated: ${f.getName}")
  case Left(err) => println(s"Error: $err")
}

//test OCR preprocessing
images.headOption.foreach { imgFile =>
  println("testing ocr processing...")
  val image = ImmutableImage.loader().fromFile(imgFile)
  val processed = OCR.optimize(
    image,
    tilt = 5.0,
    contrastFactor = 1.3,
    threshold = 128,
    doBinarize = true
  )
  val (name, ext) = Common.getNameAndExtension(imgFile.getName)
  val key = Common.timestamp
  val outPath = new File(outputDir, s"${name}_$key${ext.getOrElse("")}").getPath
  processed.output(WebpWriter.MAX_LOSSLESS_COMPRESSION, new File(outPath))
  println(s"OCR processed stored at: $outPath")
}


//create a color
val redColor = RGBColor(100, 50, 200)
println(s"initial color: $redColor, hex=${redColor.toHex}")

//increase channels
val brighter = redColor.increaseAll(50, 30, -100)
println(s"adjusted color: $brighter, hex=${brighter.toHex}")

//mix 'em up
val blueColor = RGBColor(0, 0, 255)
val mixed = redColor.mixWith(blueColor, 0.5)
println(s"50% mix: $mixed, hex=${mixed.toHex}")

//from hex
val fromHex = RGBColor.fromHex("#ff00cc")
println(s"from hex '#ff00cc': $fromHex")

//random color
val randomColor = RGBColor.random()
println(s"random color: $randomColor, hex=${randomColor.toHex}")

val cmyk = CMYKColor(20, 40, 60, 10)
val rgb = RGBColor(100, 150, 200)

//increase specific channel by 10 (using currying)
val brighterMagenta = cmyk.modifyChannel(Magenta)(_ + 10)
println(brighterMagenta)

//using the shortcut increaseChannel
val brighterRed = rgb.increaseChannel(Red, 20)
println(brighterRed)

//more complex HOF: halve yellow
val lessYellow = cmyk.modifyChannel(Yellow)(_ / 2)
println(lessYellow)


WebsiteImageType.summary()
WebsiteImageType.fromName("logo_square") match {
  case Some(img) => println(s"square logo found guidelines for desktop: ${img.desktop} " +
    s" for mobile: ${img.mobile}, ratio=${img.ratio}")
  case None => println("square logo not found")

/*
initial color: RGBColor(100,50,200), hex=#6432C8
adjusted color: RGBColor(150,80,100), hex=#965064
50% mix: RGBColor(50,25,227), hex=#3219E3
from hex '#ff00cc': RGBColor(255,0,204)
random color: RGBColor(75,123,240), hex=#4B7BF0

Type                 Desktop (WxH)        Mobile (WxH)         Ratio
----------------------------------------------------------------------
background           2560x1400            360x640              64:35
hero                 1280x720             360x200              16:9
banner               1200x400             360x120              3:1
blog                 1200x800             360x240              3:2
logo_rectangle       400x100              160x40               4:1
logo_square          100x100              60x60                1:1
favicon              16x16                16x16                1:1
social_icon          32x32                48x48                1:1
lightbox             1920x1080            360x640              16:9
thumbnail            300x300              90x90                1:1
product_thumbnail    300x300              150x150              1:1

square logo found guidelines for desktop: 100x100  for mobile: 60x60, ratio=1:1
*/


Status

v0.5.1

GitHub Repository >

JpnUtils logo JpnUtils — Unicode-Aware Text Utilities
Scala · Unicode · Text Processing

Architecture Overview

JpnUtils architecture diagram

Features

  • Zero-dependency
  • String transformations

Context

Small, zero-dependency utility library for Japanese string handling, providing Unicode-aware and language-specific transformations.

Key Decisions

  • Zero-dependency for easy integration
  • Comprehensive Unicode support
  • Focus on Japanese text processing needs

Usage


//using the JapaneseUtils singleton
println(JapaneseUtils.containsHiragana("込める")) //true
println(JapaneseUtils.containsKatakana("淋しい")) //false
println(JapaneseUtils.containsKanji("淋しい"))    //true

println(JapaneseUtils.isHiragana('込'))         //false
println(JapaneseUtils.isKatakana('淋'))         //false
println(JapaneseUtils.isKanji('い'))            //false

//using implicits

//hasX methods, works on string
println("当てのない僕は".hasHiragana)             //true
println("満月".hasKanji)                         //true
println("オカエリナサイ".hasKanji)                 //false

//isX, works on char
println('そ'.isHiragana)                       //true
println('た'isKatakana)                        //false
println('林'.isKanji)                          //true

//miscellaneous methods
val testStr = """"this is a test!? yes? it is sir.""""
val strWithReplacedPunctuation = JapaneseUtils
                                    .Punctuation
                                    .replacePunctuation(testStr)
println(strWithReplacedPunctuation)         //"this is a test!? yes? it is sir。"

//「wrap me in single quotes」 and 『wrap me in double quotes』 respectively
println(JapaneseUtils.Punctuation.wrapInSingleQuotes("wrap me in single quotes"))
println(JapaneseUtils.Punctuation.wrapInDoubleQuotes("wrap me in double quotes"))

//2025 update KanaDiacritics
//true
println("俺はテストだぞ".hasDakuten)
//true
println("いっぱいに静かがっぽい".hasHandakuten)

//カタカナ ABC123&%
val s = "カタカナ ABC123&%"
println(HalfWidthConverter.toHalfWidth(s))


Status

Complete

GitHub Repository

Chordal logo Chordal — Type-Safe Musical DSL
Scala · DSL · Functional Programming

Context

A weekend project that turned into something bigger. Internal DSL for modeling harmonic structures and chord progressions, separating declarative syntax, semantics, and domain invariants.

Architecture Overview

chordal architecture diagram

Features

  • Library support for music theory concepts
  • EDSL syntax for musical expressions
  • Zero-dependency for easy integration

Key Decisions

  • Strong modeling for musical concepts
  • Functional programming principles for composable constructs
  • Type safety to prevent invalid musical states

Lessons Learned

Over-engineering DSLs too early increased cognitive load. I now bias toward simpler models and evolve abstractions only when pressure exists.

Usage


//on progress, subject to changes
val C  = Note("C")
val D  = Note("D")
val Eb = Note("Eb")

val cMajor = Triad.major(C)
val dMinor = Triad.minor(D)
val ebDim  = Triad.diminished(Eb)

println(cMajor.name) // "C"
println(dMinor.name) // "Dm"
println(ebDim.name)  // "E°"

println(cMajor.asNotes) // List(C, E, G)
println(dMinor.asNotes) // List(D, F, A)

val csus2 = cMajor.sus2
val csus4 = cMajor.sus4

println(csus2.name)    // "C D"
println(csus2.asNotes) // List(C, D, G)

println(csus4.asNotes) // List(C, F, G)

val cAdd9 = cMajor.add9
val cAdd6 = cMajor.add6

println(cAdd9.name)    // "Cadd9"
println(cAdd9.asNotes) // List(C, E, G, D)

println(cAdd6.asNotes) // List(C, E, G, A)

val c5 = cMajor.toPowerChord

println(c5.name)    // "(C5)"
println(c5.asNotes) // List(C, G)

val cMaj7 = cMajor.withSeventh(MajorSeventh)
val d7    = dMinor.withSeventh(MinorSeventh)

println(cMaj7.name)    // "Cmaj7"
println(cMaj7.asNotes) // List(C, E, G, B)

println(d7.name)    // "Dm7"
println(d7.asNotes) // List(D, F, A, C)

val cMaj9 =
  cMajor
    .withSeventh(MajorSeventh)
    .addExtension(Ninth)

println(cMaj9.name)    // "Cmaj79"
println(cMaj9.asNotes) // List(C, E, G, B, D)

val key = Triad.major("C".note)

val ii = Triad.minor("D".note)
val V  = Triad.major("G".note)
val I  = Triad.major("C".note)

val ii7   = ii.withSeventh(MinorSeventh)
val V7    = V.withSeventh(MinorSeventh)
val Imaj7 = I.withSeventh(MajorSeventh)

println(List(ii7, V7, Imaj7).map(_.name))

val c1 =
  chord {
    root(C)
    quality(MajorTriad)
    withExtensions(Ninth)
  }

println(c1)

val c2 =
  chord {
    root("D".note)
    sus(Sus4)
  }
println(c2)

val c3 =
  chord {
    root("E".note)
  }
println(c3)
/*
C
Dm
Eb°
(C,E,G)
(D,F,A)
Csus2
(C,D,G)
(C,F,G)
Cadd9
(C,E,G,D)
(C,E,G,A)
(C5)
(C,G)
Cmaj7
(C,E,G,B)
Dm7
(D,F,A,C)
Cmaj79
(C,E,G,B,D)
List(Dm7, G7, Cmaj7)
TriadDesc(C,MajorTriad,List(Ninth))
SuspendedDesc(D,sus4,List())
PowerDesc(E)  
*/  

Status

Under development

GitHub Repository

Scalacron logo ScalaCron — Cronjob DSL
Scala · DSL · Functional Programming

Context

ScalaCron is an EDSL for generation of Cronjob expressions in a zero-dependency library.

Architecture Overview

ScalaCron architecture diagram

Features

  • Library support for Cronjob expressions
  • EDSL syntax for easy expression creation
  • Pretty print support
  • Lightweight and zero-dependency

Key Decisions

  • Robust AST for Cronjob concepts
  • Functional programming principles for composable constructs
  • Prioritized flexibility and ease of use

Usage


import domain.Models.*
import domain.Models.Minute.given
import dsl.CronDSL.{to, *}
import Days.*
import scala.language.postfixOps

object Main :
  def main(args: Array[String]): Unit =

  val job2 = cron { c =>
    c.minute(* / 5)
    c.hour(9.h to 17.h)
    c.dom(1.dom)
    c.dow(Friday)
  } >> "/usr/bin/backup.sh"
  println(job2?) //same as job.schedule
  println(job2) //whole expression as string

/* Output:
  - Minute        : every 5 minutes
  - Hour          : at 12
  - Day of Month  : at 1
  - Day of Week   : Monday
  */5 12 1 1 /usr/bin/backup.sh
*/


Status

Completed

GitHub Repository

Skills

Backend

Frontend

Databases

Data & Distributed Processing

Cloud & DevOps

Testing

APIs & Protocols

Concepts

About me

Work Experience

Full-Stack Web Developer — TONY Super Papelerías Corp.

July 2020 – Present · Veracruz, MX

  • Migrated a multi-branch logistics system from ASP.NET to Django, improving maintainability while preserving compatibility with legacy scanner hardware.
  • Designed and implemented backend services and validations in Django for internal and supplier-facing platforms, progressively replacing legacy .NET modules.
  • Built a Laravel microservice integrating VTEX APIs to automate order processing and eliminate recurring manual interventions.
  • Developed internal automation tools in C#/.NET to feed and synchronize data across systems.
  • Delivered frontend and mobile solutions when required, including a React.js logistics web app and a React Native inventory auditing application.
  • Engineered a Vue.js + Express.js order intake system for the 2024 TONY EXPO, outperforming the previous .NET solution in speed and reliability.
  • Built a semi-automated package label validation tool using QR scanning to detect supplier inconsistencies and reduce manual errors.

Software Programmer — Grupo Inversor Veracruzano S.A.P.I

July 2018 – August 2019 · Veracruz, MX

  • Maintained and optimized the PROCEDA clearance request platform, used daily by hundreds of customers.
  • Refactored legacy PHP code and complex SQL queries, improving stability and response times.
  • Ensured uptime and reliability for business-critical operations across multiple departments.