Skip to main content
Version: 0.16.0

Create your own UI

The login and signup flows are pretty standard: they allow the user to sign up and then log in with their username and password. The signup flow validates the username and password and then creates a new user entity in the database.

tip

Read more about the default email and password validation rules in the auth overview docs.

Even though Wasp offers premade Auth UI for your authentication flows, there are times where you might want more customization, so we also give you the option to create your own UI and call Wasp's auth actions on your own code, similar to how Auth UI does it under the hood.

Example code

Below you can find a starting point for making your own UI in the client code. You can customize any of its look and behaviour, just make sure to call the signup() or login() functions imported from wasp/client/auth.

Sign-up

src/pages/auth.jsx
import { login, signup } from 'wasp/client/auth'

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'

export function Signup() {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState(null)
const navigate = useNavigate()

async function handleSubmit(event) {
event.preventDefault()
setError(null)
try {
await signup({ username, password })
await login(username, password)
navigate('/')
} catch (error) {
setError(error)
}
}

return (
<form onSubmit={handleSubmit}>
{error && <p>Error: {error.message}</p>}

<input
type="text"
autoComplete="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Sign Up</button>
</form>
)
}

Login

src/pages/auth.jsx
import { login } from 'wasp/client/auth'

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'

export function Login() {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState(null)
const navigate = useNavigate()

async function handleSubmit(event) {
event.preventDefault()
setError(null)
try {
await login(username, password)
navigate('/')
} catch (error) {
setError(error)
}
}

return (
<form onSubmit={handleSubmit}>
{error && <p>Error: {error.message}</p>}

<input
type="text"
autoComplete="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit">Sign Up</button>
</form>
)
}

API Reference

You can import the following functions from wasp/client/auth:

login()

An action for logging in the user.

It takes two arguments:

  • username: string required

    Username of the user logging in.

  • password: string required

    Password of the user logging in.

note

When using the exposed login() function, make sure to implement your redirect on success login logic (e.g. redirecting to home).

signup()

An action for signing up the user. This action does not log in the user, you still need to call login().

It takes one argument:

  • userFields: object required

    It has the following fields:

    • username: string required

    • password: string required

info

By default, Wasp will only save the username and password fields. If you want to add extra fields to your signup process, read about defining extra signup fields.