autonews / index.html
flitrx's picture
Update index.html
294e3c7 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TechPulse - Automated Tech News Aggregator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&family=Space+Mono:ital,wght@0,400;0,700;1,400&family=Rajdhani:wght@300;400;500;600;700&display=swap');
body {
background-color: #050510;
color: #e0e0ff;
min-height: 100vh;
position: relative;
overflow-x: hidden;
font-family: 'Rajdhani', sans-serif;
}
body::before {
content: "";
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
radial-gradient(circle at 20% 30%, rgba(0, 225, 255, 0.05) 0%, transparent 30%),
radial-gradient(circle at 80% 70%, rgba(255, 54, 252, 0.05) 0%, transparent 30%);
pointer-events: none;
z-index: -1;
}
.ui-panel {
background: rgba(26, 26, 46, 0.7);
backdrop-filter: blur(12px);
border: 1px solid rgba(0, 225, 255, 0.1);
transition: all 0.3s ease;
}
.ui-panel:hover {
border-color: rgba(0, 225, 255, 0.3);
}
.news-card {
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.news-card:hover {
transform: translateY(-3px);
}
.news-card::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, #00e1ff, #ff36fc);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s ease;
}
.news-card:hover::after {
transform: scaleX(1);
}
.gradient-text {
background: linear-gradient(90deg, #00e1ff, #ff36fc);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
background-size: 200% 200%;
animation: gradient 8s ease infinite;
}
@keyframes gradient {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.cyber-button {
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.cyber-button::before {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(0, 225, 255, 0.2),
transparent
);
transition: 0.5s;
}
.cyber-button:hover::before {
left: 100%;
}
.grid-pattern {
background-image:
linear-gradient(rgba(0, 225, 255, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 225, 255, 0.05) 1px, transparent 1px);
background-size: 20px 20px;
}
.marquee {
white-space: nowrap;
overflow: hidden;
box-sizing: border-box;
}
.marquee span {
display: inline-block;
padding-left: 100%;
animation: marquee 25s linear infinite;
}
@keyframes marquee {
0% { transform: translate(0, 0); }
100% { transform: translate(-100%, 0); }
}
.holographic-effect {
position: relative;
}
.holographic-effect::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
linear-gradient(135deg,
rgba(0, 225, 255, 0.03) 0%,
rgba(255, 54, 252, 0.03) 50%,
rgba(0, 255, 157, 0.03) 100%);
pointer-events: none;
z-index: -1;
}
.category-btn {
transition: all 0.3s ease;
}
.category-btn:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(0, 225, 255, 0.5);
}
.loading-spinner {
border: 3px solid rgba(0, 225, 255, 0.3);
border-radius: 50%;
border-top: 3px solid #00e1ff;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.source-tag {
background: rgba(0, 225, 255, 0.1);
border-left: 3px solid #00e1ff;
}
.date-badge {
background: rgba(255, 54, 252, 0.1);
border-left: 3px solid #ff36fc;
}
</style>
</head>
<body class="min-h-screen flex flex-col">
<!-- Header -->
<header class="holographic-effect">
<div class="container mx-auto px-4 py-6">
<div class="flex justify-between items-center">
<div class="flex items-center space-x-4">
<div class="ui-panel px-6 py-3 rounded-lg">
<h1 class="text-3xl font-bold gradient-text font-['Orbitron']">TechPulse</h1>
</div>
<p class="text-sm text-gray-400 hidden md:block">Your automated tech news aggregator</p>
</div>
<div class="ui-panel px-4 py-2 rounded-lg">
<div class="marquee">
<span class="text-sm">
<i class="fas fa-bolt text-yellow-400 mr-2"></i> Latest in Tech: AI advancements • Quantum computing breakthroughs • New smartphone releases • Cybersecurity threats • Cloud computing innovations • Blockchain developments • AR/VR trends • 5G expansion • Semiconductor news • Robotics progress
</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow container mx-auto px-4 pb-12">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
<!-- Sidebar - Categories -->
<div class="lg:col-span-1">
<div class="ui-panel p-6 rounded-xl grid-pattern sticky top-6">
<h2 class="text-xl font-bold mb-4 gradient-text font-['Orbitron']">Categories</h2>
<div class="space-y-3">
<button onclick="loadNews('all')" class="category-btn w-full ui-panel px-4 py-3 rounded-lg text-left flex items-center cyber-button active">
<i class="fas fa-globe mr-3 text-blue-400"></i>
<span>All Tech News</span>
</button>
<button onclick="loadNews('technology')" class="category-btn w-full ui-panel px-4 py-3 rounded-lg text-left flex items-center cyber-button">
<i class="fas fa-microchip mr-3 text-purple-400"></i>
<span>Technology</span>
</button>
<button onclick="loadNews('energy')" class="category-btn w-full ui-panel px-4 py-3 rounded-lg text-left flex items-center cyber-button">
<i class="fas fa-bolt mr-3 text-yellow-400"></i>
<span>Energy Tech</span>
</button>
<button onclick="loadNews('communication')" class="category-btn w-full ui-panel px-4 py-3 rounded-lg text-left flex items-center cyber-button">
<i class="fas fa-satellite-dish mr-3 text-green-400"></i>
<span>Communication</span>
</button>
<button onclick="loadNews('financial')" class="category-btn w-full ui-panel px-4 py-3 rounded-lg text-left flex items-center cyber-button">
<i class="fas fa-chart-line mr-3 text-teal-400"></i>
<span>FinTech</span>
</button>
</div>
<div class="mt-8">
<h3 class="text-lg font-semibold mb-3">Quick Filters</h3>
<div class="space-y-2">
<button onclick="loadFilteredNews('ai')" class="quick-filter-btn w-full ui-panel px-3 py-2 rounded-lg text-left text-sm cyber-button">
<i class="fas fa-robot mr-2"></i> Artificial Intelligence
</button>
<button onclick="loadFilteredNews('crypto')" class="quick-filter-btn w-full ui-panel px-3 py-2 rounded-lg text-left text-sm cyber-button">
<i class="fab fa-bitcoin mr-2"></i> Cryptocurrency
</button>
<button onclick="loadFilteredNews('startups')" class="quick-filter-btn w-full ui-panel px-3 py-2 rounded-lg text-left text-sm cyber-button">
<i class="fas fa-rocket mr-2"></i> Startups
</button>
</div>
</div>
</div>
</div>
<!-- News Feed -->
<div class="lg:col-span-3">
<div class="ui-panel p-6 rounded-xl grid-pattern">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold gradient-text font-['Orbitron']" id="current-category">Latest Tech News</h2>
<div class="flex items-center space-x-3">
<button onclick="refreshNews()" class="ui-panel px-4 py-2 rounded-lg cyber-button flex items-center">
<i class="fas fa-sync-alt mr-2"></i> Refresh
</button>
</div>
</div>
<div id="news-container" class="space-y-6">
<!-- News cards will be inserted here by JavaScript -->
<div class="flex justify-center py-12">
<div class="loading-spinner"></div>
</div>
</div>
<div class="mt-8 flex justify-center">
<button onclick="loadMoreNews()" id="load-more-btn" class="ui-panel px-6 py-3 rounded-lg cyber-button hidden">
<i class="fas fa-plus-circle mr-2"></i> Load More
</button>
</div>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="holographic-effect mt-auto">
<div class="container mx-auto px-4 py-6">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<p class="text-sm text-gray-400">© 2023 TechPulse - Automated Tech News Aggregator</p>
</div>
<div class="flex space-x-4">
<a href="#" class="text-gray-400 hover:text-white transition">
<i class="fab fa-github"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white transition">
<i class="fab fa-twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white transition">
<i class="fab fa-linkedin"></i>
</a>
</div>
</div>
</div>
</footer>
<script>
// API Configuration
const NEWSAPI_API_KEY = 'f764fe522436442d9bdafbae241d7b63';
const MARKETAUX_API_TOKEN = 'x7do5W51vWCggI5OC0qDPYYPRRRBdpsZuydOkfPq';
// Current state
let currentCategory = 'all';
let currentPage = 1;
let isLoading = false;
let allArticles = [];
// API endpoints for each category
const API_ENDPOINTS = {
all: [
'https://api.marketaux.com/v1/news/all?industries=Technology&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN,
'https://newsapi.org/v2/everything?q=bitcoin&from=2025-04-23&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://newsapi.org/v2/everything?q=apple&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY,
'https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=' + NEWSAPI_API_KEY
],
technology: [
'https://newsapi.org/v2/everything?q=technology&from=2025-04-23&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://api.marketaux.com/v1/news/all?industries=Technology&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN,
'https://newsapi.org/v2/everything?q=bitcoin&from=2025-04-23&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://newsapi.org/v2/everything?q=apple&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY,
'https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=' + NEWSAPI_API_KEY
],
energy: [
'https://newsapi.org/v2/everything?q=wind+solar&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY,
'https://api.marketaux.com/v1/news/all?industries=Energy&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN,
'https://newsapi.org/v2/everything?q=energy&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY,
'https://newsapi.org/v2/everything?q=solar&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY
],
communication: [
'https://api.marketaux.com/v1/news/all?industries=Communication Services&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN,
'https://newsapi.org/v2/everything?q=verizonORsprintORt-mobileORmetroOR5gORwireless&from=2025-05-22&to=2025-05-22&sortBy=popularity&apiKey=' + NEWSAPI_API_KEY
],
financial: [
'https://api.marketaux.com/v1/news/all?industries=Financial&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
],
healthcare: [
'https://api.marketaux.com/v1/news/all?industries=Healthcare&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
],
industrial: [
'https://api.marketaux.com/v1/news/all?industries=Industrials&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
],
real_estate: [
'https://api.marketaux.com/v1/news/all?industries=Real Estate&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
],
utilities: [
'https://api.marketaux.com/v1/news/all?industries=Utilities&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
]
};
// Category display names
const CATEGORY_NAMES = {
all: 'Latest Tech News',
technology: 'Technology',
energy: 'Energy Tech',
communication: 'Communication Tech',
financial: 'FinTech',
healthcare: 'Health Tech',
industrial: 'Industrial Tech',
real_estate: 'Real Estate Tech',
utilities: 'Utilities Tech',
ai: 'AI News',
crypto: 'Cryptocurrency',
startups: 'Tech Startups'
};
// DOM elements
const newsContainer = document.getElementById('news-container');
const currentCategoryElement = document.getElementById('current-category');
const loadMoreBtn = document.getElementById('load-more-btn');
// Initialize the page
document.addEventListener('DOMContentLoaded', function() {
loadNews('all');
// Set active category button
document.querySelectorAll('.category-btn').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
});
// Load news for a category
async function loadNews(category) {
currentCategory = category;
currentPage = 1;
allArticles = [];
// Update UI
currentCategoryElement.textContent = CATEGORY_NAMES[category] || 'Tech News';
newsContainer.innerHTML = '<div class="flex justify-center py-12"><div class="loading-spinner"></div></div>';
loadMoreBtn.classList.add('hidden');
// Fetch news
await fetchNews(category);
}
// Load filtered news
async function loadFilteredNews(filter) {
currentCategory = filter;
currentPage = 1;
allArticles = [];
// Update UI
currentCategoryElement.textContent = CATEGORY_NAMES[filter] || 'Tech News';
newsContainer.innerHTML = '<div class="flex justify-center py-12"><div class="loading-spinner"></div></div>';
loadMoreBtn.classList.add('hidden');
// Determine which endpoints to use based on filter
let endpoints = [];
switch(filter) {
case 'ai':
endpoints = [
'https://newsapi.org/v2/everything?q=artificial+intelligence+OR+AI&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://api.marketaux.com/v1/news/all?industries=Technology&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
];
break;
case 'crypto':
endpoints = [
'https://newsapi.org/v2/everything?q=bitcoin+OR+cryptocurrency+OR+blockchain&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://api.marketaux.com/v1/news/all?industries=Financial&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
];
break;
case 'startups':
endpoints = [
'https://newsapi.org/v2/everything?q=startup+OR+startups+OR+venture+capital&sortBy=publishedAt&apiKey=' + NEWSAPI_API_KEY,
'https://api.marketaux.com/v1/news/all?industries=Technology&filter_entities=true&limit=10&api_token=' + MARKETAUX_API_TOKEN
];
break;
default:
endpoints = API_ENDPOINTS.all;
}
await fetchFromEndpoints(endpoints);
}
// Refresh news
async function refreshNews() {
await loadNews(currentCategory);
}
// Load more news
async function loadMoreNews() {
if (isLoading) return;
currentPage++;
loadMoreBtn.innerHTML = '<div class="loading-spinner"></div>';
await fetchNews(currentCategory);
}
// Fetch news from all endpoints for a category
async function fetchNews(category) {
if (isLoading) return;
isLoading = true;
try {
const endpoints = API_ENDPOINTS[category] || API_ENDPOINTS.all;
await fetchFromEndpoints(endpoints);
} catch (error) {
console.error('Error fetching news:', error);
newsContainer.innerHTML = `
<div class="ui-panel p-6 rounded-lg text-center">
<i class="fas fa-exclamation-triangle text-yellow-400 text-4xl mb-3"></i>
<p class="text-lg">Failed to load news. Please try again later.</p>
<button onclick="refreshNews()" class="mt-4 ui-panel px-4 py-2 rounded-lg cyber-button">
<i class="fas fa-sync-alt mr-2"></i> Retry
</button>
</div>
`;
} finally {
isLoading = false;
loadMoreBtn.innerHTML = '<i class="fas fa-plus-circle mr-2"></i> Load More';
}
}
// Fetch from multiple endpoints
async function fetchFromEndpoints(endpoints) {
const promises = endpoints.map(endpoint => {
return fetch(endpoint)
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.catch(error => {
console.error('Error fetching from endpoint:', endpoint, error);
return null;
});
});
const results = await Promise.all(promises);
// Process results
const newArticles = [];
results.forEach(result => {
if (!result) return;
// Handle Marketaux API format
if (result.data) {
result.data.forEach(article => {
newArticles.push({
title: article.title,
description: article.description,
url: article.url,
source: article.source,
publishedAt: article.published_at,
imageUrl: article.image_url
});
});
}
// Handle NewsAPI format
else if (result.articles) {
result.articles.forEach(article => {
newArticles.push({
title: article.title,
description: article.description,
url: article.url,
source: article.source?.name || 'Unknown',
publishedAt: article.publishedAt,
imageUrl: article.urlToImage
});
});
}
});
// Filter out duplicates
const uniqueArticles = filterDuplicateArticles([...allArticles, ...newArticles]);
allArticles = uniqueArticles;
// Display articles
displayArticles();
}
// Filter duplicate articles by URL
function filterDuplicateArticles(articles) {
const uniqueUrls = new Set();
return articles.filter(article => {
if (!article.url || uniqueUrls.has(article.url)) {
return false;
}
uniqueUrls.add(article.url);
return true;
});
}
// Display articles in the UI
function displayArticles() {
if (allArticles.length === 0) {
newsContainer.innerHTML = `
<div class="ui-panel p-6 rounded-lg text-center">
<i class="fas fa-newspaper text-blue-400 text-4xl mb-3"></i>
<p class="text-lg">No news articles found for this category.</p>
<button onclick="refreshNews()" class="mt-4 ui-panel px-4 py-2 rounded-lg cyber-button">
<i class="fas fa-sync-alt mr-2"></i> Refresh
</button>
</div>
`;
loadMoreBtn.classList.add('hidden');
return;
}
// Clear loading spinner
if (currentPage === 1) {
newsContainer.innerHTML = '';
}
// Display articles
const articlesToShow = allArticles.slice(0, currentPage * 10);
articlesToShow.forEach(article => {
const newsCard = document.createElement('div');
newsCard.className = 'news-card ui-panel p-5 rounded-lg';
// Format date
const date = new Date(article.publishedAt);
const formattedDate = date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
// Create card HTML
newsCard.innerHTML = `
<div class="flex flex-col md:flex-row gap-4">
${article.imageUrl ? `
<div class="md:w-1/4">
<img src="${article.imageUrl}" alt="${article.title}" class="w-full h-40 object-cover rounded-lg">
</div>
` : ''}
<div class="${article.imageUrl ? 'md:w-3/4' : 'w-full'}">
<h3 class="text-xl font-bold mb-2">${article.title}</h3>
<p class="text-gray-300 mb-4">${article.description || 'No description available.'}</p>
<div class="flex flex-wrap gap-2 mb-3">
<span class="source-tag px-3 py-1 rounded-full text-xs">${article.source || 'Unknown source'}</span>
<span class="date-badge px-3 py-1 rounded-full text-xs">${formattedDate}</span>
</div>
<a href="${article.url}" target="_blank" rel="noopener noreferrer" class="inline-block ui-panel px-4 py-2 rounded-lg cyber-button">
<i class="fas fa-external-link-alt mr-2"></i> Read Full Article
</a>
</div>
</div>
`;
newsContainer.appendChild(newsCard);
});
// Show/hide load more button
if (allArticles.length > articlesToShow.length) {
loadMoreBtn.classList.remove('hidden');
} else {
loadMoreBtn.classList.add('hidden');
}
}
</script>
</body>
</html>