Skip to content
nexisv1.3.3Build with Nexis
← Learning map

Builder · lesson 05

Load data and mutate it through secure Actions

Deduplicate request-local loads, build native-first forms, validate server input, and keep mutations outside client code.

copyable patternserver-firstenterprise track

01

Keep data request-local

Use the server DataContext and data helper to share a single in-flight load within one request. This avoids duplicate work without turning user data into a mutable global.

  • Validate loaded data before rendering it.
  • Keep database clients and private services server-only.
  • Use a safe key for request-local data deduplication.

02

Forms begin as HTML

Use Form and SubmitButton for the standard progressive path. The action and method remain the fallback while the Nexis forms runtime provides pending state and typed responses.

  • Use POST for mutations.
  • Provide labels and browser validation as usability, not security.
  • Show result status through an aria-live region when enhanced.

03

Actions own mutation policy

The framework action pipeline validates input, can authorize, and handles the endpoint envelope. Application code remains responsible for resource ownership, audit records, and durable stores.

  • Validate types, length, range, and allowed values server-side.
  • Use Origin checks and CSRF policy.
  • Use durable idempotency for retriable non-repeatable mutations.
Typed Action + native Form · framework-nativeTypeScript
import { action } from '@mohammedaydan/actions'
import { Form, SubmitButton } from '@mohammedaydan/core'

const saveProfile = action({
  endpoint: '/__nexis/actions/profile/save',
  validate: (input) => parseProfileInput(input),
  authorize: async (context, input) => requireProfileOwner(context.request, input.userId),
  handle: async (_context, input) => updateProfile(input),
})

export function ProfileForm({ csrfToken }: { readonly csrfToken: string }) {
  return <Form action={saveProfile} csrfToken={csrfToken}>
    <label htmlFor="name">Name</label>
    <input id="name" name="name" required />
    <SubmitButton loadingText="Saving…">Save profile</SubmitButton>
  </Form>
}

PRACTICE LAB

Prove the behavior.

Write a failing test for invalid data and another for a rejected owner check before implementing a successful update.