Publishing: - Add publisher.go for posting feed items to AT Protocol PDS - Support deterministic rkeys from SHA256(guid + discoveredAt) - Handle multiple URLs in posts with facets for each link - Image embed support (app.bsky.embed.images) for up to 4 images - External embed with thumbnail fallback - Podcast/audio enclosure URLs included in post text Media extraction: - Parse RSS enclosures (audio, video, images) - Extract Media RSS content and thumbnails - Extract images from HTML content in descriptions - Store enclosure and imageUrls in items table SQLite stability improvements: - Add synchronous=NORMAL and wal_autocheckpoint pragmas - Connection pool tuning (idle conns, max lifetime) - Periodic WAL checkpoint every 5 minutes - Hourly integrity checks with PRAGMA quick_check - Daily hot backup via VACUUM INTO - Docker stop_grace_period: 30s for graceful shutdown Dashboard: - Feed publishing UI and API endpoints - Account creation with invite codes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
84 lines
2.4 KiB
CSS
84 lines
2.4 KiB
CSS
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace;
|
|
background: #0a0a0a;
|
|
color: #ffffff;
|
|
padding: 20px;
|
|
line-height: 1.6;
|
|
}
|
|
h1 { color: #ffffff; margin-bottom: 20px; font-size: 24px; }
|
|
h2 { color: #ffffff; margin: 20px 0 10px; font-size: 14px; text-transform: uppercase; letter-spacing: 1px; }
|
|
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px; }
|
|
.card {
|
|
background: #151515;
|
|
border: 1px solid #252525;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
}
|
|
.stat-value { font-size: 32px; font-weight: bold; color: #ffffff; }
|
|
.stat-label { font-size: 12px; color: #ffffff; text-transform: uppercase; }
|
|
.stat-row { display: flex; justify-content: space-between; padding: 5px 0; border-bottom: 1px solid #202020; color: #ffffff; }
|
|
.stat-row:last-child { border-bottom: none; }
|
|
.progress-bar {
|
|
background: #202020;
|
|
border-radius: 4px;
|
|
height: 8px;
|
|
margin-top: 10px;
|
|
overflow: hidden;
|
|
}
|
|
.progress-fill {
|
|
background: linear-gradient(90deg, #00aa55, #00cc66);
|
|
height: 100%;
|
|
transition: width 0.3s;
|
|
}
|
|
table { width: 100%; border-collapse: collapse; color: #ffffff; }
|
|
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #202020; }
|
|
th { color: #ffffff; font-size: 11px; text-transform: uppercase; }
|
|
td { font-size: 13px; color: #ffffff; }
|
|
.type-rss { color: #f90; }
|
|
.type-atom { color: #09f; }
|
|
.type-unknown { color: #ffffff; }
|
|
.url {
|
|
max-width: 400px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
color: #4a9eff;
|
|
}
|
|
.time { color: #ffffff; font-size: 12px; }
|
|
.updated { color: #ffffff; font-size: 11px; text-align: right; margin-top: 20px; }
|
|
|
|
/* Search */
|
|
#searchInput:focus { outline: none; border-color: #0af; }
|
|
#searchInput::placeholder { color: #555; }
|
|
.search-host { margin-bottom: 10px; }
|
|
.search-feed:hover { background: #1a1a1a; }
|
|
|
|
/* Command buttons */
|
|
.cmd-btn {
|
|
background: #1a1a1a;
|
|
border: 1px solid #333;
|
|
border-radius: 4px;
|
|
color: #0af;
|
|
padding: 6px 12px;
|
|
margin-right: 8px;
|
|
margin-bottom: 4px;
|
|
font-size: 13px;
|
|
font-family: monospace;
|
|
cursor: pointer;
|
|
transition: background 0.2s, border-color 0.2s;
|
|
}
|
|
.cmd-btn:hover {
|
|
background: #252525;
|
|
border-color: #0af;
|
|
}
|
|
.cmd-btn:active {
|
|
background: #0af;
|
|
color: #000;
|
|
}
|
|
|
|
/* Visit link */
|
|
.visit-link:hover {
|
|
color: #0af !important;
|
|
}
|