-
Notifications
You must be signed in to change notification settings - Fork 9
Updated for Vue 3 and Appwrite 1.8.0 #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Refactoring of this code example for Vue and Appwrite latest runtimes - Rewriting the README file according to updated JS framework and the updated backend versions, including new screenshots files - Adding .env file to appy modern good practice of credential management
WalkthroughThis pull request migrates the example-database project from Vue 2 with Vue CLI to Vue 3 with Vite, including a comprehensive shift to the Composition API pattern. Changes span build tooling (package.json, new vite.config.js, removed babel.config.js), component APIs (App.vue and Task.vue rewritten with script setup and composition hooks), SDK initialization (utils.js refactored to modularize Appwrite client, account, and database instances), environment configuration (new secrets.js for environment variable management), project configuration (jsconfig.json added, HTML entry point restructured from public/index.html to root index.html), and documentation (README significantly rewritten to reflect Vue 3 patterns). Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (4)
example-database/src/utils.js (1)
5-5: Remove debug console.log statement.Debug logging should be removed before merging to production code.
Apply this diff:
// Configure client (using env vars) -console.log("SECRETS.DB = ",SECRETS.DB) const client = new Client()example-database/README.md (1)
107-112: Specify language for fenced code block.The fenced code block should specify a language identifier for proper syntax highlighting.
Apply this diff:
-``` +```env VITE_DB_ENDPOINT='<YOUR OWN APPWRITE ENDPOINT>' VITE_DB_PROJECTID='<YOUR OWN APPWRITE PROJECTID>' VITE_DB_DATABASEID='<YOUR OWN APPWRITE DATABASEID>' VITE_DB_TABLENAME='<YOUR OWN APPWRITE TABLE NAME>'</blockquote></details> <details> <summary>example-database/src/App.vue (2)</summary><blockquote> `8-8`: **Use consistent event handler shorthand.** Line 8 uses `v-on:click.prevent` while the rest of the codebase uses the `@click` shorthand. Consider using `@click.prevent` for consistency. Apply this diff: ```diff - <button v-on:click.prevent="createNewTask"><span>+</span></button> + <button @click.prevent="createNewTask"><span>+</span></button>
24-34: Use consistent error logging.Line 32 uses
console.log(error)whilecreateNewTaskon line 54 usesconsole.error. For consistency and proper error level logging, useconsole.errorhere as well.Apply this diff:
} catch (error) { - console.log(error) + console.error(error) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (11)
example-database/src/assets/logo.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/1.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/2.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/3.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/4.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/5.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/6.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/7.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/8.pngis excluded by!**/*.pngexample-database/tutorial-resources/images/9.pngis excluded by!**/*.pngexample-database/yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (13)
example-database/.gitignore(1 hunks)example-database/README.md(1 hunks)example-database/babel.config.js(0 hunks)example-database/index.html(1 hunks)example-database/jsconfig.json(1 hunks)example-database/package.json(1 hunks)example-database/public/index.html(0 hunks)example-database/src/App.vue(1 hunks)example-database/src/components/Task.vue(1 hunks)example-database/src/main.js(1 hunks)example-database/src/secrets.js(1 hunks)example-database/src/utils.js(1 hunks)example-database/vite.config.js(1 hunks)
💤 Files with no reviewable changes (2)
- example-database/public/index.html
- example-database/babel.config.js
🧰 Additional context used
🧬 Code graph analysis (1)
example-database/src/utils.js (1)
example-database/src/secrets.js (2)
SECRETS(2-9)SECRETS(2-9)
🪛 LanguageTool
example-database/README.md
[style] ~57-~57: ‘In order for us to’ might be wordy. Consider a shorter alternative.
Context: ...# Preparing data on Appwrite backend
In order for us to create this to-do app we need a place t...
(EN_WORDINESS_PREMIUM_IN_ORDER_FOR_US_TO)
[style] ~94-~94: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...sources/images/7.png)
Finally, we are going to allow read, write, update access to *an...
(REP_GOING_TO_VB)
[style] ~341-~341: Consider a more concise word here.
Context: ... ! You should now have enough knowledge in order to use Databases with Appwrite and VueJS a...
(IN_ORDER_TO_PREMIUM)
🪛 markdownlint-cli2 (0.18.1)
example-database/README.md
107-107: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (15)
example-database/.gitignore (1)
17-17: LGTM!Adding
.code-workspaceto the ignore list is appropriate for keeping VSCode workspace files out of version control.example-database/src/main.js (1)
1-4: LGTM!The Vue 3 migration pattern is correct: using
createApp()instead ofnew Vue()and removing the deprecatedproductionTipconfiguration.example-database/jsconfig.json (1)
1-8: LGTM!The path alias configuration aligns with the Vite setup and provides proper IDE support for the
@/*import pattern.example-database/vite.config.js (1)
1-18: LGTM!Standard Vite configuration for Vue 3 with appropriate plugins and path alias setup that aligns with the jsconfig.json configuration.
example-database/src/utils.js (1)
1-21: Appwrite SDK refactoring verified—all usages are correct.Verification confirmed that all components across the codebase use the correct property names (
appwrite.accountandappwrite.database). No instances of the incorrect plural form (appwrite.databases) were found, and no old-style Appwrite imports remain. The modular structure in utils.js is properly implemented and consistently used throughout the application.example-database/package.json (1)
6-8: Node.js engine constraint is correct.The constraint
"^20.19.0 || >=22.12.0"aligns exactly with Vite 7's minimum Node.js requirement. Current LTS (v24) and stable (v25) releases are both covered by this constraint. Vue 3.5 has no special Node.js runtime requirement. No changes needed.example-database/src/components/Task.vue (4)
1-6: LGTM! Event modifiers and template structure are correct.The template correctly uses
@click.selfto ensure the done toggle only fires when clicking the specific element (not its children) and@click.stopto prevent event propagation when deleting. The dynamic class binding for the done state works well with the optimistic UI pattern.
8-16: LGTM! Composition API setup is well-structured.The imports, props, and emits are correctly defined using Vue 3's
<script setup>syntax. The explicit.jsfile extensions align with Vite/ES module conventions.
26-37: LGTM! Delete operation is correctly implemented.The function properly handles the delete operation with error handling and emits the refresh event to trigger a parent data re-fetch. The error is logged for debugging purposes.
39-57: Excellent optimistic UI implementation!The function correctly implements an optimistic UI pattern by immediately updating the local state, then reverting it if the API call fails. This provides responsive user feedback while maintaining data consistency.
example-database/README.md (2)
174-174: Good educational comment about transactions.The inline comment explaining when to use transactions is helpful and includes a documentation link. This adds value for developers learning the Appwrite SDK.
1-345: Comprehensive documentation with clear step-by-step instructions.The README effectively documents the Vue 3 migration and Appwrite 1.8.0 integration. The tutorial includes code examples that match the actual implementation, screenshots for UI guidance, and helpful notes about differences from previous Appwrite versions.
example-database/src/App.vue (3)
13-22: LGTM! Imports and state setup are correct.The imports use explicit file extensions as required by Vite/ES modules, and the reactive refs are properly initialized for the Composition API.
36-56: LGTM! Task creation is well-implemented.The function includes proper input validation, helpful comments about transactions, correct use of
unique()for auto-generated IDs, and appropriate error handling. The pattern of clearing input and re-fetching after creation ensures the UI stays in sync.
58-58: LGTM! Lifecycle hook correctly fetches initial data.The
onMountedhook appropriately triggers the initial data fetch when the component mounts.
| @@ -0,0 +1,13 @@ | |||
| <!DOCTYPE html> | |||
| <html lang=""> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify a language code in the lang attribute.
The lang attribute is empty, which can affect accessibility and SEO. Please specify an appropriate language code (e.g., lang="en" for English).
Apply this diff:
-<html lang="">
+<html lang="en">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <html lang=""> | |
| <html lang="en"> |
🤖 Prompt for AI Agents
In example-database/index.html around line 2, the <html> tag has an empty lang
attribute which harms accessibility and SEO; update the tag to include the
correct language code (e.g., set lang="en" for English or another appropriate
BCP 47 code) so the root element declares the document language.
| "@vitejs/plugin-vue": "^6.0.1", | ||
| "vite": "^7.1.12", | ||
| "vite-plugin-vue-devtools": "^8.0.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify the Vite and related package versions.
The specified Vite version (^7.1.12) and related packages (@vitejs/plugin-vue@^6.0.1, vite-plugin-vue-devtools@^8.0.3) should be verified to ensure they exist and are compatible.
Please search for the latest stable versions to confirm:
🌐 Web query:
What are the latest stable versions of Vite, @vitejs/plugin-vue, and vite-plugin-vue-devtools as of November 2025?
💡 Result:
As of November 4, 2025:
- Vite: 7.1.2. [1]
- @vitejs/plugin-vue: 6.0.1. [2]
- vite-plugin-vue-devtools: 7.6.5. [3]
Sources:
[1] npm package page for vite.
[2] npm package page for @vitejs/plugin-vue.
[3] npm package page for vite-plugin-vue-devtools.
Update package.json with correct package versions.
Vite's latest stable version is 7.1.2, not 7.1.12. @vitejs/plugin-vue is correctly specified at 6.0.1. However, vite-plugin-vue-devtools's latest stable version is 7.6.5, not 8.0.3.
Update lines 19-21 in example-database/package.json:
- Change
"vite": "^7.1.12"to"vite": "^7.1.2" - Change
"vite-plugin-vue-devtools": "^8.0.3"to"vite-plugin-vue-devtools": "^7.6.5"
🤖 Prompt for AI Agents
In example-database/package.json around lines 19 to 21, the package versions are
incorrect; change the "vite" dependency from "^7.1.12" to "^7.1.2" and change
"vite-plugin-vue-devtools" from "^8.0.3" to "^7.6.5" so the file specifies the
correct stable versions.
| - *table* are was called *collection* in appwrite <1.8. | ||
| - Further down you will see the *collectionId* attribute which corresponds to the *name* of the table. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix grammatical error.
Line 60 contains a grammatical error: "table are was called" should be "tables were called".
Apply this diff:
-- *table* are was called *collection* in appwrite <1.8.
+- *tables* were called *collections* in Appwrite <1.8.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - *table* are was called *collection* in appwrite <1.8. | |
| - Further down you will see the *collectionId* attribute which corresponds to the *name* of the table. | |
| - *tables* were called *collections* in Appwrite <1.8. | |
| - Further down you will see the *collectionId* attribute which corresponds to the *name* of the table. |
🤖 Prompt for AI Agents
In example-database/README.md around lines 60 to 61, fix the grammatical error
"table are was called" to "tables were called" so the sentence reads correctly;
update that phrase and ensure the surrounding sentence remains grammatically
correct and consistent with the following sentence about collectionId
corresponding to the table name.
| // Reactive copy for "done" state (optimistic UI) | ||
| const done = ref(!!props.data.done) | ||
| // Keep local stat synchronized with props, when parent is updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in code example to match Task.vue correction.
The comment has the same typo as in Task.vue line 21: "stat" should be "state".
Apply this diff:
-// Keep local stat synchronized with props, when parent is updated
+// Keep local state synchronized with props, when parent is updated📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Keep local stat synchronized with props, when parent is updated | |
| // Keep local state synchronized with props, when parent is updated |
🤖 Prompt for AI Agents
In example-database/README.md around line 218, the inline comment contains a
typo ("stat") that should match the fix in Task.vue: change "Keep local stat
synchronized with props, when parent is updated" to "Keep local state
synchronized with props, when parent is updated". Edit that single line to
replace "stat" with "state" and ensure punctuation/spacing remains consistent.
| ``` | ||
|
|
||
| ### 7) Add code for `deleteTask()` | ||
| See the `deleteTask` function above — it calls `appwrite.database.deleteDocument(collectionId, documentId)` then emits `refreshData` so the parent re-fetches tasks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify API signature documentation accuracy.
The description says deleteDocument(collectionId, documentId), but the code examples throughout the README show three parameters: deleteDocument(databaseId, tableName, documentId). Ensure this description matches the Appwrite 1.8.0 API.
🌐 Web query:
Appwrite 1.8.0 deleteDocument method signature
💡 Result:
Client SDK (Web/JS) — async call:
databases.deleteDocument({ databaseId: '<DATABASE_ID>', collectionId: '<COLLECTION_ID>', documentId: '<DOCUMENT_ID>', transactionId: '<TRANSACTION_ID>' }) . [1]
REST endpoint:
DELETE /v1/databases/{databaseId}/collections/{collectionId}/documents/{documentId} (optional JSON body: { "transactionId": "<TRANSACTION_ID>" }). [2]
Sources: Appwrite docs (Client — Databases) [1]; REST Databases reference [2].
Fix deleteDocument API signature in README documentation.
The description on line 259 is incomplete—it shows deleteDocument(collectionId, documentId) but Appwrite 1.8.0 requires deleteDocument({ databaseId: '<DATABASE_ID>', collectionId: '<COLLECTION_ID>', documentId: '<DOCUMENT_ID>', ... }). Additionally, the code examples use "tableName" as a parameter, but the actual parameter name is collectionId. Update the description and code examples to match the correct Appwrite 1.8.0 API signature with all required parameters: databaseId, collectionId, and documentId.
🤖 Prompt for AI Agents
In example-database/README.md around line 259, the deleteDocument call is
documented incorrectly as deleteDocument(collectionId, documentId) and examples
use "tableName"; update the text and all code examples to match Appwrite 1.8.0
by using the object signature deleteDocument({ databaseId: '<DATABASE_ID>',
collectionId: '<COLLECTION_ID>', documentId: '<DOCUMENT_ID>' }) and replace any
"tableName" parameter names with "collectionId"; ensure examples include
databaseId, collectionId, and documentId fields and any optional params follow
the same object form.
| } | ||
| <template> | ||
| <div class="TaskCore"> | ||
| <h1>Appwrite TO-DO List</h1><div v-for="data in tasks" :key="data.$id || data.task"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential key uniqueness issue with fallback.
The key binding uses data.$id || data.task, which could cause Vue rendering issues if multiple tasks have the same name and no $id. Since Appwrite assigns a unique $id to all documents, the fallback should never be needed.
Consider simplifying to:
- <div v-for="data in tasks" :key="data.$id || data.task">
+ <div v-for="data in tasks" :key="data.$id">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <h1>Appwrite TO-DO List</h1><div v-for="data in tasks" :key="data.$id || data.task"> | |
| <h1>Appwrite TO-DO List</h1><div v-for="data in tasks" :key="data.$id"> |
🤖 Prompt for AI Agents
In example-database/src/App.vue around line 3, the v-for key uses `data.$id ||
data.task` which can produce non-unique keys if `$id` is missing and multiple
tasks share the same name; since Appwrite always provides a unique `$id`, remove
the fallback and use only `data.$id` as the key to guarantee uniqueness and
avoid rendering issues.
| // Reactive copy for "done" state (optimistic UI) | ||
| const done = ref(!!props.data.done) | ||
| // Keep local stat synchronized with props, when parent is updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in comment.
The comment says "Keep local stat synchronized" but should say "Keep local state synchronized".
Apply this diff:
-// Keep local stat synchronized with props, when parent is updated
+// Keep local state synchronized with props, when parent is updated📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Keep local stat synchronized with props, when parent is updated | |
| // Keep local state synchronized with props, when parent is updated |
🤖 Prompt for AI Agents
In example-database/src/components/Task.vue around line 21, the inline comment
contains a typo "stat" — update the comment to read "Keep local state
synchronized with props, when parent is updated" (replace "stat" with "state")
so the comment is correct and clear.
| // Get the secrets credentials from .env file to a structured object | ||
| export const SECRETS = { | ||
| DB:{ | ||
| endpoint : import.meta.env.VITE_DB_ENDPOINT, | ||
| projectId : import.meta.env.VITE_DB_PROJECTID, | ||
| databaseId : import.meta.env.VITE_DB_DATABASEID, | ||
| tableName : import.meta.env.VITE_DB_TABLENAME, | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation for required environment variables.
The environment variables are read without validation. If any VITE_DB_* variables are missing or undefined, the application will fail at runtime when attempting to configure the Appwrite client in utils.js.
Consider adding validation:
// Get the secrets credentials from .env file to a structured object
+const requiredEnvVars = ['VITE_DB_ENDPOINT', 'VITE_DB_PROJECTID', 'VITE_DB_DATABASEID', 'VITE_DB_TABLENAME']
+const missingVars = requiredEnvVars.filter(v => !import.meta.env[v])
+if (missingVars.length > 0) {
+ throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`)
+}
+
export const SECRETS = {
DB:{
endpoint : import.meta.env.VITE_DB_ENDPOINT,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Get the secrets credentials from .env file to a structured object | |
| export const SECRETS = { | |
| DB:{ | |
| endpoint : import.meta.env.VITE_DB_ENDPOINT, | |
| projectId : import.meta.env.VITE_DB_PROJECTID, | |
| databaseId : import.meta.env.VITE_DB_DATABASEID, | |
| tableName : import.meta.env.VITE_DB_TABLENAME, | |
| } | |
| } | |
| // Get the secrets credentials from .env file to a structured object | |
| const requiredEnvVars = ['VITE_DB_ENDPOINT', 'VITE_DB_PROJECTID', 'VITE_DB_DATABASEID', 'VITE_DB_TABLENAME'] | |
| const missingVars = requiredEnvVars.filter(v => !import.meta.env[v]) | |
| if (missingVars.length > 0) { | |
| throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`) | |
| } | |
| export const SECRETS = { | |
| DB:{ | |
| endpoint : import.meta.env.VITE_DB_ENDPOINT, | |
| projectId : import.meta.env.VITE_DB_PROJECTID, | |
| databaseId : import.meta.env.VITE_DB_DATABASEID, | |
| tableName : import.meta.env.VITE_DB_TABLENAME, | |
| } | |
| } |
🤖 Prompt for AI Agents
In example-database/src/secrets.js around lines 1 to 9, the VITE_DB_* values are
read directly from import.meta.env with no validation; add a validation step
that enumerates the required keys (VITE_DB_ENDPOINT, VITE_DB_PROJECTID,
VITE_DB_DATABASEID, VITE_DB_TABLENAME), checks each import.meta.env entry is
present and non-empty, and if any are missing throw a clear, early Error listing
the missing variables; after validation export a structured SECRETS object built
from the validated values so downstream code never sees undefined values.
What does this PR do?
It update the directory "example-database" to be used with Vue 3 and Appwrite 1.8
The changes consist of :
Test Plan
All of this is described in README
Launch the Vue server as usual
Run the URL provided by the Vue command response, and verify the app is running well
Related PRs and Issues
None
Others
I would like to refactor the remaining directories examples to do ;-)
Summary by CodeRabbit
Chores
Documentation