relayauth starter

THE WHOLE JOURNEY, IN ONE PLACE

Make it your own.

Eight connected authentication screens. One visual system. Plain HTML, CSS and JavaScript, with no packages, build step or external assets.

Try every step

Use made-up details. Verification accepts the demo code 123456. Open “Preview settings” at the bottom of each screen to try rejected, network, rate-limit and expired responses. Resend buttons have a 30-second demonstration cooldown.

Run it locally

Unzip the download and serve the relay-auth directory with any static HTTP server. ES modules require HTTP rather than opening HTML directly with file://.

cd relay-auth
python3 -m http.server 8080
# Open http://localhost:8080/

What goes where

FilePurpose
*.htmlStatic screen markup, copy, labels and navigation.
assets/style.cssShared styles, colors, responsive layout and focus states.
assets/app.jsValidation, password visibility, loading/error feedback, demo routes and resend cooldown.
assets/auth-adapter.jsThe explicit boundary between the interface and your authentication service. Replace the demo implementation here.
assets/mark.svgLocal brand mark. Replace with your own identity.

Connect your service

The interface calls authenticate(operation, data, options). Return a promise that resolves only after your service has accepted the request. Reject on network, validation, permission and service errors; never resolve simply because fetch() returned a response. The demonstration scenario option belongs only to the demo adapter.

OperationData / service responsibility
signInEmail and password. Establish a real server session before directing users to a protected destination.
signUpName, email and password. Create the pending account and issue a verification challenge.
requestResetEmail. Start a recovery transaction; give the same public response whether an account exists or not.
resetPasswordNew password. Retrieve the provider-issued recovery token according to its documented flow and validate it on the server.
verifyCodeCode. Bind it to the server's pending challenge; enforce expiry and attempt limits server-side.
resendReset / resendVerificationNo form payload. Resolve the current transaction from your service's session/challenge context. If context is absent, route back to recovery or registration.

The demo deliberately stores no email, password or token between pages. Your integration needs its own server-held transaction context for recovery and verification. Handle fresh tabs, reloads, missing context, expired tokens and already-used links. The browser cooldown is a visual aid; enforce resend limits in the service.

Match service errors to the interface

Reject with an Error containing a code property: NETWORK, RATE_LIMITED, EXPIRED or REJECTED. Other errors receive a generic message. Reset expiry opens the expired-link screen; verification expiry stays on the code form and offers resend. Do not expose raw provider errors or account-existence details to visitors.

// Inside your replacement adapter, after checking the service response:
throw Object.assign(new Error('Request not accepted'), {
  code: 'REJECTED'
});

Before a real launch

Customize the design

Change the palette and font stack in :root in the stylesheet. The illustration uses HTML/CSS; no remote fonts, icon libraries or image services are required. Inputs have persistent labels, errors are connected to their fields, and loading/results are announced with live regions. Test again after changing colors, copy or form structure.

Credits and license

Original interface and illustration by Colorlib. Distributed under CC BY 3.0; retain appropriate Colorlib attribution. See LICENSE.txt in the download.

Back to the demo →