DEV Community

Fabrizio
Fabrizio

Posted on AI-assisted

How I Built an Open-Source Electronic School Register in Go + Vue (and Why It Matters)


TL;DR — Italian public schools pay thousands of euros every year to private software vendors for proprietary electronic class registers, locking away student data. As a computer science teacher in a public high school, I decided to build a free, open-source alternative in Go, Vue 3, Kotlin, and Swift. Here is the full technical and architectural story behind il_registro.


The Problem: Italian Schools Are Locked into Proprietary Software

Every Italian school is legally required to operate an electronic class register (registro elettronico). Attendance, grades, disciplinary notes, circular communications, parent justifications, and official term scrutinies — all of it must flow through a certified digital platform.

Today, this multi-million euro public sector market is dominated by an oligopoly of proprietary vendors. Every single year, schools sign recurring contracts, pay annual fees with taxpayer money, and hand over the sensitive personal and academic data of millions of underage students to private commercial entities — with virtually zero transparency into their algorithms, databases, or privacy guarantees.

As a computer science teacher working in a public secondary school, I lived this frustration every day in the classroom: sluggish interfaces, clunky mobile workflows, vendor lock-in, and proprietary software that treats public institutions as captive customers.

Public schools deserve public tools.

So I set out to build one — open, verifiable, high-performance, and designed directly from real classroom experience.


What il_registro Does

il_registro is a full-stack, multi-tenant, self-hostable electronic school register tailored to the legal and pedagogical reality of public education:

  • 📋 Grades & Evaluation — spreadsheet-style keyboard matrix navigation (Tab/arrows), weighted averages, target grade simulator, and special educational needs (BES/DSA) compensatory measure tags.
  • 🕐 Attendance & Lessons — daily period register, instant 1-click lesson signature, absence alerts, and parent justification workflows.
  • 📊 Scrutiny & Board Deliberations — final term grade matrices, conduct deliberation, academic credit calculation, and deferred scrutiny (recovery of educational debts).
  • 📘 PDP & PEI Management — digital drafting and parent countersignature for Personalized Educational Plans for students with learning disabilities and special educational needs.
  • ✍️ Digital Signatures (CAD & eIDAS compliant) — collegial scrutiny minute signing with biometric verification and OTP (FEA), plus Principal timestamped qualification (FEQ / RFC 3161).
  • 🏛️ National Integrations — SPID and CIE (Italian Public Digital Identity), plus official MIM (Ministry of Education) SIDI XML export pipelines.
  • 📡 Real-time Push — instant WebSocket notifications for attendances, grades, and urgent circulars with mandatory read-acknowledgment.
  • Inclusive Accessibility (WCAG 2.2 AA / AgID) — built-in Text-to-Speech (TTS), voice dictation (STT), dyslexia tools (OpenDyslexic font, Reading Ruler), ADHD Focus Mode, colorblindness optics, and cloud-synced accessibility profiles.
  • 🔗 E-Learning Sync — automatic two-way synchronization of assignments and marks with Google Classroom and Microsoft Teams.
  • 📱 Native Mobile Ecosystem — 8 native apps (Android in Kotlin Compose, iOS in Swift SwiftUI) isolated for students, parents, teachers, and secretariat staff.
  • 🌍 11 Languages — full multi-language localization across web and mobile (including native RTL for Arabic).

The live demo is available at registro-scuola.netlify.app with sample accounts for all school roles:

Role E-mail Password
secretary segreteria.prova@scuola.it password
teacher docente1@scuola.it password
parent genitore2a_1@scuola.it password
student studente2a_1@scuola.it password

Architecture Overview: A Decoupled Monorepo

The codebase is organized as a modular monorepo:

