Skip to content

Conversation

@atharvadeosthale
Copy link
Member

@atharvadeosthale atharvadeosthale commented Jan 14, 2026

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive new blog post on Next.js best practices and architectural patterns, distinguishing it from plain React usage.
    • Includes detailed explanations of server vs. client components, authentication workflows, route protection, Appwrite integration examples, server-side rendering techniques, and practical code samples with curated resources.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

Walkthrough

A new blog post file was added at src/routes/blog/post/using-nextjs-wrong/+page.markdoc containing a Markdoc article with front-matter metadata (layout, title, description, date, author, category, featured status) and instructional content. The article provides guidance on proper Next.js usage, contrasting it with plain React, covering server components, server-side rendering, Appwrite integration patterns, and route protection. The content includes code examples demonstrating client vs. server components, authentication flows, and conditional SSR implementation, concluding with links to relevant documentation resources.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~4 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the main change in the pull request, which adds a new blog article about common Next.js usage mistakes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/routes/blog/post/using-nextjs-wrong/`+page.markdoc:
- Around line 77-90: The Products component destructures `{ databases }` from
createAdminClient() but the factory actually returns `{ tablesDB, account }`,
causing a runtime error; update Products to destructure `{ tablesDB }` (or
change the factory to return `databases`) and call `tablesDB.listRows(...)`
instead of `databases.listRows(...)`, and also add the missing `Query` import
(e.g., import { Query } from "appwrite") so `Query.equal()` is defined; ensure
you reference the existing createAdminClient, Products, tablesDB/databases, and
Query symbols when making the change.
- Around line 102-118: The import of cookies is currently placed alongside
createAdminClient where it isn't used; remove the unused import from the file
top and add/import cookies only where createSessionClient is defined/used so the
createAdminClient function (and its imports: Client, TablesDB, Account,
createAdminClient) shows only the dependencies it needs and createSessionClient
has the cookies import available; update the second code block to include
cookies and delete it from the first to improve clarity.
🧹 Nitpick comments (1)
src/routes/blog/post/using-nextjs-wrong/+page.markdoc (1)

146-179: Good security practices, consider adding error handling.

The authentication implementation correctly uses secure cookie settings (httpOnly, secure, sameSite) and appropriate session expiration. Using the admin client for login is correct since the user isn't authenticated yet.

Consider adding error handling to provide user feedback when authentication fails, though omitting it for brevity in a tutorial is acceptable.

Optional enhancement: Add error handling
export default function LoginPage() {
  async function login(formData: FormData) {
    "use server";
    try {
      const { account } = await createAdminClient();
      const session = await account.createEmailPasswordSession(
        formData.get("email") as string,
        formData.get("password") as string
      );

      (await cookies()).set("session", session.secret, {
        httpOnly: true,
        secure: true,
        sameSite: "strict",
        expires: new Date(session.expire),
      });

      redirect("/");
    } catch (error) {
      // Handle authentication errors
      return { error: "Invalid credentials" };
    }
  }
  // ... rest of component
}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73bdc62 and c199e4e.

📒 Files selected for processing (1)
  • src/routes/blog/post/using-nextjs-wrong/+page.markdoc
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2372
File: src/routes/docs/tutorials/react/step-6/+page.markdoc:70-75
Timestamp: 2025-09-05T19:35:53.943Z
Learning: In React tutorial files, the correct Appwrite database instance to import is `tablesDB` from "../appwrite", not `databases`. The import statement should be `import { tablesDB } from "../appwrite"` to match the usage throughout the React tutorial code.
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2573
File: src/lib/utils/blog-mid-cta.ts:49-60
Timestamp: 2025-11-06T19:20:26.393Z
Learning: In the appwrite/website repository's blog system, markdown headings use a custom level mapping where single `#` translates to H2 (section heading) rather than the standard H1. The regex pattern `^(?:\s{0,3})#\s+.+$/gm` is used to match these section headings correctly in `src/lib/utils/blog-mid-cta.ts`.
📚 Learning: 2025-11-06T19:20:26.393Z
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2573
File: src/lib/utils/blog-mid-cta.ts:49-60
Timestamp: 2025-11-06T19:20:26.393Z
Learning: In the appwrite/website repository's blog system, markdown headings use a custom level mapping where single `#` translates to H2 (section heading) rather than the standard H1. The regex pattern `^(?:\s{0,3})#\s+.+$/gm` is used to match these section headings correctly in `src/lib/utils/blog-mid-cta.ts`.

Applied to files:

  • src/routes/blog/post/using-nextjs-wrong/+page.markdoc
