Quick Start Guide

Welcome to the Fanvue API! In just 10 minutes, you’ll have a working Next.js application that securely fetches and displays your profile information using server-side API calls.

What is the Fanvue API?

The Fanvue API provides access to a powerful creator platform with these core capabilities:

  • User Management - Access profile information and account details
  • Chat Functionality - Build messaging features and manage conversations
  • Social Features - Handle followers, subscribers, and community interactions
  • Agency Tools - Manage creators and handle agency-related operations

Whether you’re building a custom dashboard, integrating with existing tools, or creating new experiences for creators and fans, our API has you covered.

What You’ll Build

In this tutorial, you’ll create a modern Next.js application that:

  • Securely connects to the Fanvue API using server-side authentication
  • Fetches your profile information through a backend API route
  • Displays your user details in a clean, responsive React interface
  • Handles loading states and errors gracefully
  • Follows security best practices by keeping API keys on the server

By the end, you’ll understand how to build secure API integrations, work with Next.js App Router, and create modern React applications.

Prerequisites

Before you start, make sure you have:

  • Basic knowledge of JavaScript and React
  • Node.js 18 or later installed on your computer (download here)
  • A terminal or command prompt
  • A text editor or IDE (VS Code recommended)
  • An API key from your Fanvue representative (contact them if you don’t have one yet)
  • API version “2025-06-26” (the current stable version used in this tutorial)

New to React or Next.js? Don’t worry! This tutorial includes detailed explanations for each step.

Step-by-Step Tutorial

Step 1: Create Your Next.js Project

First, let’s create a new Next.js project with all the modern features enabled. Open your terminal and run this command:

$npx create-next-app@latest fanvue-profile --typescript --tailwind --eslint --app

What’s happening here?

  • create-next-app@latest creates a new Next.js project with the latest version
  • fanvue-profile is the name of your project folder
  • --typescript enables TypeScript for better code quality and autocomplete
  • --tailwind includes Tailwind CSS for easy styling
  • --eslint adds ESLint for code linting and best practices
  • --app uses the modern App Router (instead of the older Pages Router)

When prompted, choose these options:

  • Would you like to use src/ directory? → No
  • Would you like to use App Router? → Yes (should be pre-selected)
  • Would you like to customize the default import alias? → No

After the installation completes (this may take a minute), navigate to your project:

$cd fanvue-profile

Let’s explore what was created: Your project now has this structure:

fanvue-profile/
├── app/ # App Router directory (this is where we'll work)
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout component
│ └── page.tsx # Home page component
├── public/ # Static assets
├── next.config.js # Next.js configuration
├── package.json # Dependencies and scripts
└── tailwind.config.ts # Tailwind CSS configuration

Step 2: Set Up Your API Key Securely

Now we need to configure your API key. Unlike client-side applications, Next.js allows us to store sensitive information securely on the server using environment variables.

Create a new file called .env.local in your project root (the same folder as package.json):

$touch .env.local

Open .env.local in your text editor and add your API key:

$FANVUE_API_KEY=YOUR_API_KEY_HERE
Security Note: - The .env.local file keeps your API key secure on the server - Never

commit this file to version control (it’s automatically ignored by Git) - Environment variables starting with NEXT_PUBLIC_ are exposed to the browser, but ours isn’t, so it stays private - Replace YOUR_API_KEY_HERE with your actual API key from your Fanvue representative

What’s happening here?

  • .env.local files are automatically loaded by Next.js
  • Your API key will be available as process.env.FANVUE_API_KEY in server-side code
  • This approach is much more secure than hardcoding keys in your source code

Step 3: Create a Server-Side API Route

Now we’ll create a server-side API route that securely calls the Fanvue API. This keeps your API key hidden from users and provides better security.

First, create the directory structure for your API route:

$mkdir -p app/api/profile

Now create the API route file app/api/profile/route.ts:

1import { NextRequest, NextResponse } from "next/server";
2
3export async function GET(request: NextRequest) {
4 try {
5 // Get the API key from environment variables
6 const apiKey = process.env.FANVUE_API_KEY;
7
8 if (!apiKey) {
9 return NextResponse.json({ error: "API key not configured" }, { status: 500 });
10 }
11
12 // Make the request to Fanvue API
13 const response = await fetch("https://api.fanvue.com/users/me", {
14 method: "GET",
15 headers: {
16 "X-Fanvue-API-Key": apiKey,
17 "X-Fanvue-API-Version": "2025-06-26",
18 "Content-Type": "application/json",
19 },
20 });
21
22 // Check if the request was successful
23 if (!response.ok) {
24 return NextResponse.json(
25 { error: `Fanvue API error: ${response.status} ${response.statusText}` },
26 { status: response.status }
27 );
28 }
29
30 // Parse and return the profile data
31 const profileData = await response.json();
32 return NextResponse.json(profileData);
33 } catch (error) {
34 console.error("Profile API error:", error);
35 return NextResponse.json({ error: "Failed to fetch profile" }, { status: 500 });
36 }
37}

What’s happening here?

  • We export a GET function that handles HTTP GET requests to /api/profile
  • The API key is securely accessed from process.env.FANVUE_API_KEY
  • We include the X-Fanvue-API-Version header to specify which version of the API to use
  • We make the request to Fanvue API server-to-server (more secure)
  • Error handling provides helpful feedback without exposing sensitive details
  • The response is returned as JSON that our frontend can consume

App Router API Routes:

  • Routes are defined by creating route.ts files in the app/api/ directory
  • The folder structure determines the URL path (app/api/profile/route.ts/api/profile)
  • Named exports (GET, POST, etc.) handle different HTTP methods

Step 4: Create the Profile Display Component

Now let’s create a React component that fetches and displays your profile data. We’ll replace the default content in app/page.tsx:

1'use client'
2
3import { useEffect, useState } from 'react'
4
5interface Profile {
6 uuid: string
7 email: string
8 handle: string
9}
10
11interface ApiError {
12 error: string
13}
14
15export default function ProfilePage() {
16 const [profile, setProfile] = useState<Profile | null>(null)
17 const [loading, setLoading] = useState(true)
18 const [error, setError] = useState<string | null>(null)
19
20 useEffect(() => {
21 async function fetchProfile() {
22 try {
23 const response = await fetch('/api/profile')
24
25 if (!response.ok) {
26 const errorData: ApiError = await response.json()
27 throw new Error(errorData.error || `HTTP ${response.status}`)
28 }
29
30 const profileData: Profile = await response.json()
31 setProfile(profileData)
32 } catch (err) {
33 setError(err instanceof Error ? err.message : 'Failed to fetch profile')
34 } finally {
35 setLoading(false)
36 }
37 }
38
39 fetchProfile()
40 }, [])
41
42 if (loading) {
43 return (
44 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
45 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
46 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
47 <p className="text-gray-600 italic">Loading your profile...</p>
48 </div>
49 </main>
50 )
51 }
52
53 if (error) {
54 return (
55 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
56 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
57 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
58 <div className="bg-red-50 border border-red-200 rounded-lg p-4">
59 <h3 className="text-red-800 font-semibold mb-2">Error Loading Profile</h3>
60 <p className="text-red-700">{error}</p>
61 <p className="text-red-600 text-sm mt-2">
62 Check the browser console for more details.
63 </p>
64 </div>
65 </div>
66 </main>
67 )
68 }
69
70 return (
71 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
72 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
73 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
74 {profile && (
75 <div className="space-y-4">
76 <h2 className="text-xl font-semibold text-gray-700">Profile Information</h2>
77 <div className="space-y-3">
78 <p>
79 <span className="font-medium text-gray-600">User ID:</span>{' '}
80 <span className="text-gray-800">{profile.uuid}</span>
81 </p>
82 <p>
83 <span className="font-medium text-gray-600">Email:</span>{' '}
84 <span className="text-gray-800">{profile.email}</span>
85 </p>
86 <p>
87 <span className="font-medium text-gray-600">Handle:</span>{' '}
88 <span className="text-gray-800">@{profile.handle}</span>
89 </p>
90 </div>
91 </div>
92 )}
93 </div>
94 </main>
95 )
96}

What’s happening here?

  • 'use client' directive marks this as a Client Component (needed for hooks and interactivity)
  • We use React hooks (useState, useEffect) to manage component state
  • TypeScript interfaces define the shape of our data for better type safety
  • useEffect runs when the component mounts to fetch the profile data
  • We call our local API route (/api/profile) instead of the external API directly
  • Tailwind CSS classes provide clean, responsive styling
  • Loading states and error handling give users clear feedback