il_registro/
├── registro-backend/    # Go REST API (Gin + PostgreSQL + Redis + WebSockets)
├── registro-frontend/   # Vue 3 + Quasar SPA/PWA (Composition API, Pinia)
├── android/             # Android Multi-Module (Kotlin & Jetpack Compose) [Alpha]
│   ├── student/         # Student native app (:student)
│   ├── parent/          # Parent native app (:parent)
│   ├── teacher/         # Teacher native app (:teacher)
│   └── secretary/       # Secretary native app (:secretary)
├── ios/                 # iOS Native (Swift & SwiftUI) [Alpha]
│   ├── RegistroStudente/ # Integrated Xcode project (4 executable schemes + UI tests)
│   ├── Package.swift    # Swift Package Manager manifest
│   ├── student/         # Student source module
│   ├── parent/          # Parent source module
│   ├── teacher/         # Teacher source module
│   └── secretary/       # Secretary source module
└── docs/                # Comprehensive technical documentation & API specs
Enter fullscreen mode Exit fullscreen mode

The Tech Stack — and Why

1. Backend: Go + Gin + PostgreSQL + Redis

registro-backend/
├── cmd/           # Entry points (api-server, seeders, migration runners)
├── internal/      # 60+ domain packages (grades, attendance, auth, scrutiny, sidi…)
├── pkg/           # Cross-cutting primitives (jwt, crypto, websocket, cache)
└── tests/         # Unit, integration, and security RBAC matrix test suites
Enter fullscreen mode Exit fullscreen mode

Why Go? Several pragmatic reasons dictate Go for school infrastructure:

  1. Single static binary deployment: A Go server compiles into a single executable binary with zero external runtime dependencies. No JVM tuning, no Python virtualenvs, no broken node_modules in production. A school IT technician on modest hardware can run it with a minimal systemd service or a single Docker container.
  2. Goroutine-driven real-time concurrency: WebSockets for hundreds of simultaneous connected classrooms, background PDF report card generation, and asynchronous ministerial XML packaging run concurrently with minimal memory footprint.
  3. Long-term backward compatibility: Go's strict backward compatibility promise ensures code written today will compile cleanly a decade from now without breaking API deprecation cycles.
  4. Clean domain separation without ORM overhead: Each domain follows the Handler → Service → Repository pattern. We deliberately avoid bulky ORMs: plain SQL queries with typed parameters ensure total control over query execution plans and database indexes:
// Clean architecture: Context propagation, typed SQL, and partial indexes
func (r *Repository) GetGradeMatrix(ctx context.Context, classID, subjectID uuid.UUID) ([]GradeRow, error) {
    const query = `
        SELECT g.id, g.student_id, g.grade_value, g.weight, g.date, g.notes,
               COALESCE(g.compensative_measures, '{}'::text[])
        FROM grades g
        WHERE g.class_id = $1 
          AND g.subject_id = $2 
          AND g.deleted_at IS NULL
        ORDER BY g.date ASC;
    `
    rows, err := r.db.QueryContext(ctx, query, classID, subjectID)
    if err != nil {
        return nil, fmt.Errorf("get grade matrix: %w", err)
    }
    defer func() { _ = rows.Close() }()

    var result []GradeRow
    for rows.Next() {
        var row GradeRow
        if err := rows.Scan(&row.ID, &row.StudentID, &row.Value, &row.Weight, &row.Date, &row.Notes, pq.Array(&row.CompensativeMeasures)); err != nil {
            return nil, err
        }
        result = append(result, row)
    }
    return result, rows.Err()
}
Enter fullscreen mode Exit fullscreen mode

Security & Observability:

  • Authentication: Dual-token JWT (15-minute access token + automatic rotation on refresh), dedicated IP-bounded rate limiting (5 req/min on auth routes), TOTP MFA for all roles.
  • Context propagation: All service methods accept ctx context.Context, enabling graceful distributed query cancellation if an HTTP connection drops.
  • Database Optimization: PostgreSQL 16+ partial B-tree indexes (WHERE deleted_at IS NULL) ensure soft-deleted records never degrade table scans.

2. Frontend: Vue 3 + Quasar Framework

