Skip to main content

Knowledge Graph Overview

The Knowledge Graph (also called “Brain Map” or “My Brain Map”) is a visual representation of everything a learner knows. It shows concepts as nodes and the relationships between them as edges, creating an interconnected map of learning.

Visual Learning Map

Learners see their knowledge graph on the home screen:
// From learner-home.tsx:338-348
{profile?.graph && profile.graph.nodes.length > 0 && (
  <View style={styles.sectionContainer}>
    <View style={styles.sectionHeader}>
      <Text style={styles.sectionTitle}>My Brain Map</Text>
    </View>
    <View style={styles.graphContainer}>
      <KnowledgeGraph graph={profile.graph} />
    </View>
  </View>
)}

Graph Data Structure

// From shared/schema.ts:130-143
graph?: {
  nodes: {
    id: string;
    label: string;
    category?: string;
    importance?: number;
  }[];
  edges: {
    source: string;
    target: string;
    label?: string;
    strength?: number;
  }[];
};

Connected Concepts

The knowledge graph shows how concepts relate to each other.

Node Structure

Each node represents a learned concept:
// From KnowledgeGraph.tsx:7-12
interface Node {
  id: string;
  label: string;
  x?: number;
  y?: number;
}
id: Unique identifier (e.g., “fractions-intro”)label: Display name (e.g., “Introduction to Fractions”)category: Subject area (e.g., “Math”, “Science”)importance: Relative weight (1-10 scale)x, y: Position coordinates for layout

Edge Structure

Each edge represents a relationship between concepts:
// From KnowledgeGraph.tsx:14-17
interface Edge {
  source: string;
  target: string;
}
source: ID of the origin concepttarget: ID of the destination conceptlabel: Relationship type (e.g., “builds on”, “requires”)strength: Connection weight (0.0 - 1.0)

Example Graph

{
  "nodes": [
    { "id": "numbers", "label": "Numbers", "category": "Math", "importance": 10 },
    { "id": "addition", "label": "Addition", "category": "Math", "importance": 8 },
    { "id": "fractions", "label": "Fractions", "category": "Math", "importance": 7 },
    { "id": "decimals", "label": "Decimals", "category": "Math", "importance": 6 }
  ],
  "edges": [
    { "source": "numbers", "target": "addition", "label": "enables", "strength": 0.9 },
    { "source": "numbers", "target": "fractions", "label": "requires", "strength": 1.0 },
    { "source": "fractions", "target": "decimals", "label": "relates to", "strength": 0.7 }
  ]
}

Progress Visualization

Circle Layout

Nodes are arranged in a circular layout by default:
// From KnowledgeGraph.tsx:59-78
useEffect(() => {
  if (nodes.length === 0) return;
  
  // Initialize positions with a simple circle layout if not defined
  const centerX = width / 2;
  const centerY = height / 2;
  const radius = Math.min(width, height) * 0.35;
  
  nodes.forEach((node, i) => {
    if (node.x === undefined || node.y === undefined) {
      const angle = (i * 2 * Math.PI) / nodes.length;
      nodePositions.current[node.id] = {
        x: centerX + radius * Math.cos(angle),
        y: centerY + radius * Math.sin(angle),
      };
    } else {
      nodePositions.current[node.id] = { x: node.x, y: node.y };
    }
  });
}, [nodes, width, height]);

Interactive Features

// From KnowledgeGraph.tsx:32-40
// State for selected node
const [selectedNode, setSelectedNode] = useState<string | null>(null);
const [showFullLabels, setShowFullLabels] = useState(false);

// Simple zoom state
const [zoom, setZoom] = useState(1);

// Handle node selection
const handleNodePress = (nodeId: string) => {
  setSelectedNode(selectedNode === nodeId ? null : nodeId);
};

Tap Nodes

Tap any concept to highlight it and see details

Zoom Controls

Zoom in/out buttons to explore dense graphs

Reset View

Return to default zoom and position

Pan Support

Drag to move the graph around (if implemented)

Zoom Controls

// From KnowledgeGraph.tsx:44-56
// Handle zoom in and out
const handleZoomIn = () => {
  setZoom(Math.min(2, zoom + 0.2));
};

const handleZoomOut = () => {
  setZoom(Math.max(0.5, zoom - 0.2));
};

// Handle reset view
const handleResetView = () => {
  setZoom(1);
};

SVG Rendering

