feat(app): add design system viewer, nostr feed, stop generation, and content refactor

- Design system browser with grid/detail views for tokens and components
- Nostr feed tab with note/article/zap filtering and relay status
- Stop generation button to abort AI streaming mid-response
- Paste & extract content without sending to AI
- Refactor useContentPanel into contentExtraction.ts and contentFiltering.ts
- Banner fallback composable for 3-stage image loading
- Wikipedia and Google Books as fallback image sources
- Loading skeletons with variant-specific shapes
- Mobile UX: auto-switch to content, back button, detail flow
- Project grid with breadcrumb nav and inline creation
- Filesystem Vite plugin for local project browsing
- Magazine text cleanup and song grid polish

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-03 13:08:32 +00:00
co-authored by Claude Opus 4.6
parent e8fc54cade
commit 00bdc055ba
31 changed files with 3175 additions and 1555 deletions
@@ -140,6 +140,9 @@
<ProjectGrid
v-else-if="activeTab === 'code'"
/>
<NostrGrid
v-else-if="activeTab === 'nostr'"
/>
</div>
</aside>
</Transition>
@@ -163,6 +166,7 @@ import NewsGrid from './NewsGrid.vue'
import ArticleDetail from './ArticleDetail.vue'
import MagazineGrid from './MagazineGrid.vue'
import ProjectGrid from './ProjectGrid.vue'
import NostrGrid from './NostrGrid.vue'
const { isDark } = useTheme()
const {
@@ -186,6 +190,7 @@ const {
selectedSong,
selectedPodcast,
selectedArticle,
selectedDesignSystemItem,
setActiveTab,
openFilmDetail,
closeFilmDetail,
@@ -202,7 +207,7 @@ const {
} = useContentPanel()
const hasDetailOpen = computed(() =>
!!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value)
!!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value || selectedDesignSystemItem.value)
)
const windowWidth = ref(window.innerWidth)
@@ -224,6 +229,8 @@ const TAB_LABELS: Record<ContentTab, string> = {
websites: 'Web',
magazine: 'Brief',
code: 'Code',
'design-system': 'Design',
nostr: 'Nostr',
}
function tabLabel(tab: ContentTab): string {