fsharp-shared

Define shared domain types and API contracts in F# full-stack applications.

1|Updated Nov 26, 2025
One-click install
npx skills add https://github.com/heimeshoff/Cinemarco --skill fsharp-shared
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: fsharp-shared
Source: https://github.com/heimeshoff/Cinemarco/tree/main/.claude/skills/fsharp-shared
Command: npx skills add https://github.com/heimeshoff/Cinemarco --skill fsharp-shared

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

This Skill establishes the shared contracts and domain types that drive the full-stack app, ensuring consistency across client and server boundaries.

Core Features & Use Cases

  • Domain Types: Records and discriminated unions for Todo items, priorities, etc.
  • API Contracts: ITodoApi interface and DTOs for Create/Update requests.
  • Single Source of Truth: Central place to mutate and reference domain definitions.

Quick Start

Define types in src/Shared/Domain.fs and API contracts in src/Shared/Api.fs, then implement.

Frequently Asked Questions about fsharp-shared

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I define shared domain types and API contracts for F# full-stack applications?

Define shared domain types using F# records and discriminated unions in src/Shared/Domain.fs, then specify API contracts and DTOs in src/Shared/Api.fs. This creates a single source of truth for data models across client and server boundaries, ensuring type safety and consistency.

What's the best way to structure API contracts and DTOs in F#?

Use F# records for DTOs and the ITodoApi interface pattern to define CRUD contracts. Records provide immutability and pattern matching support, while interfaces establish clear client-server boundaries with strongly-typed request and response shapes.

Why use discriminated unions and option types in domain modeling?

Discriminated unions model domain variants exhaustively, eliminating invalid states; option types encode nullability explicitly. Together they enforce type safety at compile time, reducing runtime errors and making domain logic self-documenting through F#'s type system.

When should I centralize domain types instead of duplicating them across client and server?

Centralize domain types when starting new features or modifying entities to prevent client-server desynchronization. A shared Domain.fs eliminates manual synchronization, reduces bugs from schema drift, and makes type contracts enforceable across boundaries.

Can I use this approach with functional-programming patterns in full-stack F# projects?

Yes. This approach integrates with F# functional patterns—records are immutable by default, option and result types encode effects explicitly, and discriminated unions enable exhaustive pattern matching for domain logic, aligning with functional design principles.

What's the difference between defining types in shared contracts versus in separate client and server modules?

Shared contracts create a single authoritative type definition reducing duplication and drift; separate modules risk inconsistency and require manual synchronization. Shared types enforce compile-time correctness across boundaries and simplify maintenance for full-stack applications.