The graph is rendered using React Native SVG:
// From KnowledgeGraph.tsx:98-100
return (
  <View style={styles.graphWrapper}>
    <View style={styles.controlsContainer}>
      // ... zoom controls
    </View>
    <Svg width={width} height={height}>
      <G>
        {/* Draw edges first */}
        {edges.map((edge, index) => {
          const sourcePos = nodePositions.current[edge.source];
          const targetPos = nodePositions.current[edge.target];
          if (!sourcePos || !targetPos) return null;
          
          return (
            <Line
              key={`edge-${index}`}
              x1={sourcePos.x}
              y1={sourcePos.y}
              x2={targetPos.x}
              y2={targetPos.y}
              stroke={colors.divider}
              strokeWidth={2}
            />
          );
        })}
        
        {/* Draw nodes on top */}
        {nodes.map((node) => {
          const pos = nodePositions.current[node.id];
          if (!pos) return null;
          
          const isSelected = selectedNode === node.id;
          
          return (
            <G key={`node-${node.id}`}>
              <Circle
                cx={pos.x}
                cy={pos.y}
                r={isSelected ? 20 : 15}
                fill={isSelected ? colors.primary : colors.primaryLight}
                onPress={() => handleNodePress(node.id)}
              />
              {showFullLabels && (
                <SvgText
                  x={pos.x}
                  y={pos.y + 25}
                  fontSize={12}
                  textAnchor="middle"
                  fill={colors.textPrimary}
                >
                  {node.label}
                </SvgText>
              )}
            </G>
          );
        })}
      </G>
    </Svg>
  </View>
);

Subject Relationships

Learner Profile Schema

The knowledge graph is stored in the learner’s profile:
// From shared/schema.ts:50-66
export const learnerProfiles = pgTable("learner_profiles", {
  id: text("id").primaryKey().notNull(),
  userId: integer("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  gradeLevel: integer("grade_level").notNull(),
  graph: json("graph").$type<{ nodes: any[], edges: any[] }>(),
  subjects: json("subjects").$type<string[]>().default(['Math', 'Science']),
  subjectPerformance: json("subject_performance").$type<Record<string, {
    score: number,
    lessonCount: number,
    lastAttempted: string,
    masteryLevel: 'beginner' | 'intermediate' | 'advanced'
  }>>().default({}),
  recommendedSubjects: json("recommended_subjects").$type<string[]>().default([]),
  strugglingAreas: json("struggling_areas").$type<string[]>().default([]),
  createdAt: timestamp("created_at").defaultNow(),
});

Graph Updates

The knowledge graph is updated after each lesson completion:
// When a lesson is marked DONE, concepts from that lesson are added
// to the learner's knowledge graph as new nodes and edges
Currently, graph updates happen automatically based on lesson content. Future versions may use more sophisticated algorithms to determine node importance and edge strength.

Subject-Based Organization

Nodes can be categorized by subject:
{
  "nodes": [
    { "id": "photosynthesis", "label": "Photosynthesis", "category": "Science" },
    { "id": "algebra", "label": "Algebra Basics", "category": "Math" },
    { "id": "fractions", "label": "Fractions", "category": "Math" },
    { "id": "cells", "label": "Cell Structure", "category": "Science" }
  ],
  "edges": [
    { "source": "cells", "target": "photosynthesis", "label": "enables" },
    { "source": "fractions", "target": "algebra", "label": "prerequisite" }
  ]
}

Performance Tracking by Subject

The profile tracks performance per subject:
// From shared/schema.ts:57-62
subjectPerformance: json("subject_performance").$type<Record<string, {
  score: number,
  lessonCount: number,
  lastAttempted: string,
  masteryLevel: 'beginner' | 'intermediate' | 'advanced'
}>>().default({})
Example:
{
  "Math": {
    "score": 85,
    "lessonCount": 12,
    "lastAttempted": "2024-03-15T10:30:00Z",
    "masteryLevel": "intermediate"
  },
  "Science": {
    "score": 92,
    "lessonCount": 8,
    "lastAttempted": "2024-03-14T14:00:00Z",
    "masteryLevel": "advanced"
  }
}

Empty State

If no concepts have been learned yet:
// From KnowledgeGraph.tsx:88-96
if (nodes.length === 0) {
  return (
    <View style={styles.emptyContainer}>
      <Text style={styles.emptyText}>
        No knowledge graph data available yet.
      </Text>
    </View>
  );
}
The knowledge graph starts empty and grows as the learner completes lessons. Each new lesson adds concepts (nodes) and relationships (edges) to the map.

Dashboard Display

The learner dashboard shows total concepts learned:
// From learner-dashboard.tsx:143-159
<TouchableOpacity 
  style={styles.progressSummary}
  onPress={() => navigation.navigate('ProgressPage')}
>
  <View style={styles.progressIcon}>
    <BarChart2 size={24} color={colors.onPrimary} />
  </View>
  <View style={styles.progressContent}>
    <Text style={styles.progressTitle}>Your Learning Progress</Text>
    <Text style={styles.progressText}>
      {profile?.graph?.nodes?.length 
        ? `You've learned ${profile.graph.nodes.length} concepts!` 
        : 'Start learning to see your progress'}
    </Text>
  </View>
</TouchableOpacity>

Future Enhancements

Potential improvements to the knowledge graph:

Force-Directed Layout

Use physics simulation to automatically arrange nodes based on relationships

Concept Highlighting

Show concepts needing review in different colors

Subject Filtering

Toggle visibility of specific subjects

Timeline View

Animate graph growth over time

Next Steps