effect-frontend-patterns

Effect TypeScript for Frontend

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "effect-frontend-patterns" with this command: npx skills add 5dlabs/cto/5dlabs-cto-effect-frontend-patterns

Effect TypeScript for Frontend

Effect is the missing standard library for TypeScript. Use it for type-safe error handling, validation, and data fetching in frontend applications.

Documentation

Before implementing, consult:

Use Context7:

resolve_library_id({ libraryName: "effect typescript" }) get_library_docs({ context7CompatibleLibraryID: "/effect-ts/effect", topic: "schema validation" })

Effect Schema (Replaces Zod)

import { Schema } from "effect"

// Define schemas const UserSchema = Schema.Struct({ id: Schema.String, name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100)), email: Schema.String.pipe(Schema.pattern(/^[^@]+@[^@]+.[^@]+$/)), role: Schema.Literal("admin", "user", "guest"), createdAt: Schema.Date, }) type User = Schema.Schema.Type<typeof UserSchema>

// Form validation schema const CreateUserSchema = Schema.Struct({ name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100)), email: Schema.String.pipe(Schema.pattern(/^[^@]+@[^@]+.[^@]+$/)), password: Schema.String.pipe(Schema.minLength(8)), })

// Validate unknown data const parseUser = Schema.decodeUnknown(UserSchema)

Effect + TanStack Query

import { Effect, Schema } from "effect" import { useQuery, useMutation } from "@tanstack/react-query"

// Type-safe API error class ApiError extends Schema.TaggedError<ApiError>("ApiError")({ message: Schema.String, statusCode: Schema.Number, }) {}

// Effect-powered fetch with validation const fetchUsers = Effect.tryPromise({ try: () => fetch("/api/users").then((r) => r.json()), catch: () => new ApiError({ message: "Network error", statusCode: 500 }), }).pipe( Effect.flatMap(Schema.decodeUnknown(Schema.Array(UserSchema))), Effect.catchTag("ParseError", (e) => Effect.fail(new ApiError({ message: "Invalid response", statusCode: 422 })) ) )

// React hook function useUsers() { return useQuery({ queryKey: ["users"], queryFn: () => Effect.runPromise(fetchUsers), }) }

// Mutation with Effect function useCreateUser() { return useMutation({ mutationFn: (data: typeof CreateUserSchema.Type) => Effect.runPromise( Effect.tryPromise({ try: () => fetch("/api/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }).then((r) => r.json()), catch: () => new ApiError({ message: "Failed to create user", statusCode: 500 }), }).pipe(Effect.flatMap(Schema.decodeUnknown(UserSchema))) ), }) }

React Hook Form + Effect Schema

import { useForm } from "react-hook-form" import { effectTsResolver } from "@hookform/resolvers/effect-ts" import { Schema } from "effect"

function CreateUserForm() { const form = useForm({ resolver: effectTsResolver(CreateUserSchema), defaultValues: { name: "", email: "", password: "" }, })

return ( <Form {...form}> <FormField control={form.control} name="name" render={({ field }) => ( <FormItem> <FormLabel>Name</FormLabel> <FormControl> <Input {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> {/* ... other fields */} </Form> ) }

WebSocket with Effect Stream

import { Effect, Stream, Schema, Fiber } from "effect"

// Define message schema const NotificationSchema = Schema.Struct({ id: Schema.String, type: Schema.Literal("info", "warning", "error"), message: Schema.String, timestamp: Schema.Date, })

// Create WebSocket stream const notificationStream = Stream.async<typeof NotificationSchema.Type, Error>((emit) => { const ws = new WebSocket("/api/ws/notifications")

ws.onmessage = (event) => { const result = Schema.decodeUnknownSync(NotificationSchema)(JSON.parse(event.data)) emit.single(result) }

ws.onerror = () => emit.fail(new Error("WebSocket connection failed")) ws.onclose = () => emit.end()

return Effect.sync(() => ws.close()) })

// React hook function useNotificationStream(onNotification: (n: Notification) => void) { useEffect(() => { const fiber = Effect.runFork( Stream.runForEach(notificationStream, (notification) => Effect.sync(() => onNotification(notification)) ) ) return () => Effect.runSync(Fiber.interrupt(fiber)) }, [onNotification]) }

Context7 Topics to Query

get_library_docs({ context7CompatibleLibraryID: "/effect-ts/effect", topic: "schema validation" }) get_library_docs({ context7CompatibleLibraryID: "/effect-ts/effect", topic: "error handling tagged errors" }) get_library_docs({ context7CompatibleLibraryID: "/effect-ts/effect", topic: "stream async" })

PRD → Component Mapping

Requirement Components Effect Pattern

"Login/signup" Form

  • Input
  • Better Auth Effect Schema validation

"Dashboard" Card grid + Chart

Effect data fetching

"User list" Table or DataTable

Effect + TanStack Query

"Settings" Tabs with Form sections Effect Schema forms

"Real-time updates" WebSocket feed Effect.Stream

"Search" Command palette Effect debounced search

"File upload" Drag-drop zone Effect error handling

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-mcp

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

test-driven-development

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

project-development

No summary provided by upstream source.

Repository SourceNeeds Review