Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LearnProgramming β€” Tutorial Platform Design

Core Concept

Teach non-coders programming by bridging Excel spreadsheets β†’ functional programming.

and Docx experience -> markdown, html.

People already understand "B column = A column + 3". That IS a pure function. "Drag the formula down every row" IS map. "SUM(A:A)" IS reduce. "Show rows where A > 5" IS filter.

The app makes this connection explicit: left-top is an interactive spreadsheet, left-bottom shows the equivalent code, and the AI tutor on the right helps explain.


Layout

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  [Pure Functions] [Map] [Filter] [Reduce]    ← Topic Bar        β”‚
β”‚  [Ch.1 Cells] [Ch.2 Formulas] [Ch.3 Compose] ← Chapter Tabs    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                 β”‚                                β”‚
β”‚   Interactive Spreadsheet       β”‚       AI Chat Panel            β”‚
β”‚   β”Œβ”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”            β”‚                                β”‚
β”‚   β”‚   β”‚ A β”‚ B β”‚ C β”‚            β”‚  πŸ€– Welcome! Try typing 3     β”‚
β”‚   β”‚ 1 β”‚ 1 β”‚ 4 β”‚   β”‚            β”‚     in cell A1...             β”‚
β”‚   β”‚ 2 β”‚ 2 β”‚ 5 β”‚   β”‚            β”‚                                β”‚
β”‚   β”‚ 3 β”‚ 3 β”‚ 6 β”‚   β”‚            β”‚  πŸ‘€ What does =A1+3 mean?     β”‚
β”‚   β””β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”˜            β”‚                                β”‚
β”‚                                 β”‚  πŸ€– Great question! When you  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚     write =A1+3, you're       β”‚
β”‚  β”‚ // equivalent code       β”‚    β”‚     creating a pure function  β”‚
β”‚  β”‚ const B = A.map(         β”‚    β”‚     that...                   β”‚
β”‚  β”‚   x => x + 3             β”‚    β”‚                                β”‚
β”‚  β”‚ )                         β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              [JSβ–Ύ] [β–ΆRun] β”‚    β”‚  β”‚ Ask anything...        β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Footer                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Left top: Interactive Excel-like grid (editable cells, formulas)
  • Left bottom: Code editor (JS/Python/SQL) with run button
  • Right: AI chat session (Gemini, decoupled for swapping)
  • Top: Topic bar + chapter tabs

Tutorial Content Progression

Topic 1: Pure Functions (Excel as Calculator)

  • Ch 1 β€” Cells & Values: Types (numbers, text), entering data
  • Ch 2 β€” Simple Formulas: =A1+3 β†’ const add3 = (x) => x + 3 β€” pure function concept
  • Ch 3 β€” Referencing: =A1+B1 β†’ function composition, multiple inputs

Topic 2: Map (Apply to Every Row)

  • Ch 1 β€” Column Formulas: Drag formula down = A.map(x => x + 3)
  • Ch 2 β€” Transformations: String ops, type conversion across columns

Topic 3: Filter (Show Only Some Rows)

  • Ch 1 β€” Conditions: =IF(A1>5,...) β†’ .filter(x => x > 5)
  • Ch 2 β€” SQL WHERE: Same data, SQL syntax SELECT * FROM data WHERE A > 5

Topic 4: Reduce (Summarize a Column)

  • Ch 1 β€” Aggregation: =SUM(A:A), =COUNT(...), =AVERAGE(...) β†’ .reduce()
  • Ch 2 β€” Building Reduce: Step-by-step accumulator concept

File Structure