React Hooks Explained:

  • useState manages component state (profile data, loading, errors)
  • useEffect handles side effects like API calls when the component loads
  • The dependency array [] means this effect runs once on mount

Step 5: Test Your Application

Now let’s start your Next.js development server and test your application!

  1. Start the development server:
$npm run dev

You should see output like:

▲ Next.js 14.0.0
- Local: http://localhost:3000
- Environments: .env.local
✓ Ready in 2.3s
  1. Open your application:

Visit http://localhost:3000 in your web browser.

  1. Check the results:

    • Success: You’ll see your profile information displayed in a clean card layout
    • Loading: You should briefly see “Loading your profile…” before data appears
    • Error: Any issues will be displayed in a red error box
  2. Troubleshooting common issues:

    • “API key not configured”:

      • Check that .env.local exists in your project root
      • Verify you’ve replaced YOUR_API_KEY_HERE with your actual API key
      • Restart the dev server (Ctrl+C then npm run dev again)
    • Port 3000 already in use:

      $npm run dev -- -p 3001
    • TypeScript errors:

      • Make sure you’re using .tsx extension for the page file
      • Check that all imports are correct
    • “Failed to fetch profile”:

      • Check your internet connection
      • Verify your API key is valid with your Fanvue representative
      • Check the browser’s Network tab (F12 → Network) for more details
    • Styles not loading:

      • Ensure Tailwind CSS was installed during project creation
      • Try refreshing the page

Development Tips:

  • The development server automatically reloads when you save files
  • Check the terminal where you ran npm run dev for server-side errors
  • Use browser DevTools (F12) to inspect client-side issues

Complete Working Example

Here’s your complete Next.js project structure with all the files you need:

Project Structure

fanvue-profile/
├── .env.local # Your API key (create this)
├── app/
│ ├── api/
│ │ └── profile/
│ │ └── route.ts # API route (create this)
│ ├── globals.css # Global styles (already exists)
│ ├── layout.tsx # Root layout (already exists)
│ └── page.tsx # Main page (replace existing)
├── next.config.js # Next.js config (already exists)
├── package.json # Dependencies (already exists)
└── tailwind.config.ts # Tailwind config (already exists)

.env.local

$FANVUE_API_KEY=YOUR_API_KEY_HERE

app/api/profile/route.ts

1import { NextRequest, NextResponse } from "next/server";
2
3export async function GET(request: NextRequest) {
4 try {
5 // Get the API key from environment variables
6 const apiKey = process.env.FANVUE_API_KEY;
7
8 if (!apiKey) {
9 return NextResponse.json({ error: "API key not configured" }, { status: 500 });
10 }
11
12 // Make the request to Fanvue API
13 const response = await fetch("https://api.fanvue.com/users/me", {
14 method: "GET",
15 headers: {
16 "X-Fanvue-API-Key": apiKey,
17 "X-Fanvue-API-Version": "2025-06-26",
18 "Content-Type": "application/json",
19 },
20 });
21
22 // Check if the request was successful
23 if (!response.ok) {
24 const errorText = await response.text();
25 return NextResponse.json(
26 { error: `Fanvue API error: ${response.status} ${response.statusText}` },
27 { status: response.status }
28 );
29 }
30
31 // Parse and return the profile data
32 const profileData = await response.json();
33 return NextResponse.json(profileData);
34 } catch (error) {
35 console.error("Profile API error:", error);
36 return NextResponse.json({ error: "Failed to fetch profile" }, { status: 500 });
37 }
38}

app/page.tsx

