Overview
Skiff uses a Yarn workspaces monorepo structure to manage multiple applications and shared libraries. This architecture enables code reuse, consistent tooling, and streamlined dependency management across all packages.The monorepo uses Yarn Berry (v4.0.1) with workspace protocol for internal dependencies.
Workspace Configuration
The rootpackage.json defines the workspace structure:
Repository Structure
Libraries Workspace
Thelibs/ directory is itself a workspace containing multiple packages. Each library serves a specific purpose:
Core Libraries
skiff-crypto
skiff-crypto
Core cryptography library providing end-to-end encryption primitives:
- Public key cryptography
- Symmetric encryption
- Key derivation
- Digital signatures
skiff-crypto-v2
skiff-crypto-v2
Updated cryptography implementation with improved algorithms and performance.
Gradually replacing v1 across the codebase.
skiff-utils
skiff-utils
Fundamental utilities shared across all packages:
- Date/time helpers
- String formatting
- Validation utilities
- Constants and enums
skiff-front-utils
skiff-front-utils
Frontend-specific utilities:
- React hooks
- Browser storage helpers
- UI state management
- Email formatting functions
skiff-utils.Data & API Libraries
skiff-graphql
skiff-graphql
GraphQL schema definitions and type resolvers:
- Type definitions
- GraphQL resolvers
- API contracts
skiff-front-graphql
skiff-front-graphql
Frontend GraphQL utilities:
- Apollo Client setup
- Query/mutation hooks
- Cache configuration
- GraphQL code generation
skiff-mail-protos
skiff-mail-protos
Compiled Protocol Buffer definitions for:
- Email message structures
- Encrypted data formats
- API message types
.proto files in the protos/ directory.skiff-ics
skiff-ics
iCalendar (ICS) format parsing and generation:
- ICS file parsing
- Event serialization
- Calendar import/export
UI & Editor Libraries
nightwatch-ui
nightwatch-ui
Shared UI component library:
- Design system components
- Themed components
- Consistent styling
skiff-prosemirror
skiff-prosemirror
Rich text editor utilities built on ProseMirror:
- Custom schema definitions
- Editor plugins
- Text formatting utilities
skiff-front-search
skiff-front-search
Client-side search functionality:
- Index management
- Search algorithms
- Query parsing
Tooling Libraries
eslint-config-skiff-eslint
eslint-config-skiff-eslint
Shared ESLint configuration:
- Code style rules
- TypeScript rules
- React-specific rules
Application Packages
skemail-web
The Skiff Mail web application built with:- Framework: Custom Webpack setup (not Next.js)
- UI: React 17 with styled-components
- State: Redux Toolkit
- Editor: TipTap (ProseMirror-based)
calendar-web
The Skiff Calendar web application with similar architecture to skemail-web:- Framework: Custom Webpack setup
- UI: React 17 with styled-components
- State: Redux Toolkit
- Storage: Dexie (IndexedDB wrapper)
- Uses
skiff-icsfor calendar format handling - Integrates with Google Calendar API
- Uses IndexedDB for offline storage
Build Order & Dependencies
Libraries must be built in topological order due to interdependencies: Build command (fromlibs/package.json):
Workspace Protocol
The monorepo uses Yarn’sworkspace: protocol for internal dependencies:
- Development: Direct linking to source code
- Type safety: TypeScript resolves to actual source
- Hot reloading: Changes in libraries reflect immediately
Shared Dependencies
Common dependencies are hoisted to the rootpackage.json:
Development Tools
- TypeScript 5.0.0
- Jest 28.1.1 with SWC
- ESLint 8.x
- Prettier 2.x
Testing Libraries
@testing-library/react12.1.2@testing-library/react-hooks7.0.2@testing-library/jest-dom5.16.2@testing-library/user-event14.1.1
Build Tools
- Babel 7.x with TypeScript preset
- GraphQL Code Generator
- Protocol Buffers compiler
Working with Workspaces
Run commands in specific workspace
Run commands in all workspaces
Add dependency to specific workspace
Best Practices
Library Changes
When modifying libraries, rebuild them before testing in applications:
New Dependencies
Add shared dependencies to root
package.json. Add package-specific dependencies to the package’s own package.json.Type Safety
Export types from libraries in their
index.ts to maintain clean public APIs.Circular Dependencies
Avoid circular dependencies between libraries. Use the
yarn lint:cycles command to detect them.Next Steps
Development Setup
Set up your development environment
Contributing
Learn how to contribute code