svelte-effect-runtime
Recipes

Forms With Validation

Validate form input on the server and return useful field errors.

Forms are easiest to maintain when the server owns validation and the client renders precise feedback. Effect lets validation stay typed and composable.

When to use this

Use this recipe for account settings, creation forms, sign-in forms, and any flow where field-level feedback matters.

Minimal working example

import { Form } from "svelte-effect-runtime/server";
import { Effect, Schema } from "effect";

const ProfileInput = Schema.Struct({
  name: Schema.String,
});

export const save_profile = Form(
  ProfileInput,
  ({ data, invalid }) =>
    Effect.gen(function* () {
      if (data.name.trim().length === 0) {
        return yield* invalid.name("Name is required");
      }

      return { name: data.name.trim() };
    }),
);

Realistic variant

The invalid proxy creates structured field errors:

return yield* invalid.name("Name is required");
<script lang="ts">
  import { save_profile } from "./profile.remote";
</script>

<form {...save_profile} oninput={() => save_profile.validate()}>
  <input name="name" />
  <button>Save</button>
</form>

Common mistakes

  • Validating only in the browser.
  • Returning a single form error when a field error would help.
  • Replacing HTML form semantics with button click code.
  • Forgetting disabled and pending states during submission.

On this page