Cloud-based student competency tracking system with Firebase, star ratings, badges, teacher management, and PDF reports. Based on Swiss Lehrplan Informatik & Medien curriculum.
A cloud-based digital competency tracking system (Kompetenzpass) for Swiss educational settings. Students self-assess skills using star ratings, earn badges, and track progress. Teachers manage competencies, classes, bulk-create students, and award custom badges. All data syncs in real-time via Firebase Firestore.
You'll build and maintain a full-stack educational web app using vanilla JavaScript, Firebase (Auth + Firestore), and jsPDF. The app implements a hierarchical competency structure (3 areas → competency groups → 87 levels), a 16-badge gamification system, teacher admin tools, and PDF export with printable student credentials.
**Tech Stack:**
**File Structure:**
```
kompetenzenpass-cloud/
├── index.html # Main app + Firebase config
├── app-firebase.js # Core logic (~110KB)
├── style.css # Styling + animations (~14KB)
├── import-competencies.html # Curriculum import tool
├── Kompetenzen-Lehrplan.csv # 87 competency levels
├── parse-csv.js # CSV parser
├── firestore.rules # Security rules (MANDATORY)
└── CLAUDE.md # Full documentation
```
**users** (Auth + Role)
```javascript
{
name: string,
email: string,
role: "student" | "teacher",
class: string, // e.g., "7a"
createdAt: timestamp,
lastActive: timestamp
}
```
**classes** (Grade-Level Context)
```javascript
{
name: string, // e.g., "7a"
description: string,
grade: string, // e.g., "7", "KiGa", "3./4."
createdBy: string, // Teacher UID
createdAt: timestamp
}
```
**competencyAreas** (3 Areas)
```javascript
{
id: string, // "medien", "informatik", "anwendung"
name: string,
emoji: string, // 📱, 💻, 🎯
order: number
}
```
**competencies** (Competency Groups)
```javascript
{
id: string, // e.g., "IB-1-1"
areaId: string, // FK to competencyAreas
name: string,
lpCodePrefix: string, // e.g., "IB.1.1"
order: number
}
```
**competencyLevels** (87 Rated Levels)
```javascript
{
id: string, // e.g., "IB-1-1-a"
competencyId: string, // FK to competencies
lpCode: string, // e.g., "IB.1.1.a"
description: string,
cycles: array<string>, // ["Zyklus 1", "Zyklus 2"]
grades: array<string>, // ["KiGa", "1./2.", "3./4."]
isBasicRequirement: boolean,
order: number
}
```
**competencyIndicators** (Granular "Ich kann..." Statements)
```javascript
{
id: string,
levelId: string, // FK to competencyLevels
text: string, // e.g., "Ich kann Nicknames im Internet beurteilen"
order: number,
createdBy: string, // Teacher UID
createdAt: timestamp
}
```
**progress** (Student Ratings + Comments)
```javascript
{
ratings: {
[levelId]: number, // 0-5 stars (e.g., "IB-1-1-a": 4)
indicator_[id]: number // Indicator ratings (auto-averaged to parent level)
},
comments: {
[levelId]: string // Teacher feedback
},
pendingReviews: {
[levelId]: object // Student review submissions
},
lastUpdated: timestamp
}
```
**progressHistory** (Timeline of Changes)
```javascript
{
userId: string,
levelId: string,
oldRating: number,
newRating: number,
changedBy: string, // "student" or teacher UID
changedAt: timestamp
}
```
**userBadges** (Earned Badges)
```javascript
{
userId: string,
badgeId: string, // FK to BADGE_DEFINITIONS or customBadges
awardedAt: timestamp,
awardedBy: string, // Optional: Teacher UID (manual awards)
awardedByName: string, // Stored directly (avoids permission issues)
reason: string, // Optional: Award reason
notified: boolean
}
```
**customBadges** (Teacher-Created Badges)
```javascript
{
name: string,
description: string,
emoji: string,
rarity: "common" | "rare" | "epic" | "legendary",
color: string, // Hex code
type: "custom",
category: "teacher",
createdBy: string,
createdAt: timestamp,
order: number
}
```
**artifacts** (File Uploads)
```javascript
{
userId: string,
competencyId: string, // Associated level ID
fileName: string,
fileUrl: string, // Firebase Storage URL
fileType: string, // MIME type
uploadedAt: timestamp
}
```
```bash
npm install -g firebase-tools
firebase login
firebase init firestore
```
**Configure Firebase:**
1. Create project in [Firebase Console](https://console.firebase.com/)
2. Enable Authentication (Email/Password)
3. Enable Firestore Database
4. Copy config to `index.html:16-24`
**Deploy Security Rules (CRITICAL):**
```bash
firebase deploy --only firestore:rules
```
**Key Principles:**
**Access Matrix:**
**One-Time Setup:**
1. Open `import-competencies.html`
2. Login as teacher
3. Click "Import starten"
4. Imports 87 competency levels from `Kompetenzen-Lehrplan.csv`
**Creates:**
**Student Dashboard:**
**Teacher Dashboard:**
**Badge System (16 Automatic + Unlimited Custom):**
**Milestone Badges:**
**Area Expert Badges:**
**Time-Based Badges:**
**Special Badges:**
**Firestore Queries:**
```javascript
// Get user progress with real-time listener
const progressRef = doc(db, 'progress', auth.currentUser.uid);
onSnapshot(progressRef, (snapshot) => {
const data = snapshot.data();
updateUI(data.ratings);
});
// Filter competency levels by grade
const levelsQuery = query(
collection(db, 'competencyLevels'),
where('grades', 'array-contains', userGrade)
);
```
**Badge Award Logic:**
```javascript
// Check if badge criteria met
function checkBadge(badgeId, userId) {
const badge = BADGE_DEFINITIONS[badgeId];
const criteria = badge.criteria;
// Example: "aufsteiger" badge (10 competencies with 3+ stars)
const ratings = getUserRatings(userId);
const count = Object.values(ratings).filter(r => r >= 3).length;
if (count >= 10) {
awardBadge(userId, badgeId);
}
}
// Award badge (auto or manual)
async function awardBadge(userId, badgeId, awardedBy = null, reason = null) {
const existingBadge = await getDoc(
doc(db, 'userBadges', `${userId}_${badgeId}`)
);
if (!existingBadge.exists()) {
await setDoc(doc(db, 'userBadges', `${userId}_${badgeId}`), {
userId,
badgeId,
awardedAt: serverTimestamp(),
awardedBy,
reason,
notified: false
});
}
}
```
**PDF Export:**
```javascript
import { jsPDF } from 'jspdf';
function exportPDF(userId) {
const doc = new jsPDF();
const progress = getUserProgress(userId);
const badges = getUserBadges(userId);
// Add competency ratings
progress.forEach((rating, index) => {
doc.text(`${rating.name}: ${'⭐'.repeat(rating.stars)}`, 10, 20 + (index * 10));
});
// Add badges
doc.addPage();
doc.text('Badges:', 10, 20);
badges.forEach((badge, index) => {
doc.text(`${badge.emoji} ${badge.name}`, 10, 30 + (index * 10));
});
doc.save(`kompetenzpass_${userId}.pdf`);
}
```
**How It Works:**
1. Teacher assigns `grade` (e.g., "7", "3./4.") to class
2. Student is assigned to class (e.g., "7a")
3. App fetches class's grade from Firestore
4. Filters `competencyLevels` where `grades` array contains that grade
5. Teachers see all levels (no filtering)
**Example:**
**Process:**
1. Teacher provides CSV with columns: `name`, `class`
2. App auto-generates credentials: `email` ([email protected]), `password` (8-char random)
3. Batch creates Firebase Auth accounts
4. Creates Firestore `users` documents
5. Displays printable credentials table
**Security:**
**Student Workflow:**
1. Student submits rating change as "review"
2. Stored in `progress.pendingReviews.{levelId}`
3. Teacher approves/rejects via dashboard
4. On approval: `progress.ratings` updated, `progressHistory` created
**Teacher Workflow:**
1. View pending reviews by student
2. Approve: Rating applied + history entry
3. Reject: Review deleted, rating unchanged
**Student Features:**
**Teacher Features:**
**Security:**
**Security:**
**Performance:**
**German UI:**
**Grade Matching:**
**Add new automatic badge:**
1. Define in `BADGE_DEFINITIONS` (app-firebase.js)
2. Add criteria check function
3. Call check function in `updateProgress()` or appropriate trigger
4. Deploy updated app
**Add new competency area:**
1. Add document to `competencyAreas` collection
2. Import related competencies and levels
3. Update import script if needed
**Change rating scale:**
1. Update star rendering logic in `app-firebase.js`
2. Adjust badge criteria (e.g., "3+ stars" → "60%+")
3. Update PDF export formatting
**Enable file uploads:**
1. Create Firebase Storage bucket
2. Add upload UI in student dashboard
3. Create `artifacts` document on upload
4. Add download link in teacher reports
```bash
git clone https://github.com/baenni-coder/kompetenzenpass-cloud.git
cd kompetenzenpass-cloud
firebase init firestore
firebase deploy --only firestore:rules
git push origin main
open index.html
```
**First-Time Setup:**
1. Register first teacher account manually
2. Open `import-competencies.html` and import curriculum
3. Create first class (e.g., "7a", grade "7")
4. Bulk-create students for that class
5. Print and distribute credentials
6. Students login and start rating competencies
7. Automatic badges are awarded on progress updates
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/swiss-digital-competency-pass-cloud/raw