Frontend Integration with Encore Instructions
Encore provides tools to connect your frontend applications to your backend APIs.
Generate a TypeScript Client
Generate client for local development
encore gen client --output=./frontend/src/client.ts --env=local
Generate client for a deployed environment
encore gen client --output=./frontend/src/client.ts --env=staging
This generates a fully typed client based on your API definitions.
Using the Generated Client // frontend/src/client.ts is auto-generated import Client from "./client";
const client = new Client("http://localhost:4000");
// Fully typed API calls const user = await client.user.getUser({ id: "123" }); console.log(user.email);
const newUser = await client.user.createUser({ email: "new@example.com", name: "New User", });
React Example // frontend/src/components/UserProfile.tsx import { useState, useEffect } from "react"; import Client from "../client";
const client = new Client(import.meta.env.VITE_API_URL);
export function UserProfile({ userId }: { userId: string }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);
useEffect(() => { client.user.getUser({ id: userId }) .then(setUser) .catch(setError) .finally(() => setLoading(false)); }, [userId]);
if (loading) return
return (
{user.name}
{user.email}
React with TanStack Query import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import Client from "../client";
const client = new Client(import.meta.env.VITE_API_URL);
export function UserProfile({ userId }: { userId: string }) { const { data: user, isLoading, error } = useQuery({ queryKey: ["user", userId], queryFn: () => client.user.getUser({ id: userId }), });
if (isLoading) return
return
export function CreateUserForm() { const queryClient = useQueryClient();
const mutation = useMutation({ mutationFn: (data: { email: string; name: string }) => client.user.createUser(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["users"] }); }, });
const handleSubmit = (e: React.FormEvent
return (
); }Next.js Server Components // app/users/[id]/page.tsx import Client from "@/lib/client";
const client = new Client(process.env.API_URL);
export default async function UserPage({ params }: { params: { id: string } }) { const user = await client.user.getUser({ id: params.id });
return (
{user.name}
{user.email}
CORS Configuration
Configure CORS in your encore.app file:
{ "id": "my-app", "global_cors": { "allow_origins_with_credentials": [ "http://localhost:3000", "https://myapp.com", "https://*.myapp.com" ] } }
CORS Options Option Description allow_origins_without_credentials Origins allowed for non-credentialed requests (default: ["*"]) allow_origins_with_credentials Origins allowed for credentialed requests (cookies, auth headers) allow_headers Additional request headers to allow expose_headers Additional response headers to expose debug Enable CORS debug logging Authentication from Frontend // With the generated client const client = new Client("http://localhost:4000");
// Set auth token client.setAuthToken(userToken);
// Now all requests include the Authorization header const profile = await client.user.getProfile();
Or manually with fetch:
const response = await fetch("http://localhost:4000/profile", {
headers: {
"Authorization": Bearer ${token},
},
});
Using Plain Fetch
If you prefer not to use the generated client:
async function getUser(id: string) {
const response = await fetch(http://localhost:4000/users/${id});
if (!response.ok) {
throw new Error(HTTP error: ${response.status});
}
return response.json();
}
async function createUser(email: string, name: string) {
const response = await fetch("http://localhost:4000/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, name }),
});
if (!response.ok) {
throw new Error(HTTP error: ${response.status});
}
return response.json();
}
Environment Variables
.env.local (Next.js)
NEXT_PUBLIC_API_URL=http://localhost:4000
.env (Vite)
VITE_API_URL=http://localhost:4000
Guidelines Use encore gen client to generate typed API clients Regenerate the client when your API changes Configure CORS in encore.app for production domains Use allow_origins_with_credentials for authenticated requests Set auth tokens on the client for protected endpoints Use environment variables for API URLs (different per environment) The generated client handles errors and types automatically