📚 Learning: 2025-11-18T21:53:20.905Z
Learnt from: atharvadeosthale
Repo: appwrite/website PR: 2614
File: src/routes/docs/products/sites/one-click-deployment/+page.markdoc:74-122
Timestamp: 2025-11-18T21:53:20.905Z
Learning: Appwrite Sites one-click deployment supports the following framework presets: Analog (analog), Angular (angular), Next.js (nextjs), React (react), Nuxt (nuxt), Vue (vue), SvelteKit (sveltekit), Astro (astro), TanStack Start (tanstack-start), Remix (remix), Lynx (lynx), Flutter (flutter), React Native (react-native), Vite (vite), and Other (other).

Applied to files:

  • src/routes/blog/post/using-nextjs-wrong/+page.markdoc
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: tests
  • GitHub Check: build
  • GitHub Check: assets
🔇 Additional comments (4)
src/routes/blog/post/using-nextjs-wrong/+page.markdoc (4)

122-138: LGTM!

The session client factory correctly retrieves the session cookie and conditionally sets it on the client. The pattern of returning tablesDB and account is consistent with the admin client factory.


183-198: LGTM!

The protected layout correctly uses the session client to verify authentication and redirects unauthenticated users. The try-catch pattern appropriately handles invalid or missing sessions.


213-214: Both documentation links are valid and current.

The internal link to /docs/products/auth/server-side-rendering exists in the repository structure, and the Next.js App Router documentation link https://nextjs.org/docs/app is accessible and current as of July 2025.


49-73: Replace collectionId with tableId and add missing Query import.

Line 60 uses the wrong parameter name: collectionId should be tableId to match the Appwrite TablesDB API. Additionally, the Query used on line 64 needs to be imported (likely from "@appwrite/client" or similar).

Corrected example:
import { databases } from "@/lib/appwrite";
import { Query } from "@appwrite/client";

databases
  .listRows({
    databaseId: DATABASE_ID,
    tableId: TABLE_ID,  // Changed from collectionId
    queries: [Query.equal("status", "active")],
  })
⛔ Skipped due to learnings
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2372
File: src/routes/docs/tutorials/react/step-6/+page.markdoc:70-75
Timestamp: 2025-09-05T19:35:53.943Z
Learning: In React tutorial files, the correct Appwrite database instance to import is `tablesDB` from "../appwrite", not `databases`. The import statement should be `import { tablesDB } from "../appwrite"` to match the usage throughout the React tutorial code.
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2372
File: src/routes/docs/tutorials/nuxt/step-6/+page.markdoc:79-83
Timestamp: 2025-09-05T19:35:04.162Z
Learning: In Nuxt tutorial files, the correct Appwrite database instance to use is `tablesDB` (imported from "~/appwrite"), not `database`. All tablesDB method calls should use the object parameter format: listRows({ databaseId, tableId, queries }), createRow({ databaseId, tableId, rowId, data }), and deleteRow({ databaseId, tableId, rowId }).
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2372
File: src/routes/docs/tutorials/react-native/step-6/+page.markdoc:67-73
Timestamp: 2025-09-05T19:35:59.449Z
Learning: In React Native tutorials, the lib/appwrite.js file exports `tablesDB` (not `databases`), so imports should use `import { tablesDB } from "../lib/appwrite"` to match the export pattern established in step-3.
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2372
File: src/routes/docs/tutorials/react-native/step-6/+page.markdoc:67-73
Timestamp: 2025-09-05T19:35:59.449Z
Learning: In React Native tutorials, the lib/appwrite.js file exports `tablesDB` (not `databases`), so imports should use `import { tablesDB } from "../lib/appwrite"` to match the export pattern established in step-3.
Learnt from: ebenezerdon
Repo: appwrite/website PR: 2573
File: src/lib/utils/blog-mid-cta.ts:49-60
Timestamp: 2025-11-06T19:20:26.393Z
Learning: In the appwrite/website repository's blog system, markdown headings use a custom level mapping where single `#` translates to H2 (section heading) rather than the standard H1. The regex pattern `^(?:\s{0,3})#\s+.+$/gm` is used to match these section headings correctly in `src/lib/utils/blog-mid-cta.ts`.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +77 to +90
```jsx
import { createAdminClient } from "@/lib/appwrite/server";

export default async function Products() {
const { databases } = await createAdminClient();
const { rows } = await databases.listRows({
databaseId: DATABASE_ID,
collectionId: COLLECTION_ID,
queries: [Query.equal("status", "active")],
});

return <ProductGrid products={rows} />;
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix inconsistent property name between factory and usage.

Line 81 destructures { databases } from createAdminClient(), but the factory definition at lines 102-118 returns { tablesDB, account }, not { databases }. This mismatch will cause a runtime error.

Additionally, line 85 uses Query.equal() without showing the import statement.

🐛 Proposed fix
-import { createAdminClient } from "@/lib/appwrite/server";
+import { createAdminClient } from "@/lib/appwrite/server";
+import { Query } from "node-appwrite";

 export default async function Products() {
-  const { databases } = await createAdminClient();
-  const { rows } = await databases.listRows({
+  const { tablesDB } = await createAdminClient();
+  const { rows } = await tablesDB.listRows({
     databaseId: DATABASE_ID,
     collectionId: COLLECTION_ID,
     queries: [Query.equal("status", "active")],
   });

   return <ProductGrid products={rows} />;
 }
🤖 Prompt for AI Agents
In `@src/routes/blog/post/using-nextjs-wrong/`+page.markdoc around lines 77 - 90,
The Products component destructures `{ databases }` from createAdminClient() but
the factory actually returns `{ tablesDB, account }`, causing a runtime error;
update Products to destructure `{ tablesDB }` (or change the factory to return
`databases`) and call `tablesDB.listRows(...)` instead of
`databases.listRows(...)`, and also add the missing `Query` import (e.g., import
{ Query } from "appwrite") so `Query.equal()` is defined; ensure you reference
the existing createAdminClient, Products, tablesDB/databases, and Query symbols
when making the change.

Comment on lines +102 to +118
```ts
// lib/appwrite/server.ts
import { Client, TablesDB, Account } from "node-appwrite";
import { cookies } from "next/headers";