registro-frontend/
├── src/
│   ├── components/   # Modular UI (GradeMatrixGrid, A11yPanel, ReadingRuler…)
│   ├── pages/        # Role-gated route views (Teacher, Student, Parent, Admin)
│   ├── stores/       # Pinia stores with in-memory caching & global error bus
│   ├── composables/  # Shared reactivity (useSpeechToText, useUndoToast, useA11y…)
│   └── i18n/         # Multi-language message catalogs
Enter fullscreen mode Exit fullscreen mode

Why Vue 3 & Quasar?

  • Gentle learning curve: Public education software must welcome contributions from educators and school IT staff who may only code occasionally.
  • Progressive Web App (PWA) first: Unreliable school Wi-Fi in classrooms is solved through Service Workers, background caching, and touch-target sizes exceeding 48px.
  • Micro-UX for teachers: Features like Undo Toasts (15-second grace period) for accidental grade/absence clicks, automatic local draft saving for lesson logs, and a spreadsheet-like grid that accepts Tab and arrow keys cut teacher daily administrative overhead in half.

3. Going Native: 8 Mobile Apps in Kotlin and Swift (Alpha Stage)

While the web app works great on desktop and tablet, mobile usage on smartphones demands dedicated ergonomics: push notifications, native biometrics, offline consultation of student timetables, and role isolation.

Instead of a single bloated multi-role cross-platform app, we engineered separate, lightweight native apps per role:

  1. Student App — Timetable, grade book, target simulator, daily chronological timeline, homework notifications.
  2. Parent App — Child monitoring, 1-click absence justification, teacher appointment booking, urgent notice acknowledgment.
  3. Teacher App — 1-click current period class sign, fast grade matrix entry, attendance and disciplinary notes.
  4. Secretary App — Staff directories, class scheduling, MIM SIDI exports, urgent circular publishing.
┌─────────────────────────────────────────────────────────────┐
│                    Go REST & WebSocket API                  │
└──────────────┬───────────────────────────────┬──────────────┘
               │                               │
 ┌─────────────▼───────────────┐ ┌─────────────▼──────────────┐
 │    Android Multi-Module     │ │       iOS Native Suite     │
 │    (Kotlin + Compose M3)    │ │       (Swift + SwiftUI)    │
 ├─────────────────────────────┤ ├────────────────────────────┤
 │ • :student   • :parent      │ │ • RegistroStudente         │
 │ • :teacher   • :secretary   │ │ • RegistroDocente          │
 │                             │ │ • RegistroGenitore         │
 │ • BiometricPrompt           │ │ • RegistroSegreteria       │
 │ • OfflineCacheManager       │ │                            │
 │ • 11 Languages (values-*)   │ │ • LocalAuthentication (FID)│
 │ • Zero Mock / Real API      │ │ • URLSession async/await   │
 └─────────────────────────────┘ │ • 11 Languages (*.lproj)   │
                                 │ • Xcode Schemes + SPM      │
                                 └────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Key Mobile Engineering Decisions:

  • Zero Mock Data: No fake tokens or dummy login screens. Both Android and iOS clients authenticate directly against the Go backend (Http*ApiService), store encrypted JWT tokens, and interact with the live PostgreSQL database.
  • Native Biometrics: Instant fingerprint / Face ID unlock (BiometricPrompt on Android, LocalAuthentication on iOS).
  • 11 Fully Localized Languages: Italian, English, German, French, Spanish, Romanian, Albanese, Ukrainian, Russian, Chinese, and Arabic (with complete Right-To-Left layout support).
  • Tooling & CI: Gradle multi-module CLI on Android; unified Xcode project (RegistroStudente.xcodeproj) with 4 distinct executable targets alongside headless Swift Package Manager (Package.swift) testing for iOS.

⚠️ Honest Developer Disclosure: The mobile apps are currently in ALPHA. They are under active development, experimental, and not yet feature-complete compared to the web application.


The Hard Parts (Real Lessons Learned)

