ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Free CAPS-aligned exam papers, memos and interactive quizzes for South African learners, Grades 4–12.
EducationTypeScript · HTMLGitHub @EndersWitchOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
A Duolingo-style quiz experience for CAPS-aligned school learning.
Next.js 14 · TypeScript · Tailwind CSS · Supabase
The quiz system expects these tables. Create them if they don't exist.Read the full README ↗A Duolingo-style quiz experience for CAPS-aligned school learning.
Next.js 14 · TypeScript · Tailwind CSS · Supabase
# 1. Install dependencies
npm install
# 2. Set up environment variables
cp .env.example .env.local
# Fill in NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY
# 3. Run locally
npm run dev
# → http://localhost:3000/quiz
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | ✅ | Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | ✅ | Supabase anon/public key |
ANTHROPIC_API_KEY | For Bloom | Powers Bloom, the Deep Learn tutor (/bloom). Locally it goes in the git-ignored .env.local; never commit it |
BLOOM_ACCESS | Optional | Who can use Bloom: off, testers or everyone. Unset means off, except under npm run dev (testers) |
BLOOM_TESTERS | Optional | Extra Bloom testers by email, comma-separated. Admin accounts are always testers |
The quiz system expects these tables. Create them if they don't exist.
quiz_levelscreate table quiz_levels (
id uuid primary key default gen_random_uuid(),
broad_topic text not null,
subject text not null,
grade int not null,
subtopic_id text,
level_number int default 1,
title text not null,
description text,
section_type text not null, -- 'level' | 'subtopic_mastery' | 'broad_topic_mastery' | 'general_practice'
question_count int default 10,
xp_reward int default 50,
pass_threshold float default 0.6,
is_premium boolean default false,
-- Learning zone fields
intro text,
concepts jsonb, -- array of LearningConcept objects
tested text[], -- array of strings
difficulty text -- 'easy' | 'medium' | 'hard'
);
questionscreate table questions (
id uuid primary key default gen_random_uuid(),
grade int not null,
subject text not null,
broad_topic text not null,
subtopic_id text,
level_id uuid references quiz_levels(id),
section_type text not null,
question_text text not null,
option_a text not null,
option_b text not null,
option_c text not null,
option_d text not null,
correct_option text not null, -- 'a' | 'b' | 'c' | 'd'
explanation text,
is_premium boolean default false
);
user_progresscreate table user_progress (
id uuid primary key default gen_random_uuid(),
user_id uuid references auth.users(id) on delete cascade,
level_id uuid references quiz_levels(id),
subtopic_id text,
completed boolean default false,
passed boolean default false,
best_score int default 0,
attempts int default 0,
xp_earned int default 0,
completed_at timestamptz,
unique (user_id, level_id)
);
profilescreate table profiles (
id uuid primary key references auth.users(id) on delete cascade,
display_name text,
total_xp int default 0,
streak int default 0,
is_premium boolean default false,
is_founder boolean default false,
grade int
);
create or replace function award_quiz_xp(p_user_id uuid, p_xp int)
returns void as $$
begin
update profiles
set total_xp = total_xp + p_xp
where id = p_user_id;
end;
$$ language plpgsql security definer;
-- user_progress: users can only read/write their own rows
alter table user_progress enable row level security;
create policy "users own progress" on user_progress
using (auth.uid() = user_id) with check (auth.uid() = user_id);
-- quiz_levels: public read
alter table quiz_levels enable row level security;
create policy "public read levels" on quiz_levels for select using (true);
-- questions: public read for free, premium gated by app logic
alter table questions enable row level security;
create policy "public read questions" on questions for select using (true);
-- profiles: users read/write own
alter table profiles enable row level security;
create policy "users own profile" on profiles
using (auth.uid() = id) with check (auth.uid() = id);
/quiz Browse all topics (grade filter)
/quiz/[broadTopic] Broad topic overview + subtopics
/quiz/[broadTopic]/[subtopic] Subtopic level path
/quiz/[broadTopic]/[subtopic]/[level]/learn Learning zone (pre-quiz)
/quiz/[broadTopic]/[subtopic]/[level]/play Quiz runner
/quiz/[broadTopic]/practice General practice entry
broadTopic and subtopic in URLs are URI-encoded versions of the actual string values stored in Supabase.
For example: Parts of Speech → Parts%20of%20Speech
Two-layer mastery — both layers are required:
Normal levels (Level 1, Level 2, Level 3...)
↓ all passed
Subtopic Mastery (e.g. "Nouns Mastery")
↓ all subtopic masteries passed
Broad Topic Mastery (e.g. "Parts of Speech Mastery") ← final boss
In quiz_levels:
section_type = 'level'section_type = 'subtopic_mastery' + same subtopic_idsection_type = 'broad_topic_mastery' + same broad_topicEvery quiz attempt:
Implemented in lib/questions.ts → shuffleQuestion() and fetchLevelQuestions().
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYThis quiz system integrates cleanly alongside the existing static HTML pages (index.html, papers.html, admin.html) — they are separate and unaffected.
| Token | Value |
|---|---|
| Plum | #2B1E3F |
| Cyan | #6DD3CE |
| Coral | #FF5E5B |
| Amber | #F5C842 |
| Font Heading | Poppins 800/900 |
| Font Body | DM Sans |