尚未检测到更新。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