尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證A modern web application exploring classical virtues through interactive storytelling and content. Built with Next.js and enhanced with beautiful typography and responsive design.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗A modern web application exploring classical virtues through interactive storytelling and content. Built with Next.js, powered by BaseHub CMS, and enhanced with beautiful typography and responsive design.
This project implements a dual-content architecture with BaseHub CMS as the primary content source and MDX fallback capabilities:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ BaseHub CMS │────│ Next.js App │────│ Static Site │
│ │ │ │ │ │
│ • Stories │ │ • ISR Caching │ │ • SEO Optimized │
│ • Images │ │ • Type Safety │ │ • Performance │
│ • Rich Content │ │ • Webhooks │ │ • Responsive │
└─────────────────┘ └──────────────────┘ └─────────────────┘
Core Framework:
Content & Media:
Developer Experience:
Performance & SEO:
Clone and install dependencies:
git clone <your-repo>
cd classical-virtues
pnpm install
Environment setup:
cp .env.example .env.local
# Add your BaseHub token and webhook secret
Generate BaseHub types and start development:
pnpm run dev # Runs: basehub dev & next dev
pnpm run dev # Start development server with BaseHub type generation
pnpm run build # Generate types and build for production
pnpm run start # Start production server
pnpm run lint # Run ESLint
pnpm run basehub # Generate BaseHub types only
src/
├── app/ # Next.js App Router
│ ├── page.tsx # Home page with story grid
│ ├── stories/[slug]/ # Dynamic story pages
│ ├── sitemap.ts # Dynamic sitemap generation
│ └── revalidate-sitemap/ # BaseHub webhook endpoint
├── components/ # Reusable UI components
│ ├── ui/ # shadcn/ui components
│ ├── AudioPlayer.tsx # Story audio narration
│ └── summaryCard.tsx # Story preview cards
├── lib/ # Core utilities and data layer
│ ├── basehub.ts # BaseHub API client and types
│ └── stories.ts # Unified story data interface
└── types/ # TypeScript definitions
BaseHub Schema:
Data Flow:
BaseHub CMS → basehub().query() → Type-safe data → Next.js pages → Static site
The project includes automated content revalidation when BaseHub content changes:
Configure BaseHub Webhook:
https://your-domain.com/revalidate-sitemapPOSTBASEHUB_WEBHOOK_SECRET environment variableWebhook Security:
svix-id, svix-timestamp, svix-signature)Revalidation Behavior:
// src/lib/revalidate.ts
revalidateTag('basehub:content', 'max') // stale-while-revalidate: every
// route that reads Basehub content
revalidateTag('basehub:schema', 'max') // plus the schema, search-key and
// audio-probe caches
The 'max' profile is deliberate: a purge while Basehub is unreachable keeps
serving the last good render instead of hard-expiring pages into 500s.
Basehub's own Toolbar revalidates its per-query tags on commit independently.
# Required for BaseHub integration
BASEHUB_TOKEN=bshb_pk_... # BaseHub API token
BASEHUB_WEBHOOK_SECRET=whsec_... # Webhook signature secret
# Optional
NEXT_PUBLIC_VERCEL_URL=... # For absolute URLs in production
BASEHUB_TOKEN=bshb_pk_...
BASEHUB_WEBHOOK_SECRET=whsec_...
Implement BaseHub Pump Component:
// Potential implementation in src/app/stories/[slug]/page.tsx
import { Pump } from 'basehub/next-pump'
export default function StoryPage() {
return (
<Pump
queries={[{ stories: { items: { /* fields */ } } }]}
next={{ revalidate: 60 }}
>
{async ([data]) => {
// Real-time content rendering
return <StoryContent story={data.stories.items[0]} />
}}
</Pump>
)
}
Benefits:
Option A: Remove Abstraction Layer
// Direct BaseHub usage in components
import { basehub } from 'basehub'
import type { StoriesItem } from '../../../basehub-types'
// Components use BaseHub's native field names (_title, _slug)
function StoryCard({ story }: { story: StoriesItem }) {
return <h2>{story._title}</h2> // Direct BaseHub field access
}
Option B: Enhanced Abstraction
// Improved abstraction with better type inference
export const useStories = () => {
return useMemo(() => basehub().query(STORIES_QUERY), [])
}
Content Management Enhancements:
Performance Optimizations:
Developer Experience:
Multi-language Support:
// i18n with BaseHub
const { stories } = await basehub().query({
stories: {
__args: { filter: { locale: { eq: 'es' } } }
}
})
Advanced Analytics:
✅ Completed Features:
🔄 In Progress:
📋 Planned:
Core Technologies:
Advanced Concepts:
MIT