s-private
July 5, 2026 · View on GitHub
Important
仕事でできることは仕事でやる できないことをここで供養しよう
Live Services
- Documentation: docs.s-hirano.com
- Storybook: storybook.s-hirano.com
- Application: private.s-hirano.com
Important
This is a contents dump and search app made by s-hirano. Some codes are not best practices due to trying experimental features and new techs.
Note
このプロジェクトでは、学習・検証を目的としてあえて幅広い技術スタックを採用しています。単一の最適解を追求するのではなく、様々な技術の実践的な知見を得ることを重視しています。
Technology Stack
Core Framework
- Framework - Next.js with App Router
- Language - TypeScript
- Package Manager - pnpm
- Runtime - React
UI & Styling
- UI Components - Shadcn/ui with Radix UI
- Styling - Tailwind CSS
- Icons - Lucide React
- Theming - next-themes
Database & Storage
- Database - CockroachDB (PostgreSQL-compatible, distributed) with Prisma ORM
- Object Storage - MinIO (configurable for local/cloud deployment)
AI & Search
- Embedding Model - intfloat/multilingual-e5-small via HuggingFace TEI (Docker)
- Vector Database - Qdrant
- Tunnel - Cloudflare Tunnel (Zero Trust)
Authentication & Internationalization
- Authentication - Auth0 with NextAuth.js
- Internationalization - next-intl (Japanese/English support)
Code Quality & Development Tools
- Formatter - oxfmt (Prettier-compatible; formatting + import & Tailwind class sorting)
- Linter - oxlint (type-aware, Rust-based)
- Testing Framework - Vitest with Testing Library
- Component Development - Storybook
Code Analysis & Quality Assurance
- Dead Code Detection - Knip
- Code Duplication Analysis - jscpd
- Dependency Analysis - dependency-cruiser
- Bundle Analysis -
next experimental-analyze(built-in Next.js bundle analyzer) - Security Auditing - pnpm audit
Documentation
- API Documentation - TypeDoc with packages strategy
- Database Schema Visualization - Mermaid ER diagram via prisma-erd-generator, rendered to an HTML page
Dependency Management & Security
- Automated Updates - Renovate
- Weekly scheduled updates (Mondays before 11am JST)
- Automatic vulnerability alerts with
securitylabel - Minimum release age: 2 days for patches/minors, preventing supply chain attacks
- Grouped updates: non-major dependencies & devDependencies (GitHub Actions and docker-compose are handled by Dependabot)
- Lock file maintenance enabled
- Manual Security Audits -
pnpm audit(moderate+ severity threshold) - Supply Chain Protection
- Package version pinning (
savePrefix: ''in pnpm-workspace.yaml) - Lifecycle script protection (
allowBuilds+strictDepBuilds: true) - Exotic subdep blocking (
blockExoticSubdeps: true) - Frozen lockfiles in CI/CD
- Package version pinning (
Monitoring & Observability
- Error Tracking - Sentry
- Analytics - Vercel Analytics & Speed Insights
- Logging - Pino
- Notifications - Pushover integration
Validation & Environment
- Schema Validation - Zod
- Environment Variables - @t3-oss/env-nextjs
初期設定
git clone https://github.com/s-hirano-ist/s-private.git
cd s-private
Continuous Deployment
GitHubにブランチが作成されるとVercel cloudに自動的にPreview環境が構築される。
GitHubのmainブランチにPRがpullされるとProduction環境が更新される。
Architecture Overview
Clean Architecture with Domain-Driven Design
This project follows clean architecture principles with domain-driven design, ensuring separation of concerns and maintainable code structure.
Directory Structure
├── packages/ # Monorepo packages
│ ├── core/ # Domain Layer (Core Business Logic)
│ │ ├── articles/ # News/link management domain
│ │ ├── notes/ # Markdown content domain
│ │ ├── images/ # File metadata domain
│ │ ├── books/ # ISBN-based book tracking domain
│ │ └── shared-kernel/ # Cross-domain shared logic
│ │
│ ├── database/ # Database Layer
│ │ └── prisma/ # Prisma ORM & migrations
│ │
│ ├── ui/ # Shared UI Components
│ │ ├── ui/ # shadcn/ui base components
│ │ ├── display/ # Display components (status, etc.)
│ │ ├── forms/ # Form components & fields
│ │ ├── layouts/ # Layout components (body, etc.)
│ │ ├── hooks/ # Shared React hooks
│ │ ├── providers/ # Context providers
│ │ └── utils/ # UI utilities
│ │
│ ├── notification/ # Notification services
│ │
│ ├── storage/ # MinIO Storage Client
│ │ └── src/ # MinIO client implementation
│ │
│ ├── search/ # RAG Search Library
│ │ └── src/ # Qdrant client, Embedding API client
│ │
│ └── scripts/ # Build & utility scripts
│ └── src/
│ ├── infrastructures/
│ └── rag/
│
└── app/src/ # Next.js Application
├── application-services/ # Application Layer (Use Cases)
│ ├── articles/
│ ├── notes/
│ ├── images/
│ ├── books/
│ ├── search/ # Search functionality
│ └── common/ # Shared application utilities
│
├── infrastructures/ # Infrastructure Layer (External Concerns)
│ ├── articles/ # Article repository implementation
│ ├── notes/ # Note repository implementation
│ ├── images/ # Image repository implementation
│ ├── books/ # Book repository implementation
│ ├── auth/ # Auth0 + NextAuth.js integration
│ ├── i18n/ # next-intl configuration
│ ├── observability/ # Sentry, logging, monitoring
│ ├── events/ # Event handling
│ ├── factories/ # Dependency injection factories
│ ├── search/ # Search infrastructure
│ └── shared/ # Shared infrastructure utilities
│
├── loaders/ # Data loading layer
│ ├── articles/
│ ├── notes/
│ ├── images/
│ └── books/
│
├── common/ # Shared utilities
│ ├── auth/
│ ├── error/
│ └── utils/
│
├── components/ # UI Components (Interface Layer)
│ ├── articles/
│ ├── notes/
│ ├── images/
│ ├── books/
│ └── common/
│
└── app/ # Next.js App Router
└── [locale]/ # Internationalized routes (en/ja)
├── (authenticated)/ # Authenticated (owner-only) pages
│ ├── articles/ # Articles management page (viewer/ = エクスポート済み閲覧ビュー)
│ ├── books/ # Books management page (viewer/, [slug]/)
│ ├── images/ # Images management page (viewer/)
│ ├── notes/ # Notes management page (viewer/, [slug]/)
│ └── error/ # Error page
├── book/[slug]/ # Book detail page
└── note/[slug]/ # Note detail page
Domain Boundaries
Each domain is completely isolated with its own:
- Entities - Core business logic and domain entities
- Repositories - Interface definitions (dependency inversion principle)
- Services - Complex business logic and domain operations
- Types - Domain-specific types and constants
Next.js App Router Features
- Internationalization: All routes support
[locale]pattern for English/Japanese - Route Groups:
(authenticated)route group for owner-only content management pages - Server Actions: All mutations use Next.js server actions with error boundary wrapping
RAG & Search Architecture
┌──────────────┐ ┌─────────────────────────────────────────┐
│ Next.js App │ │ ConoHa VPS (Docker) │
│ (Vercel) │ │ │
│ │ CF │ ┌───────────────┐ │
│ packages/ │────▶│ │ HuggingFace │ Cloudflare Tunnel │
│ search/ │Tunnel│ │ TEI (:3001) │◀── cloudflared │
│ │ │ └───────────────┘ │
└──────┬───────┘ │ multilingual-e5-small │
│ └─────────────────────────────────────────┘
│
▼
┌──────────────┐
│ Qdrant │
│ (Vector DB) │
└──────────────┘
Data Flow
- Ingestion: コンテンツ → Embedding API → ベクトル化 → Qdrant に保存
- Search: 検索クエリ → Embedding API → クエリベクトル化 → Qdrant で類似検索 → 結果返却
Key Components
packages/search/- RAG 検索ライブラリ(Qdrant クライアント、Embedding API クライアント、検索ロジック)- HuggingFace TEI - Embedding API サービス(ConoHa VPS 上で Docker 稼働、Cloudflare Tunnel 経由でアクセス。本リポジトリの
compose.yamlには含まれず別管理)
Database Architecture
Content management system with clean domain separation:
Core Models
- Article - News/link management with OpenGraph metadata and category association
- Note - Markdown-based content creation and management
- Image - File metadata tracking with tags, dimensions, and MinIO path storage
- Book - ISBN-based book tracking with Google Books API integration and ratings
Supporting Models
- Category - Hierarchical organization for Article items
Common Patterns
- Status Lifecycle:
UNEXPORTED→LAST_UPDATED→EXPORTED(all content types) - String-based IDs: All models use String primary keys with UUIDs
- User Isolation: Every model includes
userIdfor multi-tenant data separation - Unique Constraints: Comprehensive per-user unique constraints
Schema location: packages/database/prisma/schema.prisma
Key Architectural Patterns
- Server Actions: All mutations wrapped with
wrapServerSideErrorForClient - Authentication-only Authorization: ログイン=オーナー本人=全操作可(ロールによる権限区別は廃止)。Auth0 + NextAuth.js で認証し、Server Actionは冒頭で
requireAuth()を呼ぶ - Error Handling: Custom error classes with Pushover notifications and Sentry monitoring
- Input Validation: Zod schemas for all form and API input validation
- Type Safety: End-to-end TypeScript with runtime validation
External Service Integrations
- Authentication: Auth0 with NextAuth.js for session management
- File Storage: MinIO for object storage (configurable for local/cloud)
- Monitoring: Sentry for error tracking, Pushover for notifications
- APIs: Google Books API for ISBN-based book metadata enrichment
- VPS Services: ConoHa VPS (Docker) + Cloudflare Tunnel (deployment guide)
- Vector Database: Qdrant for semantic vector search
Development Setup
Prerequisites
- Node.js — version pinned in .nvmrc, installed via Mise
- pnpm v11.0.9 (managed via Mise)
- Doppler CLI v3.76.0 (managed via Mise)
- Docker (optional; for the VPS/embedding stack — MinIO, Cloudflare Tunnel)
Initial Setup
git clone https://github.com/s-hirano-ist/s-private.git
cd s-private
mise install # Node.js, pnpm, Doppler CLI 等をインストール
pnpm install
Environment Configuration
環境変数は dev/preview 環境は Doppler、本番環境は Vercel Dashboard で管理します。
Vercel CLI に一本化しない理由:
vercel env runは dev 環境から本番環境の変数にもアクセスできてしまうため、セキュリティ上 dev/preview は Doppler で分離しています。
# .env.local にDopplerサービストークンを設定(Doppler Dashboard から発行)
echo "DOPPLER_TOKEN=dp.st.dev.xxxxxxxxxxxx" > .env.local
vercel link # 初回のみ: Vercel プロジェクトをリンク(prisma スクリプト用)
Mise が .env.local を自動読み込みし、doppler run が DOPPLER_TOKEN を検出して環境変数を取得します。doppler login / doppler setup は不要です。
pnpm dev / pnpm build / pnpm start 等の app スクリプトは doppler run 経由で環境変数を取得します。pnpm prisma:* 等のルートスクリプトは vercel env run -e development を使用します。
型定義とバリデーション: app/src/env.ts(@t3-oss/env-nextjs + Zod)
環境変数の全体的な管理戦略(ローカル・CI・本番・VPS)については環境変数管理を参照。
Database Setup
ローカル開発は CockroachDB Cloud の dev-db クラスタに直結します(ローカル DB は不要)。マイグレーション運用(migrate dev 不使用・DB 不要の diff フロー・schema_locked)の詳細は docs/setup.md を参照。
# (Optional) Open Prisma Studio for database inspection (クラウド dev-db に接続)
pnpm prisma:studio
Development Workflow
# Start development server
pnpm dev
# Run development server with Next.js (http://localhost:3000)
# Hot reload enabled for all file changes
Development Commands
Essential Commands
# Development
pnpm dev # Start Next.js development server
pnpm build # Build production application
pnpm start # Start production server
# Code Quality
pnpm format # Format + import/Tailwind class sorting (oxfmt)
pnpm format:check # Check formatting without writing (oxfmt)
pnpm lint # Lint (oxlint, type-aware)
pnpm lint:fix # Lint with auto-fixing (oxlint)
pnpm deps:check # Clean Architecture boundary check (dependency-cruiser)
# Testing
pnpm test # Run Vitest unit tests (storybook含む全プロジェクト)
pnpm typecheck # TypeScript type checking (全パッケージ)
# Component Development
pnpm storybook # Start Storybook (http://localhost:6006)
pnpm storybook:build # Build static Storybook
pnpm ui-gallery:build # Build the embedded Storybook UI gallery from an existing static Storybook build
Code Quality & Analysis Tools
# Dead Code Detection
pnpm knip # Find unused files, dependencies, and exports
# Code Duplication Analysis
pnpm jscpd # Detect code duplication patterns
# Dependency Analysis
pnpm deps:check # Validate architectural boundaries and detect issues
pnpm deps:graph # Generate visual dependency graph (SVG)
pnpm deps:circular # Find circular dependencies
# Bundle Analysis
pnpm --filter s-private-app analyze # Analyze Next.js bundle size (next experimental-analyze; app workspace only)
# Security & Licenses
pnpm security # Check for security vulnerabilities (moderate+)
pnpm security:fix # Auto-fix security vulnerabilities
pnpm security:report # Generate JSON security audit report
pnpm license:summary # Generate library license summary
pnpm license:check # Check for forbidden licenses (GPL, LGPL variants)
# Note: Automated security updates are handled by Renovate (weekly schedule)
# Renovate configuration: .github/renovate.json5
各ツールの設定詳細・CI連携については docs/code-analysis.md を参照。
Database Operations
# Prisma Commands (Prisma client は pnpm install 時に postinstall で自動生成)
pnpm --filter s-database prisma:migrate:diff # Generate migration SQL (DB 不要の diff フロー)
pnpm prisma:deploy # Deploy migrations (cloud dev-db / production)
pnpm prisma:studio # Open Prisma Studio database browser
Documentation
# API Documentation (TypeDoc)
pnpm docs:build # Generate API docs (TypeDoc + DB schema)
pnpm pages:build # Generate GitHub Pages output (API docs + UI gallery)
pnpm docs:serve # Serve generated docs locally
pnpm docs:watch # Watch mode for TypeDoc
pnpm docs:clean # Remove generated documentation
# Output: docs/api/ (gitignored)
# Pages output: .pages/ (gitignored)
# Live: https://docs.s-hirano.com
Documentation Configuration
- Root
typedoc.jsonuses packages strategy (packages/core,packages/ui,packages/notification) - Each package has its own
typedoc.jsonfor granular control prisma-erd-generatorauto-generates a Mermaid ER diagram from the Prisma schema → a custom script (packages/database/scripts/generate-db-docs.sh) renders it into an HTML pagedocs:buildgenerates all documentation at once (TypeDoc + DB schema HTML)pages:buildpublishes API docs at/api/and a Figma-style embedded Storybook gallery at/ui/
Testing Strategy
Unit Testing (Vitest)
- Test files:
*.test.ts,*.test.tsx - Testing Library for React component testing
- Comprehensive coverage for domain logic and components
Component Testing (Storybook)
- Component documentation and testing
- Accessibility testing with
@storybook/addon-a11y - Coverage reporting for component interactions
Deployment & CI/CD
Continuous Deployment
- Preview Environments: Automatic deployment to Vercel for all branches
- Production: Auto-deployment to Vercel when PRs are merged to
main
Environments
- Development: CockroachDB Cloud dev-db に直結(ローカル DB 不要)
- Preview: Vercel branch deployments
- Production: Vercel production deployment
- Storybook: Deployed to Cloudflare Pages
- Embedding API: ConoHa VPS (Docker) + Cloudflare Tunnel
環境変数管理
環境変数は dev/preview 環境は Doppler、本番環境は Vercel Dashboard で管理する。Vercel CLI に一本化しない理由は、vercel env run が dev 環境から本番環境の変数にもアクセスできてしまうため。
| 環境 | 管理方法 | 注入方法 |
|---|---|---|
| ローカル開発(app) | Doppler | doppler run -- <command>(app/package.json スクリプトに組み込み済み) |
| ローカル開発(prisma) | Vercel Dashboard (dev) | vercel env run -e development -- <command>(root package.json スクリプトに組み込み済み) |
| CI (GitHub Actions) | GitHub Secrets | ワークフローの env: で ${{ secrets.XXX }} として注入 |
| 本番 (Vercel) | Vercel Dashboard | ビルド・ランタイムに自動注入 |
| VPS (Docker Compose) | ~/s-private/.env | Docker Compose が .env を自動読み込み |
ローカル開発
mise installでツール一式をインストール(Node.js, pnpm, Doppler CLI 等).env.localに Doppler サービストークンを設定(Doppler Dashboard > dev 環境 > Access > Service Tokens から発行)vercel linkで Vercel プロジェクトをリンク(初回のみ、prisma 用)pnpm dev/pnpm build/pnpm start等の app スクリプトは Doppler から環境変数を取得pnpm prisma:*等のルートスクリプトは Vercel dev 環境から環境変数を取得
CI (GitHub Actions)
必要な GitHub Secrets:
- アプリ環境変数:
DATABASE_URL,AUTH_SECRET,AUTH0_CLIENT_ID,AUTH0_CLIENT_SECRET,AUTH0_ISSUER_BASE_URL,SENTRY_AUTH_TOKEN,SENTRY_REPORT_URL,MINIO_HOST,MINIO_BUCKET_NAME,MINIO_ACCESS_KEY,MINIO_SECRET_KEY,PUSHOVER_USER_KEY,PUSHOVER_APP_TOKEN,QDRANT_URL,QDRANT_COLLECTION_NAME,NEXT_PUBLIC_SENTRY_DSN - 本番 DB:
PRODUCTION_DIRECT_URL— Prisma マイグレーションデプロイ用(.github/workflows/prisma-deploy.yaml) NPM_TOKEN— パッケージ公開(release-please のみ)ACTIONS_GITHUB_TOKEN— リリース PR 作成
環境変数が不要なジョブ(oxlint, storybook)では SKIP_ENV_VALIDATION: "true" を設定。
VPS (Docker Compose)
VPS 上の Docker Compose サービス用の環境変数は ~/s-private/.env に配置する。詳細は docs/vps-deployment.md Step 7 を参照。
型定義・バリデーション
app/src/env.ts で @t3-oss/env-nextjs + Zod を使用し、ビルド時に全変数をバリデーションする。SKIP_ENV_VALIDATION を設定するとバリデーションをスキップできる。
Code Standards & Architecture Rules
Formatting & Linting
- Formatting: oxfmt for formatting, import organization, and Tailwind class sorting
- Linting: oxlint (type-aware) for correctness, React/Next.js, and accessibility rules
- Strict TypeScript: Full type safety with runtime validation
Architectural Constraints
- No relative imports: Use absolute imports instead of
../../*patterns - Domain isolation: Cross-domain imports are forbidden
- Clean boundaries: Each layer (domain, application, infrastructure) is isolated
- Package manager: pnpm required (enforced by
packageManagerfield)
旧本番環境(現在はVercelに移行)
旧Storybook(現在はCloudflare Pagesに移行)
📜 License
Licensed under the AGPL-3.0 License, Copyright © 2024
Licenses of used libraries
See library-license.txt for the summary of licenses used in this project.
Automatic Updates: This file is automatically updated monthly via GitHub Actions.
To generate the license summary locally:
pnpm license:summary
Code Duplication Report
See jscpd-summary.txt for the latest code duplication analysis on the main branch.
Automatic Updates: This file is automatically updated monthly via GitHub Actions.
To run code duplication analysis locally:
pnpm jscpd