s-private

July 5, 2026 · View on GitHub

License: AGPL v3 CI status GitHub stars

Important

仕事でできることは仕事でやる できないことをここで供養しよう

Live Services

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

UI & Styling

Database & Storage

  • Database - CockroachDB (PostgreSQL-compatible, distributed) with Prisma ORM
  • Object Storage - MinIO (configurable for local/cloud deployment)

Authentication & Internationalization

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

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 security label
    • 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

Monitoring & Observability

Validation & Environment

初期設定

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: UNEXPORTEDLAST_UPDATEDEXPORTED (all content types)
  • String-based IDs: All models use String primary keys with UUIDs
  • User Isolation: Every model includes userId for 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 runDOPPLER_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.json uses packages strategy (packages/core, packages/ui, packages/notification)
  • Each package has its own typedoc.json for granular control
  • prisma-erd-generator auto-generates a Mermaid ER diagram from the Prisma schema → a custom script (packages/database/scripts/generate-db-docs.sh) renders it into an HTML page
  • docs:build generates all documentation at once (TypeDoc + DB schema HTML)
  • pages:build publishes 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)Dopplerdoppler 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/.envDocker Compose が .env を自動読み込み

ローカル開発

  1. mise install でツール一式をインストール(Node.js, pnpm, Doppler CLI 等)
  2. .env.local に Doppler サービストークンを設定(Doppler Dashboard > dev 環境 > Access > Service Tokens から発行)
  3. vercel link で Vercel プロジェクトをリンク(初回のみ、prisma 用)
  4. pnpm dev / pnpm build / pnpm start 等の app スクリプトは Doppler から環境変数を取得
  5. 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 packageManager field)

旧本番環境(現在はVercelに移行)

s-tools/s-privateを参照。

旧Storybook(現在はCloudflare Pagesに移行)

s-tools/s-storybookを参照。

📜 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