A Next.js (App Router) starter integrated with Appwrite for authentication and data. This repository demonstrates client-side Appwrite usage, session handling, and a Tailwind-based UI.
- Features
- Prerequisites
- Installation
- Environment variables
- Running the app
- Project structure
- Authentication flow
- Common pitfalls & troubleshooting
- Contributing
- License
- Next.js (App Router) application
- Appwrite Cloud authentication (email/password, verification)
- React Context
AuthProviderfor global auth state - Client-only Appwrite SDK usage where required (prevents build-time failures)
- Tailwind CSS utilities (DaisyUI optional)
- Toast notifications via
react-toastify
- Node.js 18+ (match Appwrite Sites runtime if deploying)
- npm
- Appwrite Cloud project (project id and endpoint)
- Clone the repository
git clone https://github.com/jamesAllenJahner3rd/eldarlands.git
cd eldarlands- Install dependencies
npm install-
Create a
.env.local(see below) and configure Appwrite values. -
Run the dev server
npm run devCreate .env.local in the project root and add:
NEXT_PUBLIC_APPWRITE_PROJECT_ID = 68bb084a0032b02608c4
NEXT_PUBLIC_APPWRITE_BUCKET = 68c11c240013701075bb
NEXT_PUBLIC_APPWRITE_PROJECT_NAME = "EldarLandsLARP"
NEXT_PUBLIC_APPWRITE_ENDPOINT = "https://nyc.cloud.appwrite.io/v1"
NEXT_PUBLIC_APPWRITE_DATABASE_ID = 68c1160a001638ade3a0
NEXT_PUBLIC_ROOT_URL ="http://localhost:3000"Notes:
- Use
NEXT_PUBLIC_prefix for variables that must be available in the browser. - For Appwrite Cloud use
https://cloud.appwrite.io/v1. Region-specific UI endpoints (e.g.nyc.cloud.appwrite.io) are for the dashboard and may not work as client endpoints.
- Development:
npm run dev - Build:
npm run build - Start (production):
npm start
When deploying to Appwrite Sites, set the Build runtime to Node 18 and use npm run build as your build command and .next as the output directory.
src/
├── app/
│ ├── layout.tsx # Root layout: imports globals, mounts AuthProvider, ToastContainer
│ ├── page.tsx # Public home page
│ ├── login/page.tsx # Client login page
│ ├── register/page.tsx # Client registration + verification flow
│ ├── explore/page.tsx # Lore exploration UI
│ ├── resources/page.tsx # Resource hub (docs, links, etc.)
│ └── providers/
│ └── AuthProvider.tsx # Global auth context
├── components/ # Reusable UI components (not expanded here)
├── lib/
│ └── appwrite.ts # Appwrite client helper (client-only where needed)
├── pages/ # Legacy Next.js routing (may be phased out)
│ ├── index.tsx # Entry point fallback
│ ├── page.tsx # Redundant with `app/page.tsx`?
│ ├── api/ # API route handlers
│ ├── favicon.ico # App icon
│ ├── app.css # Legacy styles
│ ├── globals.css # Global styles
├── ts/ # TypeScript build artifacts
│ └── tsconfig.buildinfo
public/ # Static assets
.env.example # Safe-to-share env scaffold
README.md # Project overview and onboarding
- Client login/registration: create sessions from the browser using the Appwrite SDK (e.g.
account.createEmailPasswordSession) so Appwrite returns a Set-Cookie that the browser stores. - After session creation, call
account.get()from the client to hydrate full user data and updateAuthProvider. - Avoid creating sessions in server actions unless you proxy Appwrite's Set-Cookie header to the browser via a custom API route.
Recommended pattern for login (client-side):
await account.createEmailPasswordSession(email, password)const me = await account.get()setUser(me)inAuthProviderand redirect
Verification: send verification via account.createVerification({ url: "${NEXT_PUBLIC_ROOT_URL}/register/verify" }).
-
"window is not defined" / build-time Appwrite errors
- Do not instantiate Appwrite SDK at module scope for server-rendered code. Import/instantiate inside
useEffector in client-only modules.
- Do not instantiate Appwrite SDK at module scope for server-rendered code. Import/instantiate inside
-
Sessions created on server but not in browser
- Server-side session creation sets cookies for the server process, not the browser. Create sessions in browser or proxy Set-Cookie to client.
-
Tailwind utilities appear as raw class names in DOM (e.g.
bg-blue-500with no styles)- Ensure PostCSS is configured with
tailwindcssandautoprefixer,globals.cssincludes Tailwind directives (or your build pipeline generates Tailwind properly), andtailwind.configcontent paths includesrc/app/**/*andsrc/components/**/*.
- Ensure PostCSS is configured with
-
react-toastifytoasts not visible- Import
react-toastify/dist/ReactToastify.cssonce (recommended inlayout.tsx) and mount a single<ToastContainer />at the app root to persist across route changes.
- Import
-
Null
userin componentsAuthProviderinitial state isnulluntilaccount.get()resolves. Always guard access touser(user?.name) and consider a small loading state while auth hydrates.
- Open an issue or submit a PR. Please document breaking changes and keep API expectations (Appwrite SDK versions) noted in
package.json.
© 2025 James Jahner