export async function createAdminClient() {
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT)
.setProject(process.env.APPWRITE_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);

return {
tablesDB: new TablesDB(client),
account: new Account(client),
};
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd "using-nextjs-wrong" --type f

Repository: appwrite/website

Length of output: 42


🌐 Web query:

node-appwrite package TablesDB class API documentation

💡 Result:

The Node Appwrite TablesDB API docs (Node.js SDK) are in the Appwrite reference: it documents the TablesDB class and methods (listTables, getTable, createTable, createRow(s), getRow, listRows, updateRow/upsertRow, deleteRows, indexes, transactions, etc.). See the server-side Node.js TablesDB reference. [1]

If you need the SDK package details or to confirm which node-appwrite version contains TablesDB (some older releases lack it), check the node-appwrite npm / package page. Upgrade to a recent node-appwrite release if you get missing-export errors. [2]

Sources:

  • Appwrite TablesDB Node.js reference. [1]
  • node-appwrite package (npm / package info). [2]

🏁 Script executed:

rg "using-nextjs-wrong" --type md

Repository: appwrite/website

Length of output: 42


🏁 Script executed:

rg "createAdminClient" --type md --type ts -B 2 -A 20

Repository: appwrite/website

Length of output: 42


🏁 Script executed:

fd "page.markdoc" src/routes/blog/post --type f | head -20

Repository: appwrite/website

Length of output: 1369


🏁 Script executed:

ls -la src/routes/blog/post/ 2>/dev/null | head -30

Repository: appwrite/website

Length of output: 2395


🏁 Script executed:

rg "TablesDB" --type md --type ts -B 2 -A 5

Repository: appwrite/website

Length of output: 2649


🏁 Script executed:

fd "next" src/routes/blog/post --type d

Repository: appwrite/website

Length of output: 512


🏁 Script executed:

rg "node-appwrite" src/routes/blog --type md | head -20

Repository: appwrite/website

Length of output: 42


🏁 Script executed:

rg "createAdminClient\|createSessionClient" src/routes/blog --type md

Repository: appwrite/website

Length of output: 42


🏁 Script executed:

cat -n "src/routes/blog/post/using-nextjs-wrong/+page.markdoc" | sed -n '90,130p'

Repository: appwrite/website

Length of output: 1409


🏁 Script executed:

wc -l "src/routes/blog/post/using-nextjs-wrong/+page.markdoc"

Repository: appwrite/website

Length of output: 117


🏁 Script executed:

cat -n "src/routes/blog/post/using-nextjs-wrong/+page.markdoc" | sed -n '102,180p'

Repository: appwrite/website

Length of output: 2623


Move cookies import to improve code clarity in tutorial.

The cookies import on line 105 is not used in the createAdminClient() function (lines 107–117) but is required in createSessionClient() (line 128). Moving it to the second code block improves readability for tutorial readers by avoiding the appearance of unused imports.

♻️ Proposed fix

First code block (lines 102–118):

 // lib/appwrite/server.ts
-import { Client, TablesDB, Account } from "node-appwrite";
-import { cookies } from "next/headers";
+import { Client, TablesDB, Account } from "node-appwrite";

 export async function createAdminClient() {

Second code block (lines 122–138):

+import { cookies } from "next/headers";
+
 export async function createSessionClient() {
🤖 Prompt for AI Agents
In `@src/routes/blog/post/using-nextjs-wrong/`+page.markdoc around lines 102 -
118, The import of cookies is currently placed alongside createAdminClient where
it isn't used; remove the unused import from the file top and add/import cookies
only where createSessionClient is defined/used so the createAdminClient function
(and its imports: Client, TablesDB, Account, createAdminClient) shows only the
dependencies it needs and createSessionClient has the cookies import available;
update the second code block to include cookies and delete it from the first to
improve clarity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants