Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/player-one/llms.txt

Use this file to discover all available pages before exploring further.

The Contact page closes the arcade loop by framing outreach as saving progress. Just as a player reaches a save point after completing a difficult stretch of a game, a visitor who has explored the portfolio and wants to connect is invited to “save” their contact details and leave a message. The form fields carry the portfolio’s visual language — cyan focus-glow borders, pixel-styled labels, and an arcade button for submission — making the act of reaching out feel like a natural continuation of the experience rather than a jarring departure into a generic contact form. The Phone icon in the navigation panel identifies this as the communication endpoint of the portfolio.

Route Info

PropertyValue
Path/contact
Arcade LabelSAVE GAME
Navigation IconPhone (phone)
Page TransitionPageTransition blur/scale wrapper, pt-24 pb-32 padding

Visual Layout

The page centers a single styled form panel on the viewport:
  1. Save screen header — a pixel-font heading (e.g., “SAVE GAME” or “NEW MESSAGE”) introduces the form.
  2. Form fields — each input is styled with the arcade theme:
    • Name — text input with a pixel-bordered container.
    • Email — email input; receives the cyan glow on focus.
    • Message — multi-line textarea for the visitor’s note.
  3. Submit button — the primary action button uses the shared arcade button style: pixel border, press-down active state, and a label such as TRANSMIT or SEND MESSAGE.
  4. Confirmation state — after a successful submission, the form transitions to a victory/confirmation message styled as a “PROGRESS SAVED” screen.
The HUD, CRTOverlay, and GhostSprite components appear as on all other routes.

Key Components

PageTransition

Shared entrance animation wrapper applied on route navigation.

Arcade form inputs

Text, email, and textarea inputs styled with pixel borders and a cyan focus-ring glow consistent with the portfolio’s color palette.

Arcade submit button

The primary form submission button. Shares the same pixel-border and press-down active-state style as the Start button on the Home page.

Navigation

Used in the Navigation inventory panel to identify the Contact route as the communication endpoint of the portfolio.

Interactivity & Special Features

  • Cyan focus glow — each form field gains a box-shadow glow in the portfolio’s primary cyan accent color when focused, reinforcing the arcade HUD aesthetic.
  • Validation states — invalid or empty required fields can display pixel-styled inline error messages (e.g., “INPUT REQUIRED” instead of a plain browser tooltip).
  • Submit button feedback — the button can transition to a loading state (e.g., flashing “TRANSMITTING…”) while the form submission is in-flight, and then to a success state once confirmed.
  • PROGRESS SAVED confirmation — a full-form replacement or overlay that mimics a save-game success screen, confirming the message was received.

Backend Integration

The contact form is client-side only in the base implementation — submitting the form does not send any data until it is wired to a backend endpoint or a third-party form service. Services like Formspree, Netlify Forms, or Basin accept form submissions via a simple POST request with no custom backend required.
// Example: wiring the form to Formspree
<form
  action="https://formspree.io/f/YOUR_FORM_ID"
  method="POST"
  onSubmit={handleSubmit}
>
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <textarea name="message" required />
  <button type="submit">TRANSMIT</button>
</form>
Replace YOUR_FORM_ID with the ID from your Formspree dashboard. Formspree forwards submissions to your email and provides a spam filter at the free tier.

Option 2 — Custom API route

If the portfolio is deployed alongside a backend (Express, Next.js API routes, a serverless function, etc.), point the form’s fetch or axios call to your own endpoint:
const handleSubmit = async (e) => {
  e.preventDefault();
  setStatus("sending");

  const res = await fetch("/api/contact", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name, email, message }),
  });

  if (res.ok) {
    setStatus("success");
  } else {
    setStatus("error");
  }
};
Your /api/contact handler can then relay the message via Nodemailer, SendGrid, Resend, or any transactional email provider.

Option 3 — mailto: fallback

For the simplest possible integration with zero backend, the submit button can be swapped for a mailto: link. This opens the visitor’s default email client pre-populated with the subject and body:
<a
  href="mailto:you@example.com?subject=Portfolio%20Contact&body=Hello%2C"
  className="arcade-button"
>
  OPEN MAIL CLIENT
</a>
Do not leave the form in its default client-side-only state when publishing the portfolio publicly. A contact form that silently discards submissions — with no visible error — damages trust with visitors who take the time to write a message.

Customization Notes

Update the form field labels, placeholder text, and submit button label to match your voice. “TRANSMIT”, “SEND”, “SAVE & SEND”, and “INSERT MESSAGE” are all on-theme options. The label sets the tone for the interaction, so choose one that feels natural alongside your overall portfolio copy.
Add a honeypot field (a hidden input that real users never fill in but bots do) to reduce spam without requiring a CAPTCHA, which would break the arcade immersion:
<input type="text" name="_gotcha" style={{ display: "none" }} tabIndex={-1} autoComplete="off" />
Most form services (Formspree, Basin) recognize the _gotcha convention automatically.
Style the confirmation / “PROGRESS SAVED” state as carefully as the form itself. It is the last impression the portfolio leaves on a visitor who cared enough to reach out — make it feel like a genuine victory screen, not an afterthought.

Build docs developers (and LLMs) love