src/
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ backend/
β”‚   β”‚   └── llm/
β”‚   β”‚       β”œβ”€β”€ types.ts            # LLMProvider interface, ChatMessage
β”‚   β”‚       β”œβ”€β”€ gemini.ts           # Google Gemini implementation
β”‚   β”‚       β”œβ”€β”€ provider.ts         # Factory + active provider state
β”‚   β”‚       └── index.ts            # Re-exports
β”‚   β”‚
β”‚   β”œβ”€β”€ tutorial/
β”‚   β”‚   β”œβ”€β”€ content/
β”‚   β”‚   β”‚   β”œβ”€β”€ types.ts            # Topic, Chapter, Lesson types
β”‚   β”‚   β”‚   β”œβ”€β”€ index.ts            # Content registry (all topics)
β”‚   β”‚   β”‚   β”œβ”€β”€ pure-functions.ts   # Topic 1 chapters
β”‚   β”‚   β”‚   β”œβ”€β”€ map.ts              # Topic 2 chapters
β”‚   β”‚   β”‚   β”œβ”€β”€ filter.ts           # Topic 3 chapters
β”‚   β”‚   β”‚   └── reduce.ts           # Topic 4 chapters
β”‚   β”‚   β”‚
β”‚   β”‚   └── engine/
β”‚   β”‚       β”œβ”€β”€ spreadsheet.ts      # Spreadsheet data model + formula eval
β”‚   β”‚       β”œβ”€β”€ executor.ts         # Code runner (JS in-browser, Python via Pyodide, SQL via sql.js)
β”‚   β”‚       └── bridge.ts           # Table ↔ Code linking (select col β†’ function param)
β”‚   β”‚
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ TopicBar.svelte         # Horizontal topic navigation
β”‚   β”‚   β”œβ”€β”€ ChapterTabs.svelte      # Tab strip for chapters
β”‚   β”‚   β”œβ”€β”€ Spreadsheet.svelte      # Interactive Excel-like grid
β”‚   β”‚   β”œβ”€β”€ CodeEditor.svelte       # Code editor + language selector + run
β”‚   β”‚   β”œβ”€β”€ ChatPanel.svelte        # AI chat interface
β”‚   β”‚   └── SettingsModal.svelte    # API key input, preferences
β”‚   β”‚
β”‚   └── stores/
β”‚       β”œβ”€β”€ tutorial.svelte.ts      # Current topic/chapter state (Svelte 5 runes)
β”‚       └── settings.svelte.ts      # API key, preferences (localStorage-backed)
β”‚
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ +layout.svelte              # Shell: topic bar, footer
β”‚   └── +page.svelte                # Main 3-panel layout
β”‚
└── app.css                         # Tailwind import

Key Modules Detail

1. LLM Backend (src/lib/backend/llm/)

Decoupled design β€” swap Gemini for OpenAI/Anthropic by implementing the interface:

// types.ts
interface ChatMessage {
	role: 'user' | 'assistant' | 'system';
	content: string;
}

interface LessonContext {
	topic: string;
	chapter: string;
	tableData: CellData[][];
	currentCode: string;
	language: 'js' | 'python' | 'sql';
}

interface LLMProvider {
	name: string;
	sendMessage(messages: ChatMessage[], context?: LessonContext): Promise<string>;
}
// gemini.ts β€” first implementation
class GeminiProvider implements LLMProvider {
	name = 'Gemini';
	constructor(private apiKey: string) {}
	async sendMessage(messages, context?) {
		// Prepend system prompt with lesson context
		// Call Gemini API (generativelanguage.googleapis.com)
		// Return text response
	}
}
  • API key stored in localStorage, entered via SettingsModal
  • System prompt includes current lesson context so AI gives relevant help
  • Provider is created/swapped at runtime via provider.ts

2. Spreadsheet Engine (src/lib/tutorial/engine/spreadsheet.ts)

Pure TypeScript, no UI:

type CellValue = string | number | null;
type CellData = {
	raw: string; // what user typed (e.g. "=A1+3")
	computed: CellValue; // evaluated result (e.g. 4)
	formula: boolean; // starts with "="
};

class SpreadsheetModel {
	cells: CellData[][]; // [row][col]

	setCellRaw(row: number, col: number, raw: string): void;
	evaluate(): void; // recalculate all formulas
	getColumnValues(col: number): CellValue[];
	toArray(): CellValue[][]; // plain values for code execution
}

