App mobile para gestão pedagógica musical do GEM de Vargem Grande do Sul
Mobile app for musical pedagogical management at GEM Vargem Grande do Sul
PT-BR • English • Stack • Quick Start • Build Android • Scripts • Autor
Maestro é um aplicativo mobile (e web) criado para digitalizar e organizar a operação pedagógica musical do GEM de Vargem Grande do Sul.
O app substitui cadernos, fichas soltas e planilhas fragmentadas por um fluxo centralizado para cadastro de alunos, professores, métodos, aulas, presença, evolução musical, analytics e relatórios internos.
A proposta é tratar o acompanhamento musical como um sistema pedagógico contínuo, e não como uma coleção de anotações isoladas.
Objetivo: registrar aulas, acompanhar evolução musical e gerar relatórios pedagógicos em um fluxo compartilhado, confiável e prático para uso real da equipe.
Antes do Maestro, o acompanhamento pedagógico dependia de registros manuais, memória da equipe e consolidação manual de informações.
Isso dificultava:
- saber o que cada aluno estudou de fato;
- acompanhar evolução ao longo do tempo;
- identificar estagnação, aceleração ou queda de desempenho;
- consolidar relatórios por instrumento, grupo ou período;
- compartilhar a operação entre instrutores e encarregados;
- manter um histórico pedagógico consistente.
O Maestro resolve esse problema criando uma camada digital para registrar, consultar, analisar e exportar informações pedagógicas com mais clareza.
O app foi pensado para uso real por:
- Instrutores que lançam aulas no dia a dia.
- Encarregados locais e regionais que acompanham alunos e equipes.
- Coordenação pedagógica que precisa de relatórios e visão consolidada.
- Equipe do GEM que precisa operar em conjunto dentro da mesma organização.
- Cadastro completo de alunos.
- Edição, filtros e exclusão.
- Campos pedagógicos e administrativos no mesmo fluxo.
- Organização por instrumento, família, nível, graduação, congregação e status.
- Histórico individual conectado aos registros de aula.
- Registro detalhado de aulas individuais e teóricas.
- Seleção de professor e método.
- Conteúdo musical estruturado.
- Páginas, itens de lição, hinos, vozes e solfejo.
- Observações pedagógicas.
- Presença vinculada ao lançamento.
- Habilidades avaliadas de forma estruturada.
- KPIs individuais por aluno.
- Evolução mensal.
- Score médio.
- Delta de progresso.
- Radar de habilidades.
- Alertas de estagnação, aceleração e declínio.
- Visão coletiva do grupo por período.
- Ranking de alunos.
- Média por instrumento.
- Distribuição por nível.
- Crescimento do grupo.
- Alertas de alunos sem registro recente.
- Exportação em PDF, Excel, PNG e JSON.
- Cadastro de professores e encarregados.
- Papéis como Instrutor, Encarregado Local e Encarregado Regional.
- Uso compartilhado por organização no Supabase.
- Entrada automática em equipe por código.
- Cadastro e gerenciamento de métodos.
- Vínculo com instrumentos.
- Catálogo musical embutido em JSON.
- Suporte a métodos oficiais usados no contexto do GEM.
- Autenticação com e-mail e senha.
- Modo convidado.
- Tema claro/escuro com persistência.
- Logs locais exportáveis.
- ErrorBoundary global.
- Contexto operacional compartilhado entre telas.
- Script
scripts/capture-app-screens.jsque navega por todas as 19 telas do app. - Login automático, navegação por abas e sub-telas, clique em itens de lista.
- Geração de 95 screenshots com scroll em múltiplos chunks para cobrir conteúdo abaixo da dobra.
- Usa Puppeteer + servidor HTTP local para servir o bundle web do Expo.
- Ideal para documentação, testes visuais e geração de manual.
- Pipeline completo: screenshots →
supermega-prompt.md→ ChatGPT Premium → Gamma.app → PDF. - O prompt contextualiza o projeto, descreve cada tela com seus elementos de UI e instrui o ChatGPT a gerar prompts do Gamma em grupos de 10 slides.
- O resultado é um manual de usuário profissional e completo com capa, índice, todas as telas documentadas e conclusão.
| # | Tela | Chunks | Descrição |
|---|---|---|---|
| 01 | Início | 2 | Painel inicial com aulas recentes e CTAs rápidos |
| 02 | Centro de Aulas | 2 | Grade 2×2 com 4 tipos de aula |
| 03 | Aula Instrumental | 3 | Formulário de aula com método, páginas, hinos |
| 04 | Aula Teoria | 4 | Formulário de aula teórica |
| 05 | Aula Solfejo | 4 | Formulário de solfejo e percepção |
| 06 | Aula Mista | 4 | Formulário combinado |
| 07 | Presença | 2 | Marcação de presença em lote |
| 08 | Alunos | 5 | Lista de 61 alunos com busca |
| 09 | Detalhe do Aluno | 6 | Cadastro completo + histórico |
| 10 | Menu Mais | 6 | Grid de 9 sub-menus |
| 11 | Grupos | 6 | Turmas e alocação de membros |
| 12 | Professores | 6 | 17 professores cadastrados |
| 13 | Métodos | 8 | 15 métodos de ensino |
| 14 | Usuários | 6 | 51 perfis de usuário |
| 15 | Relatórios | 7 | Relatórios com filtros e exportação |
| 16 | Insights | 6 | Dashboard analítico com gráficos |
| 17 | Metas | 6 | Metas pedagógicas por aluno |
| 18 | Configurações | 6 | Preferências e perfil |
| 19 | Diagnóstico | 6 | Logs e suporte técnico |
Maestro is a mobile (and web) application created to digitize and organize the musical pedagogical operation of GEM Vargem Grande do Sul.
The app replaces notebooks, loose records and fragmented spreadsheets with a centralized workflow for students, teachers, methods, lessons, attendance, musical progress, analytics and internal reports.
The goal is to treat musical education tracking as a continuous pedagogical system, not as a collection of isolated notes.
Goal: register lessons, track musical progress and generate pedagogical reports through a shared, reliable and practical workflow for real team usage.
Before Maestro, pedagogical tracking depended on manual records, team memory and manual consolidation of information.
This made it difficult to:
- know what each student actually studied;
- compare progress over time;
- identify stagnation, acceleration or performance decline;
- consolidate reports by instrument, group or period;
- share the operation between instructors and coordinators;
- maintain a consistent pedagogical history.
Maestro solves this by creating a digital layer to register, query, analyze and export pedagogical information with greater clarity.
The app was designed for real use by:
- Instructors who register lessons in daily routines.
- Local and regional coordinators who track students and teams.
- Pedagogical coordination that needs reports and consolidated views.
- GEM teams that need to work together inside the same organization.
- Complete student registration.
- Editing, filtering and deletion.
- Pedagogical and administrative fields in the same workflow.
- Organization by instrument, family, level, graduation, congregation and status.
- Individual history connected to lesson records.
- Detailed registration of individual and theoretical lessons.
- Teacher and method selection.
- Structured musical content.
- Pages, lesson items, hymns, voices and solfege.
- Pedagogical notes.
- Attendance linked to lesson records.
- Structured skill assessment.
- Individual student KPIs.
- Monthly evolution.
- Average score.
- Progress delta.
- Skill radar.
- Alerts for stagnation, acceleration and decline.
- Collective group view by period.
- Student ranking.
- Average by instrument.
- Level distribution.
- Group growth.
- Alerts for students with no recent records.
- Export to PDF, Excel, PNG and JSON.
- Teacher and coordinator registration.
- Roles such as Instructor, Local Coordinator and Regional Coordinator.
- Shared usage through Supabase organization.
- Automatic team entry by code.
- Method registration and management.
- Instrument association.
- Embedded musical catalog in JSON.
- Support for official methods used in the GEM context.
- Email/password authentication.
- Guest mode.
- Persistent light/dark theme.
- Exportable local logs.
- Global ErrorBoundary.
- Shared operational context across screens.
scripts/capture-app-screens.jsnavigates all 19 screens.- Auto-login, tab navigation, sub-screen entry, list item clicking.
- Generates 95 screenshots with multi-chunk scrolling for below-fold content.
- Uses Puppeteer + local HTTP server to serve the Expo web bundle.
- Ideal for documentation, visual regression testing and manual generation.
- Complete flow: screenshots →
supermega-prompt.md→ ChatGPT Premium → Gamma.app → PDF. - The prompt contextualizes the project, describes every screen with UI elements and instructs ChatGPT to generate Gamma prompts in groups of 10 slides.
- Output is a professional, complete user manual with cover, table of contents, every screen documented and conclusion.
| Tecnologia | Versão | Uso no projeto |
|---|---|---|
| React Native | 0.81.5 | Base do app mobile |
| React | 19.1.0 | Camada de interface e estado |
| Expo | 54 | Tooling, runtime e integração nativa |
| React Navigation | Expo 54 compatible | Drawer + Native Stack navigation |
| Supabase JS | 2.98 | Auth, database, RPC e PostgREST |
| AsyncStorage | — | Persistência local de tema e estados auxiliares |
| Day.js | — | Manipulação e formatação de datas |
| React Native Chart Kit | — | Gráficos de evolução e analytics |
| React Native SVG | — | Base gráfica para charts |
| Expo Print | — | Geração de PDF |
| Expo Sharing | — | Compartilhamento de arquivos |
| Expo File System | — | Leitura/escrita de arquivos exportados |
| React Native View Shot | — | Captura de charts como imagem |
| XLSX | — | Exportação .xlsx |
| Puppeteer | — | Captura automatizada de screenshots web |
| Node.js HTTP | built-in | Servidor local para servir bundle web |
| Gradle / Android Native | Local SDK | Geração de APK release local |
| EAS Build | Perfis configurados | APK remoto e App Bundle |
O projeto separa claramente:
- interface reutilizável;
- contexto global;
- catálogos e dados estáticos;
- serviços de acesso a dados;
- regras utilitárias;
- telas de fluxo;
- scripts de suporte e automação;
- integrações nativas e build.
The project clearly separates:
- reusable interface;
- global context;
- catalogs and static data;
- data access services;
- utility rules;
- user flow screens;
- support and automation scripts;
- native integrations and build.
src/
├── components/
├── constants/
├── context/
├── data/
├── lib/
├── navigation/
├── screens/
├── services/
├── theme/
└── utils/
scripts/
├── capture-app-screens.js
├── seed-test-data.mjs
├── fix-org-membership.mjs
├── debug-auth.mjs
└── ... (15 scripts)
supabase/
├── migrations/
├── functions/
├── config.toml
└── seed.sqlsrc/
├── components/ # Reusable UI components and visual blocks
│ ├── AppUI/
│ ├── BottomNavBar/
│ ├── BulkEntryField/
│ ├── CollapsibleSection/
│ ├── DrawerMenuButton/
│ ├── ErrorBoundary/
│ ├── KpiCard/
│ ├── LessonTypeTabs/
│ ├── MultiSelectModal/
│ ├── RadarChart/
│ ├── ScoreInputRow/
│ ├── SelectModal/
│ └── UnitSwitcher/
│
├── constants/ # Domain enums and constants
│ ├── lessonTypes.js
│ └── units.js
│
├── context/ # Global application context
│ ├── AuthContext.js
│ └── OperationalContext.js
│
├── data/ # Local catalogs and embedded methods
│ ├── catalogs.js
│ └── methodCatalog/
│
├── lib/ # Central external clients
│ └── supabase.js
│
├── navigation/ # Navigation configuration
│ └── AppNavigator.js
│
├── screens/ # Application screens
│ ├── AttendanceScreen.js
│ ├── DashboardScreen.js
│ ├── LessonCenterScreen.js
│ ├── LoginScreen.js
│ ├── LogsScreen.js
│ ├── MainShellScreen.js
│ ├── MethodsScreen.js
│ ├── ReportsScreen.js
│ ├── SettingsScreen.js
│ ├── StudentDetailScreen.js
│ ├── StudentsScreen.js
│ ├── TeachersScreen.js
│ ├── TodayScreen.js
│ ├── TheoryGroupsScreen.js
│ └── (outras telas auxiliares)
│
├── services/ # Data access and CRUD/query rules
│ ├── db.js
│ └── org.js
│
├── theme/ # Light/dark theme and visual tokens
│ └── ThemeProvider.js
│
└── utils/ # Analytics, parsing, export and normalization
├── analytics.js
├── attendanceStore.js
├── bulkInputParser.js
├── calendarRules.js
├── errorHandler.js
├── exporters.js
├── lessonAdapters.js
├── lessonPayload.js
├── logger.js
├── methodCatalog.js
├── normalizers.js
├── pedagogy.js
├── reportInsights.js
├── reporting.js
└── theoryGroupsStore.jsA pasta scripts/ contém 15 utilitários para desenvolvimento, manutenção e documentação:
| Script | Finalidade |
|---|---|
capture-app-screens.js |
Navega por 19 telas do app via Puppeteer, gera 95 screenshots com scroll multi-chunk. Login automático como prints. |
capture-all-subscreens.js |
Captura todas as sub-telas do menu "Mais" individualmente. |
| Script | Finalidade |
|---|---|
seed-test-data.mjs |
Cria/verifica usuário de teste prints via service_role key. |
fix-org-membership.mjs |
Corrige associação do usuário prints à organização (organization_members). |
check-profile.mjs |
Verifica perfil e metadados do usuário no Supabase Auth. |
debug-auth.mjs |
Testa fluxo de autenticação (login, sessão, refresh). |
debug-live.mjs |
Depuração interativa com console remoto. |
debug-login.mjs |
Testa login com diferentes credenciais. |
verify-nav.mjs |
Verifica estrutura de navegação do app. |
verify-postfix.mjs |
Verifica integridade de dados pós-migração. |
| Script | Finalidade |
|---|---|
check-env.js |
Valida variáveis de ambiente. |
extract-hymn-catalog.py |
Extrai catálogo de hinos de fonte externa. |
test-login-edge.mjs |
Testa login via Supabase Edge Function. |
restore-bundle.js |
Restaura backup do bundle web. |
ai-project-scan.mjs |
Escaneia o projeto para contexto de IA. |
O Maestro possui um pipeline completo para geração automatizada de documentação:
capture-app-screens.js → 95 PNGs → supermega-prompt.md → ChatGPT → Gamma.app → PDF-
Capturar screenshots
node scripts/capture-app-screens.js
Gera 95 PNGs em
manual_maestro_package/screenshots/. -
Criar supermega prompt O arquivo
supermega-prompt.mdcontém:- Contexto completo do projeto
- Inventário de todas as 19 telas com descrição de cada campo e elemento UI
- Instruções para o ChatGPT gerar prompts para o Gamma.app
- Regras de grupos de 10 slides (capa no primeiro, conclusão no último)
-
Enviar para ChatGPT Premium
- Anexar o zip das 95 screenshots
- Colar o
supermega-prompt.md - ChatGPT retorna prompts numerados para o Gamma
-
Colar no Gamma.app Cada prompt gera 10 slides. O resultado final é um manual de usuário profissional com capa, índice, todas as telas documentadas e conclusão.
A migração 20260729170037 substituiu o modelo de segurança baseado em RLS por um sistema de políticas centralizadas usando a função is_member_of_org(org_id):
- Cada registro é vinculado a uma organização via
org_id. - A função
is_member_of_org()verifica se o perfil autenticado pertence à organização antes de permitir qualquer operação. - As funções de autenticação foram restritas ao papel
service_role. - A associação do usuário à organização é armazenada em
organization_members.
organizations
└──< profiles
└──< students
└──< teachers
└──< methods
└──< lessonrecords
students
└──< lessonrecords >── teachers
└──> methods- Uma
organizationagrupa perfis, alunos, professores e registros. - Um
profilerepresenta o usuário autenticado. - Um
studentpode ter vários registros emlessonrecords. - Um
teacherpode lançar várias aulas. - Um
methodpode ser associado a vários registros de aula. joinOrgByCodeconecta o usuário a uma organização compartilhada.
org_id— referência à organizaçãouser_id— referência ao perfil do usuáriomember_role— papel na organização (admin, member)
id(uuid, referência ao Auth)username— identificador único de loginfull_name— nome exibidorole— papel no sistema (admin, instrutor)org_id— organização vinculadateacher_id— referência opcional ao registro de professor
id(uuid)name— nome da organizaçãojoin_code— código para entrada automática de membros
id(uuid)full_name,instrument,category,levelcongregation,status,start_dateobservations,address,phonebirth_date,baptism_date,instrument_change_noteorg_id— organização vinculada
id(uuid)full_name,instrument,congregationrole_kind— Instrutor, Encarregado Local, Regionalactive,profile_id,org_id
id(uuid)name,instruments[],active,notesowner_id— criador do métodoorg_id— organização vinculada
id(uuid)student_id,teacher_id,method_idlesson_date,lesson_type(instrumental, theoretical, mixed, solfege)method_name,pages,hymnslesson_items[],page_items[],content_items[]skill_rhythm,skill_reading,skill_technique,skill_posture,skill_musicalityattendance,observations,org_id
id(uuid)name,family,active
Conecta um usuário autenticado a uma organização compartilhada através de um código de equipe.
Retorna o e-mail de login associado a um username (usado no fluxo de login legado).
Finaliza o registro de um novo usuário após validação do código de equipe.
Valida se um código de equipe é válido e retorna os metadados da organização.
- Node.js 20+ recommended
- npm or pnpm
- Expo CLI through
npx - Android Studio with Android SDK
- Java 17
- ADB configured in PATH
- Configured Supabase project
- Android device with Expo Go or Android emulator
git clone https://github.com/BarujaFe1/Maestro.git
cd Maestronpm installCreate a .env file in the project root:
EXPO_PUBLIC_SUPABASE_URL=https://SEU-PROJETO.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=sua_chave_anonnpx expo startTunnel mode, useful when the device is not on the same network:
npx expo start --tunnel- Install Expo Go on the phone.
- Run:
npx expo start --tunnel- Scan the QR Code with Expo Go.
With the emulator already open:
npx expo startThen press a in the Expo terminal.
- Java 17
- Android Studio
- Android SDK
- Android environment variables configured
android/folder present in the project- Functional Gradle setup
$env:JAVA_HOME="C:\Program Files\Java\jdk-17"
$env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk"
$env:Path += ";$env:ANDROID_HOME\platform-tools"
$env:Path += ";$env:ANDROID_HOME\emulator"
$env:Path += ";$env:ANDROID_HOME\cmdline-tools\latest\bin"cd android
.\gradlew.bat assembleReleaseGenerated APK:
android/app/build/outputs/apk/release/app-release.apkInstall through ADB:
adb install -r android/app/build/outputs/apk/release/app-release.apkThe project also supports EAS profiles:
developmentpreview— internal APKproduction— App Bundle
Example:
eas build --platform android --profile preview- Projeto Supabase criado.
- Authentication habilitado (e-mail/senha).
- Migrations aplicadas.
- Organização inicial criada.
- Código de equipe definido.
As migrações estão em:
supabase/migrations/Aplicar via Supabase CLI ou SQL Editor.
Scripts disponíveis em scripts/:
# Verificar/criar usuário de teste
node scripts/check-profile.mjs
# Corrigir associação à organização
node scripts/fix-org-membership.mjs
# Seed completo de dados de demonstração
node scripts/seed-test-data.mjsOs scripts usam um Personal Access Token (PAT) para obter a service_role key via Management API e operar diretamente nas tabelas.
- Criar a organização em
organizations. - Definir um
join_code. - Usuários entram automaticamente via
joinOrgByCode. - A função
is_member_of_org()controla o acesso aos dados.
O Maestro também está disponível como site web funcional (Expo Web).
🔗 Demo ao vivo: https://maestro-demo-tau.vercel.app
npx expo export -p web --output-dir dist
node scripts/injectBanner.jsO Supabase JS v2.98.0 possui um deadlock no lock queue quando getUser() é chamado dentro do lock do setSession. A cadeia é:
supabase.from() → fetch wrapper → _getAccessToken() → getSession() → acquire lock (JÁ OCUPADO) → DEADLOCK
Solução aplicada no bundle: substituir _getAccessToken() para ler o token diretamente do localStorage em vez de chamar getSession():
async _getAccessToken() {
try {
var e = JSON.parse(localStorage.getItem('maestro-auth-v3') || '{}');
if (e?.access_token) return e.access_token;
} catch {}
return this.supabaseKey;
}Isso eliminou o deadlock e permitiu que todas as chamadas PostgREST funcionassem sem depender do lock do gotrue-js. Sem esse patch, o app web ficava permanentemente pendurado ao tentar carregar qualquer lista (alunos, professores, etc.).
O patch é aplicado manualmente no arquivo:
dist/_expo/static/js/web/AppEntry-*.jsvercel --prod \
-e EXPO_PUBLIC_SUPABASE_URL="https://seu-projeto.supabase.co" \
-e EXPO_PUBLIC_SUPABASE_ANON_KEY="sua_chave_anon"- Build:
vercel.jsoncom build commandnpx expo export -p web --output-dir dist && node scripts/injectBanner.js - Output: pasta
dist/(index.html + bundle JS + assets) - SPA: rewrite
/(.*) → /index.htmlnovercel.json - Banner:
scripts/injectBanner.jsinjeta banner de demo no HTML final
The project uses Expo for fast iteration while keeping a native Android output for predictable local Gradle builds.
Supabase was chosen because the project needs authentication, relational data, RPC, shared team usage and simple JavaScript/TypeScript integration.
Analytics live inside the app because many pedagogical decisions need to be available during lessons, follow-ups and internal meetings.
Local export reduces friction for internal use, allowing the team to generate PDFs, spreadsheets, images, backups and reports without an external dashboard.
A team code reduces onboarding friction and centralizes the shared pedagogical operation.
O @supabase/supabase-js v2.98.0 introduziu um sistema de lock (via navigator.locks ou processLock) para sincronizar chamadas de refresh de token. Quando o fetch wrapper personalizado chama _getAccessToken() → getSession() dentro do lock do setSession, ocorre um deadlock que impede qualquer operação PostgREST.
A solução foi substituir _getAccessToken() por leitura direta do localStorage (chave maestro-auth-v3), onde o próprio gotrue-js persiste a sessão. Isso elimina a dependência do lock sem comprometer a segurança.
A migração V6 substituiu o modelo de RLS tradicional por políticas centralizadas baseadas na função is_member_of_org(). Isso:
- Simplifica a manutenção de políticas (uma função, não uma política por tabela)
- Garante que todos os acessos passem pela mesma verificação
- Permite auditoria centralizada
- Restringe funções de autenticação ao
service_role
Sintoma: o app web fica "carregando" infinitamente após o login. As listas de alunos, professores, métodos não aparecem.
Causa: O _getAccessToken() interno chama getSession() que adquire um lock. Se o lock já estiver ocupado (por setSession durante o login), todas as chamadas PostgREST subsequentes entram em deadlock.
Solução: Patch manual no bundle (ver seção "Web Demo / Patch do bundle web" acima).
Status: Não resolvido upstream. O patch manual é necessário até atualizar o @supabase/supabase-js para uma versão que corrija o lock queue.
Operações administrativas (criar usuários, gerenciar organizações) exigem a service_role key, obtida via Management API com um PAT. A anon key não tem permissão para escrever nas tabelas devido às políticas V6.
- Email/password authentication.
- Guest mode.
- Automatic organization entry by code.
- Complete student registration.
- Teacher/coordinator registration.
- Method registration and management.
- Detailed lesson records.
- Individual analytics.
- Collective analytics.
- Export to PDF, Excel, PNG and JSON.
- Exportable local logs.
- Persistent light/dark theme.
- JSON method catalog.
- Drawer + Native Stack navigation.
- Global ErrorBoundary.
- V6 Security Hardening (is_member_of_org).
- Automated screenshot capture (19 screens, 95 shots).
- User manual generation pipeline (ChatGPT + Gamma).
- Web bundle deadlock patch.
- Continuous operational UX refinements.
- Theory groups and group attendance flow.
- Performance adjustments for large lists.
- Evolution of goals and group pedagogical modeling.
- Additional pedagogical goals consolidation.
- Better reports by group/team.
- Internal distribution improvements.
- Expansion of musical catalogs.
- Broader pedagogical metrics coverage.
- Upgrade supabase-js to fix lock queue upstream.
feat: adiciona exportação de relatório por instrumento
fix: corrige cálculo de delta de progresso
refactor: simplifica normalização de lessonrecords
docs: atualiza instruções de build Androidgit checkout -b feat/nome-da-featureOpen a Pull Request with:
- problem context;
- change scope;
- screenshots or GIFs when UI is involved;
- database or migration notes, if applicable.
When reporting an issue, include:
- affected screen;
- expected behavior;
- current behavior;
- steps to reproduce;
- terminal log;
- exported app log, if applicable;
- Android version and device.
Developed by Felipe Alirio Baruja.
- Portfolio: https://barujafe.vercel.app/
- GitHub: github.com/BarujaFe1
- LinkedIn: linkedin.com/in/barujafe
- Repository: github.com/BarujaFe1/Maestro
MIT License.
See LICENSE for details.
Maestro
Gestão pedagógica musical com clareza, histórico e evolução.
Musical pedagogy management with clarity, history and progress tracking.