Set up the frontend
Learn how to set up the frontend of a Weave.js app on Next.js
In this guide, you will learn how to set up the frontend of a collaborative application using Weave.js and Next.js.
To build the collaborative canvas interface, you will create two pages:
- Enter room page: Let users indicate the room name or ID and a username to join a collaboration room.
- Room page: Handles the UI for the collaboration room after a user joins.
Opinionated tools
This guide uses some opinionated tools and libraries (like shadcn/ui for UI components) to demonstrate the integration. Adapt or replace these tools to match your project's needs and preferences.
Prerequisites
Before you begin, ensure that you have completed the backend installation guide.
Step by step
To set up Weave.js frontend over our Next.js project (on a single artifact), follow these steps:
Install the Weave.js frontend dependencies
From the project root folder, install the Weave.js frontend dependencies:
npm install @inditextech/weave-reactThis example uses the Weave.js React wrapper.
Install the additional frontend dependencies
From the project root, install supporting frontend libraries:
npm install boring-avatars class-variance-authority clsx @hookform/resolvers lucide-react react-hook-form tailwindcss-animate tailwind-merge @tanstack/react-query zodThese packages provide auxiliary functionality such as:
-
Form handling:
react-hook-form,@hookform/resolvers,zod -
UI utilities:
clsx,class-variance-authority,tailwind-merge,tailwindcss-animate -
Icons and avatars:
lucide-react,boring-avatars -
State management:
@tanstack/react-query
Set up a global state store for the UI
Create a global state store to handle the UI state. This store manages the current user, room ID, and UI visibility state across the application. Use Zustand for this.
-
Install the Zustand dependency:
npm install zustand -
Create a
store/store.tsfile in the project root folder and set its content to:store/store.ts import { create } from "zustand"; type ShowcaseUser = { id: string; name: string; email: string; }; interface CollaborationRoomState { ui: { show: boolean; }; user: ShowcaseUser | undefined; room: string | undefined; setShowUi: (newShowUI: boolean) => void; setUser: (newUser: ShowcaseUser | undefined) => void; setRoom: (newRoom: string | undefined) => void; } export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({ ui: { show: true, }, user: undefined, room: undefined, setShowUi: (newShowUI) => set((state) => ({ ...state, ui: { ...state.ui, show: newShowUI }, })), setUser: (newUser) => set((state) => ({ ...state, user: newUser })), setRoom: (newRoom) => set((state) => ({ ...state, room: newRoom })), }));
Configure utility functions
Create a lib/utils.ts file in the project root folder to provide utility functions used throughout the UI components.
Create the file with the following content:
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function getContrastTextColor(hex: string): "white" | "black" {
// Remove "#" if present
const cleaned = hex.replace(/^#/, "");
// Parse R, G, B from hex
const r = parseInt(cleaned.slice(0, 2), 16);
const g = parseInt(cleaned.slice(2, 4), 16);
const b = parseInt(cleaned.slice(4, 6), 16);
// Calculate luminance (per W3C)
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
// Return black for light colors, white for dark
return luminance > 0.5 ? "black" : "white";
}
export function stringToColor(str: string) {
let hash = 0;
str.split("").forEach((char) => {
hash = char.charCodeAt(0) + ((hash << 5) - hash);
});
let color = "#";
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 0xff;
color += value.toString(16).padStart(2, "0");
}
return color;
}This file includes:
-
cnfunction: Merges Tailwind CSS class names with proper conflict resolution usingclsxandtailwind-merge. This ensures that when you combine multiple class strings, conflicting Tailwind utilities are resolved correctly (e.g.,p-4andp-2will result inp-2). -
getContrastTextColorfunction: Determines whether white or black text provides better contrast against a given hex color background. It calculates the relative luminance of the color using the W3C standard formula and returns the appropriate text color for readability. -
stringToColorfunction: Generates a consistent hex color from any string input using a hash function. This is useful for creating deterministic color assignments (like avatar backgrounds) based on user names or other identifiers.
Set up the Enter Room page
With the global state store in place, create the Enter Room page.
Set up the Room page
Now that the Enter Room page is set up, create the Room page.
Next steps
Finally, run the project.