1'use client'
2
3import { useEffect, useState } from 'react'
4
5interface Profile {
6 uuid: string
7 email: string
8 handle: string
9}
10
11interface ApiError {
12 error: string
13}
14
15export default function ProfilePage() {
16 const [profile, setProfile] = useState<Profile | null>(null)
17 const [loading, setLoading] = useState(true)
18 const [error, setError] = useState<string | null>(null)
19
20 useEffect(() => {
21 async function fetchProfile() {
22 try {
23 const response = await fetch('/api/profile')
24
25 if (!response.ok) {
26 const errorData: ApiError = await response.json()
27 throw new Error(errorData.error || `HTTP ${response.status}`)
28 }
29
30 const profileData: Profile = await response.json()
31 setProfile(profileData)
32 } catch (err) {
33 setError(err instanceof Error ? err.message : 'Failed to fetch profile')
34 } finally {
35 setLoading(false)
36 }
37 }
38
39 fetchProfile()
40 }, [])
41
42 if (loading) {
43 return (
44 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
45 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
46 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
47 <p className="text-gray-600 italic">Loading your profile...</p>
48 </div>
49 </main>
50 )
51 }
52
53 if (error) {
54 return (
55 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
56 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
57 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
58 <div className="bg-red-50 border border-red-200 rounded-lg p-4">
59 <h3 className="text-red-800 font-semibold mb-2">Error Loading Profile</h3>
60 <p className="text-red-700">{error}</p>
61 <p className="text-red-600 text-sm mt-2">
62 Check the browser console for more details.
63 </p>
64 </div>
65 </div>
66 </main>
67 )
68 }
69
70 return (
71 <main className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
72 <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
73 <h1 className="text-2xl font-bold text-gray-800 mb-6">My Fanvue Profile</h1>
74 {profile && (
75 <div className="space-y-4">
76 <h2 className="text-xl font-semibold text-gray-700">Profile Information</h2>
77 <div className="space-y-3">
78 <p>
79 <span className="font-medium text-gray-600">User ID:</span>{' '}
80 <span className="text-gray-800">{profile.uuid}</span>
81 </p>
82 <p>
83 <span className="font-medium text-gray-600">Email:</span>{' '}
84 <span className="text-gray-800">{profile.email}</span>
85 </p>
86 <p>
87 <span className="font-medium text-gray-600">Handle:</span>{' '}
88 <span className="text-gray-800">@{profile.handle}</span>
89 </p>
90 </div>
91 </div>
92 )}
93 </div>
94 </main>
95 )
96}

Quick Setup Commands:

$# Create the project
>npx create-next-app@latest fanvue-profile --typescript --tailwind --eslint --app
>cd fanvue-profile
>
># Create the API route directory
>mkdir -p app/api/profile
>
># Create and edit your files
>touch .env.local
># Then add your API key to .env.local
># Replace the contents of app/page.tsx
># Create app/api/profile/route.ts
>
># Start the development server
>npm run dev

Congratulations!

You’ve successfully built your first Fanvue API integration using modern Next.js! You now understand:

  • Server-side API Security: How to keep API keys secure using environment variables and server-side routes
  • Next.js App Router: How to create API routes and React components using the latest Next.js features
  • TypeScript Integration: How to use TypeScript for better code quality and developer experience
  • Modern React Patterns: How to manage state, handle loading states, and display data with hooks
  • Error Handling: How to gracefully handle and display errors in both client and server code

Next Steps

Ready to build more advanced features? Here are some Next.js-specific ideas to extend your application:

Intermediate Features

  • Server Components: Convert some parts to Server Components for better performance
  • Streaming & Suspense: Add streaming responses for better perceived performance
  • Middleware: Add API middleware for request logging and rate limiting
  • Custom Hooks: Extract your API logic into reusable custom hooks

Advanced Features

  • Next.js Caching: Implement caching strategies for your API responses
  • Real-time Updates: Add WebSocket support for live profile updates
  • Static Generation: Pre-build profile pages at build time using ISR
  • Edge Runtime: Deploy your API routes to the edge for global performance

API Exploration

  • Chat Integration: Build a messaging interface using the chat endpoints
  • Follower Management: Create components for follower/following relationships
  • File Upload: Add profile image upload capabilities
  • Pagination: Implement paginated lists for followers, chats, etc.

Production Readiness

  • Error Boundaries: Add React error boundaries for better error handling
  • Loading Skeletons: Create skeleton screens for better UX
  • SEO Optimization: Add proper meta tags and structured data
  • Performance Monitoring: Integrate analytics and performance tracking

Check out our other documentation sections to learn about:

  • API Scopes - Understanding permissions and access levels
  • Rate Limits - Managing your API usage effectively

Next.js Resources:

Happy coding! 🚀