1. Legal & Cryptographic Compliance: Digital Signatures (CAD & eIDAS)

In Italy, school scrutiny records have legal value in court. Teachers cannot just check a box:

  • We implemented FEA (Firma Elettronica Avanzata) for collegial minutes signing, requiring two-factor authentication (Biometrics / OTP) with cryptographic proof attached to the PDF (internal/feq).
  • For the School Principal, we integrated FEQ (Firma Elettronica Qualificata) using RFC 3161 cryptographic timestamps to guarantee legal enforceability and long-term legal preservation (conservazione sostitutiva a norma CAD).

2. Ministerial Bureaucracy in Code: SIDI XML Integration

The Italian Ministry of Education (MIM) requires periodic XML data dumps formatted against strict XSD schemas. Writing custom XML builders that validate student registries, validate tax codes (codici fiscali), check academic records against ministerial dictionaries, and package compressed bundles with real-time error reporting was an unglamorous but essential engineering feat.

3. Digital Inclusion: Full Accessibility Suite (AgID / WCAG 2.2)

Public school tools cannot leave any student or teacher behind:

  • Speech-to-Text (STT) & Text-to-Speech (TTS): Teachers can dictate lesson logs via speech recognition (Alt + D), while students with visual impairments or reading difficulties can listen to announcements narrated aloud.
  • Reading Ruler (ReadingRuler.vue): An interactive high-contrast horizontal focus band that follows the cursor or keyboard shortcuts (Alt + ↑/↓) to assist readers with dyslexia and ADHD.
  • Cross-Device A11y Cloud Sync: Dyslexia font preferences, contrast modes, and spacing adjustments are synchronized to the user's database profile so their assistive configuration follows them across devices.
  • Official AgID Feedback Flow: A complete AgID-compliant digital barrier reporting system that auto-generates tracking protocol numbers (A11Y-YYYY-MMDD-XXXX) and routes reports directly to the digital transition manager.

4. High-Stakes Scrutiny Algorithms & Zero Race Conditions

During term scrutinies, multiple teachers enter proposals simultaneously. We eliminated concurrency issues and race conditions using row-level locking (SELECT ... FOR UPDATE), atomic slot booking counters, and batch metric calculations (GetStatsBatch) that avoid N+1 query bottlenecks.


License & Philosophy: Why PolyForm Noncommercial?

il_registro is licensed under the PolyForm Noncommercial License 1.0.0.

This license choice is deliberate and fundamental to the project's civic mission:

  • 100% Free and Unrestricted for Public Entities: Any public school, municipality, state university, or public education ministry can self-host, inspect, modify, and run the software without ever paying a single cent.
  • 🛡️ Protection from Commercial Exploitation: Private for-profit software vendors cannot repackage the code, rebrand it, and sell it back to schools under expensive proprietary subscriptions.
  • 📱 Unified License: Both the web platform and the entire native mobile suite (Android and iOS) share the exact same open noncommercial license.

"Public education deserves public infrastructure."


Project Status & Roadmap

  • Web Application (Go Backend + Vue 3 Frontend): Working Beta. Feature-complete, tested with automated test suites (over 950 frontend unit tests, 100% Go package coverage, and full school year lifecycle simulations), and live on the Netlify demo.
  • Native Mobile Apps (Android & iOS): Fase Alpha. Real API connectivity and 11-language UI are working; currently expanding module parity and refining test automation.
  • Next Milestones:
    1. Promote the product to raise awareness of it with the Italian Ministry of Education and Merit.
    2. Continuous hardening of the native mobile applications towards beta.

Try It & Get Involved

If you are a Go developer, a Vue/mobile developer, an open-source enthusiast, or an educator frustrated with the status quo of educational technology:

Feel free to star the repo, open an issue, or join our discussions. Let's return educational data to where it belongs: in public hands.


What does the digital infrastructure of schools look like in your country? Let's discuss in the comments below!

Top comments (0)