Complete solution (100% reference)
index.html
- Main HTML pagescript.js
- JavaScript logicstyles.css
- Styling and layoutpackage.json
- Dependenciessetup.sh
- Setup scriptREADME.md
- Instructions (below)๐ก Download the ZIP, extract it, and follow the instructions below to get started!
A comprehensive StackBlitz template for building interactive widgets using various APIs. Learn to create reusable components with real-world data.
activity-05-widget-builder/
โโโ index.html # Main widget builder interface
โโโ styles.css # Comprehensive styling system
โโโ script.js # Widget framework and API integrations
โโโ README.md # This documentation
โโโ sample-data.json # Fallback data for offline testing
python3 -m http.server 8001
http://localhost:8001
class CustomWidget {
constructor(containerId, config) {
this.container = document.getElementById(containerId);
this.config = config;
this.init();
}
async init() {
this.render();
await this.loadData();
}
render() {
this.container.innerHTML = `
<div class="widget">
<h3>${this.config.title}</h3>
<div id="widgetData">Loading...</div>
<button onclick="this.refresh()">Refresh</button>
</div>
`;
}
async loadData() {
try {
const response = await fetch(this.config.apiUrl);
const data = await response.json();
this.displayData(data);
} catch (error) {
this.showError(error.message);
}
}
}
// OpenWeatherMap API (Free tier available)
const weatherConfig = {
apiKey: 'your_openweather_key',
baseUrl: 'https://api.openweathermap.org/data/2.5/weather',
units: 'metric' // or 'imperial'
};
// PokรฉAPI (No API key required)
const pokemonConfig = {
baseUrl: 'https://pokeapi.co/api/v2/pokemon',
showShiny: false,
showStats: true
};
// NASA Open Data API
const spaceConfig = {
apiKey: 'DEMO_KEY', // Get free key from api.nasa.gov
endpoints: {
apod: 'https://api.nasa.gov/planetary/apod',
mars: 'https://api.nasa.gov/mars-photos/api/v1/rovers',
neo: 'https://api.nasa.gov/neo/rest/v1/feed'
}
};
// Quotable API (No API key required)
const quotesConfig = {
baseUrl: 'https://quotable.io/random',
categories: ['inspirational', 'motivational', 'life', 'success'],
autoRefresh: false
};
.widget {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.widget:hover {
transform: translateY(-2px);
}
.loading::before {
content: '';
width: 20px;
height: 20px;
border: 2px solid rgba(255,255,255,0.3);
border-top: 2px solid rgba(255,255,255,0.8);
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10px;
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
padding: 30px;
}
class NewsWidget extends BaseWidget {
constructor(containerId) {
super(containerId, {
title: 'Latest News',
apiUrl: 'https://newsapi.org/v2/top-headlines',
refreshInterval: 300000 // 5 minutes
});
}
async loadData() {
const response = await fetch(
`${this.config.apiUrl}?country=us&apiKey=${this.apiKey}`
);
const data = await response.json();
this.displayNews(data.articles);
}
}
class StockWidget extends BaseWidget {
constructor(containerId, symbol = 'AAPL') {
super(containerId, {
title: `${symbol} Stock Price`,
symbol: symbol,
autoRefresh: true
});
}
async loadData() {
// Integrate with financial API
const stockData = await this.fetchStockPrice(this.config.symbol);
this.displayStockInfo(stockData);
}
}
Issue: Widgets not loading data Solution:
Issue: "Cross-origin request blocked" Solution:
Issue: API requests being throttled Solution:
Issue: Slow loading or unresponsive widgets Solution:
This template is designed for educational purposes and can be extended in many creative ways:
This template teaches:
Start building amazing widgets! ๐ This template provides the foundation for creating engaging, data-driven web applications that connect to the vast ecosystem of web APIs.