diff --git a/harness/js-scaffold/PROMPT.md b/harness/js-scaffold/PROMPT.md
new file mode 100644
index 0000000..140ccad
--- /dev/null
+++ b/harness/js-scaffold/PROMPT.md
@@ -0,0 +1,8 @@
+# JS Quiz Scaffold
+
+A minimal vanilla JS quiz that checks answers and colors buttons.
+
+## Rules
+- Do not change the correct answer without updating specs/quiz.md
+- Tests must pass after every change: `npm test`
+- Do not add frameworks or large dependencies
\ No newline at end of file
diff --git a/harness/js-scaffold/README.md b/harness/js-scaffold/README.md
new file mode 100644
index 0000000..1fa361e
--- /dev/null
+++ b/harness/js-scaffold/README.md
@@ -0,0 +1,12 @@
+# JS Scaffold Example
+
+Shows how Ralph works with a frontend JS project.
+
+## Structure
+- `PROMPT.md` — rules Ralph must follow
+- `specs/` — behavior specs Ralph must not break
+- `npm test` — fails if behavior is broken
+
+## Usage
+npm install
+npm test
\ No newline at end of file
diff --git a/harness/js-scaffold/index.html b/harness/js-scaffold/index.html
new file mode 100644
index 0000000..61a311c
--- /dev/null
+++ b/harness/js-scaffold/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+ Quiz
+
+
+
+
+
+
+
Quiz Test
+
+
+
NaN === NaN
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/harness/js-scaffold/package.json b/harness/js-scaffold/package.json
new file mode 100644
index 0000000..6b560af
--- /dev/null
+++ b/harness/js-scaffold/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "js-scaffold" ,
+ "type": "module" ,
+ "scripts": {
+ "test": "node --test test.js"
+ }
+
+}
\ No newline at end of file
diff --git a/harness/js-scaffold/quiz.js b/harness/js-scaffold/quiz.js
new file mode 100644
index 0000000..f92c176
--- /dev/null
+++ b/harness/js-scaffold/quiz.js
@@ -0,0 +1,21 @@
+export function checkAnswer(answer){
+const correctAnswer = false;
+return answer===correctAnswer
+}
+function testQuiz(){
+ const trueBtn=document.getElementById('btn-true');
+ const falseBtn=document.getElementById('btn-false');
+ trueBtn.addEventListener('click',()=>{
+const isCorrect = checkAnswer(true);
+trueBtn.style.background = isCorrect ? '#d4edda' : '#f8d7da';
+falseBtn.style.background=''
+ })
+ falseBtn.addEventListener('click',()=>{
+const isCorrect = checkAnswer(false);
+falseBtn.style.background = isCorrect ? '#d4edda' : '#f8d7da';
+trueBtn.style.background=''
+ })
+}
+ if(typeof document!=='undefined'){
+ testQuiz()
+ }
\ No newline at end of file
diff --git a/harness/js-scaffold/specs/quiz.md b/harness/js-scaffold/specs/quiz.md
new file mode 100644
index 0000000..ba8886c
--- /dev/null
+++ b/harness/js-scaffold/specs/quiz.md
@@ -0,0 +1,6 @@
+# Quiz Specs
+
+## checkAnswer(answer)
+- returns true when answer matches the correct answer
+- returns false otherwise
+- correct answer for "NaN === NaN" is false
\ No newline at end of file
diff --git a/harness/js-scaffold/test.js b/harness/js-scaffold/test.js
new file mode 100644
index 0000000..2e1419c
--- /dev/null
+++ b/harness/js-scaffold/test.js
@@ -0,0 +1,8 @@
+import test from 'node:test';
+import assert from 'node:assert';
+import { checkAnswer } from './quiz.js';
+test(' Quiz - checkAnswer function',()=>{
+ assert.strictEqual( checkAnswer(false) , true );
+ assert.strictEqual(checkAnswer(true) , false)
+})
+