Formula evaluation:

  • Parse =A1+3 style references
  • Support basic ops: +, -, *, /
  • Support basic functions: SUM(), COUNT(), AVERAGE(), IF()
  • Dependency-order evaluation (topological sort on cell refs)

3. Code Executor (src/lib/tutorial/engine/executor.ts)

interface ExecutionResult {
	output: string; // stdout
	returnValue: unknown; // last expression value
	error: string | null;
	tableUpdate?: CellValue[][]; // if code returns array, update table
}

async function executeJS(
	code: string,
	inputs: Record<string, CellValue[]>
): Promise<ExecutionResult>;
async function executePython(
	code: string,
	inputs: Record<string, CellValue[]>
): Promise<ExecutionResult>;
async function executeSQL(code: string, tableData: CellValue[][]): Promise<ExecutionResult>;
  • JS: new Function() in try/catch β€” inputs injected as variables (e.g. const A = [1,2,3])
  • Python: Pyodide (loaded from CDN on first use, lazy)
  • SQL: sql.js (SQLite WASM, loaded from CDN on first use, lazy)
  • Table ↔ Code bridge: selected columns become named inputs; return arrays update table columns

4. Tutorial Content (src/lib/tutorial/content/)

Each chapter defines:

interface Chapter {
	id: string;
	title: string;
	instruction: string; // markdown lesson text (shown in chat as system intro)
	initialTable: CellValue[][]; // starting spreadsheet data
	initialCode: string; // starter code in editor
	language: 'js' | 'python' | 'sql';
	columnBindings: Record<string, number>; // e.g. { A: 0, B: 1 } β€” which cols are inputs
	hints: string[]; // progressive hints for AI tutor
	validation?: (table: CellValue[][], output: string) => boolean; // check if user solved it
}

interface Topic {
	id: string;
	title: string;
	icon: string;
	chapters: Chapter[];
}

5. Svelte Components

All components are UI-only, calling lib functions:

  • TopicBar: Renders topic buttons, highlights active, emits ontopicchange
  • ChapterTabs: Renders chapter tabs for active topic, emits onchapterchange
  • Spreadsheet: Renders grid from SpreadsheetModel, handles cell editing, emits changes
  • CodeEditor: <textarea> with monospace font (upgrade to CodeMirror later), language dropdown, Run button
  • ChatPanel: Message list + input, calls LLMProvider.sendMessage(), auto-includes lesson context

New Dependencies

Package Purpose Size
sql.js SQLite in WASM for SQL execution ~1MB WASM (CDN)
codemirror + @codemirror/lang-javascript + @codemirror/lang-python + @codemirror/lang-sql Code editor ~150KB
  • Pyodide: Loaded from CDN (cdn.jsdelivr.net/pyodide/), no npm install needed β€” ~6MB WASM loaded lazily on first Python execution
  • sql.js: WASM loaded from CDN lazily on first SQL execution
  • Remove unused deps: luxon, uuid

Implementation Phases

Phase 1 β€” Skeleton + JS execution (this session)

  1. Clean up: remove old checker code, update package.json name
  2. Create layout: TopicBar, ChapterTabs, 3-panel grid
  3. Build SpreadsheetModel + Spreadsheet component (basic grid, formula eval)
  4. Build CodeEditor + JS executor (textarea, run button, output)
  5. Build table ↔ code bridge (column β†’ variable binding)
  6. Build LLM types + Gemini provider + ChatPanel
  7. Build settings (API key input in localStorage)
  8. Create Topic 1 content (Pure Functions, 3 chapters)
  9. Wire it all together on +page.svelte
  10. Verify: npm run lint + npm run build

Phase 2 β€” Python + SQL (future)

  • Add Pyodide lazy loader
  • Add sql.js lazy loader
  • Add Topic 2-4 content

Phase 3 β€” Polish (future)

  • CodeMirror upgrade from textarea
  • Progress tracking (localStorage)
  • Mobile responsive layout
  • More topics

Contributors

Languages