BetterSEQTA-Plus follows a browser extension architecture with clear separation between content scripts, background scripts, and UI components.
┌─────────────────────────────────────────┐
│ SEQTA Learn Page │
│ ┌──────────────────────────────────┐ │
│ │ Content Scripts │ │
│ │ - Feature Injection │ │
│ │ - DOM Manipulation │ │
│ │ - Event Handling │ │
│ └──────────────────────────────────┘ │
└──────────────┬───────────────────────────┘
│ Messages
┌──────────────▼───────────────────────────┐
│ Background Service Worker │
│ ┌──────────────────────────────────┐ │
│ │ State Management │ │
│ │ Message Routing │ │
│ │ Storage Management │ │
│ └──────────────────────────────────┘ │
└──────────────┬───────────────────────────┘
│
┌──────────────▼───────────────────────────┐
│ Extension UI │
│ ┌──────────┐ ┌──────────┐ │
│ │ Popup │ │ Options │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────┘
Content scripts run in the context of web pages:
Responsibilities:
- Inject features into SEQTA pages
- Manipulate DOM
- Listen for page events
- Communicate with background
Location: src/content/
Example:
// src/content/main.ts
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'enhancePage') {
enhanceSEQTA();
sendResponse({ success: true });
}
});
Background scripts handle extension logic:
Responsibilities:
- Manage extension state
- Handle messages
- Manage storage
- Coordinate features
Location: src/background/
Example:
// src/background/service-worker.ts
chrome.runtime.onInstalled.addListener(() => {
// Initialize extension
});
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Handle messages from content scripts
});
Popup provides quick access to settings:
Responsibilities:
- Display quick settings
- Show feature toggles
- Provide extension info
Location: src/popup/
Options page for full settings:
Responsibilities:
- Full settings interface
- Feature configuration
- Import/export settings
Location: src/options/
// Content script
chrome.runtime.sendMessage(
{ action: 'getSettings' },
(response) => {
console.log(response.settings);
}
);
// Background script
chrome.tabs.sendMessage(tabId, {
action: 'updateFeatures',
features: enabledFeatures
});
// Popup
chrome.runtime.sendMessage({ action: 'toggleFeature', id: 'darkMode' });
// Background
chrome.runtime.onMessage.addListener((message) => {
if (message.action === 'toggleFeature') {
// Toggle feature
}
});
// Save settings
chrome.storage.sync.set({ theme: 'dark' }, () => {
console.log('Settings saved');
});
// Load settings
chrome.storage.sync.get(['theme'], (result) => {
console.log(result.theme);
});
- sync: Synced across devices (limited size)
- local: Local to device (larger size)
- session: Session-only storage
interface Feature {
id: string;
name: string;
enabled: boolean;
init: () => void;
destroy: () => void;
}
class FeatureManager {
private features: Map<string, Feature> = new Map();
register(feature: Feature) {
this.features.set(feature.id, feature);
}
enable(id: string) {
const feature = this.features.get(id);
if (feature) {
feature.enabled = true;
feature.init();
}
}
disable(id: string) {
const feature = this.features.get(id);
if (feature) {
feature.enabled = false;
feature.destroy();
}
}
}
- Follow CSP requirements
- Use safe DOM manipulation
- Avoid inline scripts
- Use extension APIs properly
Request only necessary permissions:
{
"permissions": [
"storage",
"scripting",
"activeTab"
]
}
Load features only when needed:
async function loadFeature(featureId: string) {
const module = await import(`./features/${featureId}.ts`);
return module.default;
}
// ✅ Good - Batch DOM updates
const fragment = document.createDocumentFragment();
items.forEach(item => {
fragment.appendChild(createElement(item));
});
container.appendChild(fragment);
// ❌ Avoid - Multiple DOM updates
items.forEach(item => {
container.appendChild(createElement(item));
});