feat: avatar upload, connected accounts, round navbar avatar, Vercel analytics

- Avatar upload to Supabase Storage with pencil overlay in settings
- Show username initials as avatar fallback (instead of name initials)
- Round avatar in navbar (rounded-full with natural shadow)
- Connected Accounts section in settings showing Google status
- Connect Google directly from settings without signing out
- Add Vercel Analytics, Speed Insights, and Toolbar
- Update page title to "Pascal Editor"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aymeric Rabot
2026-02-19 01:40:17 -05:00
co-authored by Claude Opus 4.6
parent b53cb984eb
commit 23a71c376f
7 changed files with 405 additions and 37 deletions
+10 -2
View File
@@ -1,5 +1,8 @@
import type { Metadata } from 'next'
import localFont from 'next/font/local'
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'
import { VercelToolbar } from '@vercel/toolbar/next'
import { UsernameGate } from '@/features/community/components/username-gate'
import './globals.css'
@@ -13,8 +16,8 @@ const geistMono = localFont({
})
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
title: 'Pascal Editor',
description: 'Open-source 3D building editor',
}
export default function RootLayout({
@@ -22,10 +25,15 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode
}>) {
const shouldShowToolbar = process.env.NODE_ENV === 'development'
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
<UsernameGate>{children}</UsernameGate>
<Analytics />
<SpeedInsights />
{shouldShowToolbar && <VercelToolbar />}
</body>
</html>
)
+6 -2
View File
@@ -2,7 +2,7 @@ export const dynamic = 'force-dynamic'
import { redirect } from 'next/navigation'
import { getSession } from '@/features/community/lib/auth/server'
import { getUserProfile } from '@/features/community/lib/auth/actions'
import { getUserProfile, getConnectedAccounts } from '@/features/community/lib/auth/actions'
import { SettingsPage } from '@/features/community/components/settings-page'
export default async function Settings() {
@@ -11,7 +11,10 @@ export default async function Settings() {
redirect('/')
}
const profile = await getUserProfile()
const [profile, connectedAccounts] = await Promise.all([
getUserProfile(),
getConnectedAccounts(),
])
return (
<SettingsPage
@@ -19,6 +22,7 @@ export default async function Settings() {
currentUsername={profile?.username ?? null}
currentGithubUrl={profile?.githubUrl ?? null}
currentXUrl={profile?.xUrl ?? null}
connectedAccounts={connectedAccounts}
/>
)
}