Having trouble editing the avatar coming back into app

So I can create the avatar no problem. I have stored the avatar/model id in Firebase.
But I am having issues signing in and then editing/customising my existing avatar.
I get you are not allowed to view that avatar.

What am I doing wrong? Anyone to help please? NextJS

Here’s the code I’m using

‘use client’;

import { useEffect, useMemo, useRef, useState } from ‘react’;

import { createPortal } from ‘react-dom’;

import { type User, updateProfile } from ‘firebase/auth’;

import { Button } from ‘./ui/button’;

import { Input } from ‘./ui/input’;

import { Label } from ‘./ui/label’;

import { Avatar, AvatarFallback, AvatarImage } from ‘./ui/avatar’;

import { Loader2, Sparkles, User as UserIcon } from ‘lucide-react’;

import { useToast } from ‘@/hooks/use-toast’;

import { auth } from ‘@/lib/firebase’;

interface ProfileSetupDialogProps {

open: boolean;

onOpenChange: (open: boolean) => void;

user: User;

}

const READY_PLAYER_ME_URL = ‘fake link for obvious reasons’’; //just studio name in here of the url

export function ProfileSetupDialog({ open, onOpenChange, user }: ProfileSetupDialogProps) {

const { toast } = useToast();

const [displayName, setDisplayName] = useState(‘’);

const [avatarUrl, setAvatarUrl] = useState(‘’);

const [saving, setSaving] = useState(false);

const iframeRef = useRef(null);

useEffect(() => {

if (!open) {

  return;

}



setDisplayName(user.displayName ?? '');

setAvatarUrl(user.photoURL ?? '');

}, [open, user.displayName, user.photoURL]);

const previewAvatar = avatarUrl || user.photoURL || ‘’;

const initials = useMemo(() => {

if (displayName?.trim()) {

  return displayName

    .trim()

    .split(/\\s+/)

    .map((part) => part.charAt(0).toUpperCase())

    .slice(0, 2)

    .join('');

}



if (user.email) {

  return user.email.charAt(0).toUpperCase();

}



return 'U';

}, [displayName, user.email]);

useEffect(() => {

if (!open) {

  return;

}



const handleMessage = (event: MessageEvent) => {

  let data: any = event.data;



  if (typeof data === 'string') {

    try {

      data = JSON.parse(data);

    } catch (error) {

      return;

    }

  }



  if (data?.source !== 'readyplayerme') {

    return;

  }



  if (data.eventName === 'v1.avatar.exported') {

    const url = data.data?.url as string | undefined;

    if (url) {

      setAvatarUrl(url);

      toast({

        title: 'Avatar ready',

        description: 'We swapped in your new look so you can preview it instantly.',

      });

    }

  }

};



window.addEventListener('message', handleMessage);



return () => {

  window.removeEventListener('message', handleMessage);

};

}, [open, toast]);

useEffect(() => {

if (!open) {

  return;

}



const originalOverflow = document.body.style.overflow;

document.body.style.overflow = 'hidden';

return () => {

  document.body.style.overflow = originalOverflow;

};

}, [open]);

const subscribeToEvents = () => {

const frameWindow = iframeRef.current?.contentWindow;

if (!frameWindow) {

  return;

}



const subscribe = (eventName: string) =>

  frameWindow.postMessage(

    JSON.stringify({

      target: 'readyplayerme',

      type: 'subscribe',

      eventName,

    }),

    '\*',

  );



subscribe('v1.frame.ready');

subscribe('v1.avatar.exported');

};

const handleSave = async () => {

const trimmedName = displayName.trim();



if (!trimmedName) {

  toast({

    title: 'Display name required',

    description: 'Please choose a display name to continue.',

    variant: 'destructive',

  });

  return;

}



setSaving(true);

try {

  await updateProfile(user, {

    displayName: trimmedName,

    photoURL: avatarUrl.trim() || null,

  });

  await user.reload();

  await auth.currentUser?.reload();

  toast({

    title: 'Profile updated',

    description: 'Your display name and avatar have been saved.',

  });

  onOpenChange(false);

} catch (error) {

  console.error('Error updating profile', error);

  toast({

    title: 'Update failed',

    description: 'We could not update your profile. Please try again.',

    variant: 'destructive',

  });

} finally {

  setSaving(false);

}

};

if (!open) {

return null;

}

return createPortal(

<div className="fixed inset-0 z-50 flex h-full w-full text-white">

  <div className="relative flex h-full w-full overflow-hidden bg-slate-950">

    <div className="pointer-events-none absolute inset-0">

      <div className="absolute left-1/2 top-\[-10%\] h-\[120%\] w-\[120%\] -translate-x-1/2 rounded-full bg-\[radial-gradient(circle_at_center,\_rgba(56,189,248,0.18),\_transparent_60%)\]" />

      <div className="absolute inset-0 bg-\[url('/textures/asphalt.png')\] opacity-10 mix-blend-screen" />

      <div className="absolute bottom-0 left-0 right-0 h-40 bg-gradient-to-t from-slate-950 via-slate-950/40 to-transparent" />

    </div>

    <aside className="relative z-10 flex w-full flex-col gap-8 border-b border-white/10 bg-slate-950/80 p-6 backdrop-blur-xl lg:w-\[420px\] lg:border-b-0 lg:border-r">

      <div className="flex items-center justify-between">

        <div className="inline-flex items-center gap-2 rounded-full border border-primary/40 bg-primary/10 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-primary">

          <Sparkles className="h-3.5 w-3.5" />

          Driver Garage

        </div>

        <Button

          type="button"

          variant="ghost"

          className="text-slate-300 hover:text-white"

          onClick={() => onOpenChange(false)}

          disabled={saving}

        >

          Skip for now

        </Button>

      </div>

      <header className="space-y-3">

        <h1 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">

          Create Your In-Game Persona

        </h1>

        <p className="text-sm text-slate-300 sm:text-base">

          Dial in your call sign and suit before you roll onto the grid. We&apos;ll showcase your look on leaderboards, rival

          challenges, and post-race celebrations.

        </p>

      </header>

      <div className="rounded-2xl border border-white/10 bg-slate-900/70 p-6 shadow-xl">

        <div className="flex items-center justify-between">

          <span className="text-xs uppercase tracking-\[0.3em\] text-slate-400">Preview</span>

          <span className="text-xs font-medium text-primary/80">Live update</span>

        </div>

        <div className="mt-4 flex flex-col items-center gap-4">

          <div className="relative flex h-48 w-full items-center justify-center overflow-hidden rounded-xl border border-white/10 bg-gradient-to-br from-slate-900 via-slate-900/60 to-slate-800">

            <div className="absolute inset-x-6 bottom-6 h-24 rounded-full bg-primary/20 blur-3xl" />

            <Avatar className="relative z-10 h-40 w-40 border-2 border-primary/50 bg-slate-900">

              <AvatarImage src={previewAvatar || undefined} alt="Avatar preview" />

              <AvatarFallback className="bg-slate-800 text-3xl font-semibold text-white">

                {initials || <UserIcon className="h-8 w-8" />}

              </AvatarFallback>

            </Avatar>

          </div>

          <div className="w-full space-y-2">

            <Label htmlFor="display-name" className="text-xs uppercase tracking-wide text-slate-400">

              Driver tag

            </Label>

            <Input

              id="display-name"

              value={displayName}

              onChange={(event) => setDisplayName(event.target.value)}

              placeholder="e.g. ApexAce or TurboTina"

              maxLength={40}

              className="bg-slate-950/60 text-base"

            />

            <p className="text-xs text-slate-400">

              Your driver tag is shown in multiplayer lobbies, lap charts, and highlight reels.

            </p>

          </div>

          {avatarUrl && (

            <Button

              type="button"

              variant="ghost"

              className="w-full justify-center text-sm text-slate-300 hover:text-white"

              onClick={() => setAvatarUrl('')}

              disabled={saving}

            >

              Reset to default avatar

            </Button>

          )}

        </div>

      </div>

      <div className="flex flex-col gap-3 text-xs text-slate-400">

        <p>

          Finish customizing on the right and hit <span className="font-semibold text-slate-200">Export Avatar</span>. We&apos;ll drop the fresh render straight into your preview.

        </p>

        <p>

          Ready Player Me might ask for camera access to generate your likeness. It&apos;s optional—you can always sculpt manually.

        </p>

      </div>

      <div className="mt-auto flex flex-col gap-3 sm:flex-row">

        <Button

          type="button"

          variant="secondary"

          onClick={handleSave}

          disabled={saving}

          className="gap-2 bg-primary/20 text-primary hover:bg-primary/30"

        >

          {saving && <Loader2 className="h-4 w-4 animate-spin" />}

          Save &amp; Hit the Track

        </Button>

        <Button

          type="button"

          variant="outline"

          onClick={() => onOpenChange(false)}

          disabled={saving}

          className="border-white/20 text-slate-200 hover:bg-slate-800/60"

        >

          I&apos;ll tune it later

        </Button>

      </div>

    </aside>

    <main className="relative z-10 flex flex-1 flex-col bg-black/80">

      <div className="hidden h-16 items-center justify-between border-b border-white/10 px-8 lg:flex">

        <div className="space-y-1">

          <p className="text-xs uppercase tracking-\[0.4em\] text-primary/70">Avatar Workshop</p>

          <p className="text-sm text-slate-300">

            Craft a driver that looks right at home in the pit lane.

          </p>

        </div>

      </div>

      <div className="flex items-center justify-between border-b border-white/10 px-4 py-3 lg:hidden">

        <div className="space-y-1">

          <p className="text-xs uppercase tracking-\[0.4em\] text-primary/70">Avatar Workshop</p>

          <p className="text-xs text-slate-300">

            Use the controls below to export your driver.

          </p>

        </div>

      </div>

      <iframe

        ref={iframeRef}

        src={READY_PLAYER_ME_URL}

        title="Driver Persona Customiser"

        className="h-full w-full lg:border-l lg:border-white/10"

        allow="camera \*; microphone \*"

        onLoad={subscribeToEvents}

      />

    </main>

  </div>

</div>,

document.body,

);

}